Skip to content

Commit 916b79a

Browse files
committed
feat(llvm): Add the debug_str intrinsic function
..and add misc naming improvements.
1 parent d67154c commit 916b79a

File tree

7 files changed

+83
-26
lines changed

7 files changed

+83
-26
lines changed

lib/compiler-llvm/src/object_file.rs

+2
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ static LIBCALLS_ELF: phf::Map<&'static str, LibCall> = phf::phf_map! {
8484
"wasmer_vm_read_exception" => LibCall::ReadException,
8585
"wasmer_vm_dbg_usize" => LibCall::DebugUsize,
8686
"wasmer_eh_personality" => LibCall::EHPersonality,
87+
"wasmer_vm_dbg_str" => LibCall::DebugStr,
8788
};
8889

8990
static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
@@ -142,6 +143,7 @@ static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
142143
//
143144
// todo: find out if it is a bug in LLVM or it is expected.
144145
"___gxx_personality_v0" => LibCall::EHPersonality,
146+
"_wasmer_vm_dbg_str" => LibCall::DebugStr,
145147
};
146148

147149
pub fn load_object_file<F>(

lib/compiler-llvm/src/translator/code.rs

+52-25
Original file line numberDiff line numberDiff line change
@@ -213,34 +213,51 @@ impl FuncTranslator {
213213
1
214214
};
215215
let mut is_first_alloca = true;
216-
let mut insert_alloca = |ty, name| -> Result<PointerValue, CompileError> {
217-
let alloca = err!(alloca_builder.build_alloca(ty, name));
216+
let mut insert_alloca = |ty, name: String| -> Result<PointerValue, CompileError> {
217+
let alloca = err!(alloca_builder.build_alloca(ty, &name));
218218
if is_first_alloca {
219219
alloca_builder.position_at(entry, &alloca.as_instruction_value().unwrap());
220220
is_first_alloca = false;
221221
}
222222
Ok(alloca)
223223
};
224224

225+
// Uncomment to print, at the start of the function, the function name.
226+
// (poor man's debugger!)
227+
//let func_name_str =
228+
// err!(alloca_builder.build_global_string_ptr(&function_name, "function_name"));
229+
//
230+
//_ = alloca_builder.build_call(
231+
// intrinsics.debug_str,
232+
// &[
233+
// func_name_str.as_pointer_value().into(),
234+
// intrinsics
235+
// .i32_ty
236+
// .const_int(function_name.len() as _, false)
237+
// .into(),
238+
// ],
239+
// "",
240+
//);
241+
225242
for idx in 0..wasm_fn_type.params().len() {
226243
let ty = wasm_fn_type.params()[idx];
227244
let ty = type_to_llvm(&intrinsics, ty)?;
228245
let value = func
229246
.get_nth_param((idx as u32).checked_add(first_param).unwrap())
230247
.unwrap();
231-
let alloca = insert_alloca(ty, "param")?;
248+
let alloca = insert_alloca(ty, format!("param_{idx}"))?;
232249
err!(cache_builder.build_store(alloca, value));
233250
params.push((ty, alloca));
234251
}
235252

236253
let mut locals = vec![];
237254
let num_locals = reader.read_local_count()?;
238-
for _ in 0..num_locals {
255+
for idx in 0..num_locals {
239256
let (count, ty) = reader.read_local_decl()?;
240257
let ty = err!(wptype_to_type(ty));
241258
let ty = type_to_llvm(&intrinsics, ty)?;
242259
for _ in 0..count {
243-
let alloca = insert_alloca(ty, "local")?;
260+
let alloca = insert_alloca(ty, format!("local_{idx}"))?;
244261
err!(cache_builder.build_store(alloca, ty.const_zero()));
245262
locals.push((ty, alloca));
246263
}
@@ -253,7 +270,7 @@ impl FuncTranslator {
253270

254271
if g0m0_is_enabled {
255272
let value = self.abi.get_g0_ptr_param(&func);
256-
let g0 = insert_alloca(intrinsics.i32_ty.as_basic_type_enum(), "g0")?;
273+
let g0 = insert_alloca(intrinsics.i32_ty.as_basic_type_enum(), "g0".to_string())?;
257274
err!(cache_builder.build_store(g0, value));
258275
g0.set_name("g0");
259276
let m0 = self.abi.get_m0_ptr_param(&func);
@@ -1257,13 +1274,16 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
12571274
let ptr_in_bounds = match ptr_in_bounds {
12581275
Some(ptr) => ptr,
12591276
None => {
1260-
let load_offset_end =
1261-
err!(builder.build_int_add(offset, value_size_v, ""));
1277+
let load_offset_end = err!(builder.build_int_add(
1278+
offset,
1279+
value_size_v,
1280+
"load_offset_end"
1281+
));
12621282

12631283
let current_length = err!(builder.build_load(
12641284
self.intrinsics.i32_ty,
12651285
ptr_to_current_length,
1266-
""
1286+
"current_length"
12671287
))
12681288
.into_int_value();
12691289
tbaa_label(
@@ -1275,14 +1295,14 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
12751295
let current_length = err!(builder.build_int_z_extend(
12761296
current_length,
12771297
intrinsics.i64_ty,
1278-
""
1298+
"current_length_zextd"
12791299
));
12801300

12811301
err!(builder.build_int_compare(
12821302
IntPredicate::ULE,
12831303
load_offset_end,
12841304
current_length,
1285-
"",
1305+
"ptr_in_bounds",
12861306
))
12871307
}
12881308
};
@@ -1327,7 +1347,7 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
13271347
builder.position_at_end(in_bounds_continue_block);
13281348
}
13291349
let ptr_to_base =
1330-
err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, ""))
1350+
err!(builder.build_load(intrinsics.ptr_ty, ptr_to_base_ptr, "ptr_to_base"))
13311351
.into_pointer_value();
13321352
tbaa_label(
13331353
self.module,
@@ -1340,10 +1360,11 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
13401360
MemoryCache::Static { base_ptr } => base_ptr,
13411361
}
13421362
};
1343-
let value_ptr =
1344-
unsafe { err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "")) };
1363+
let value_ptr = unsafe {
1364+
err!(builder.build_gep(self.intrinsics.i8_ty, base_ptr, &[offset], "mem_value_ptr"))
1365+
};
13451366
err_nt!(builder
1346-
.build_bit_cast(value_ptr, ptr_ty, "")
1367+
.build_bit_cast(value_ptr, ptr_ty, "mem_value")
13471368
.map(|v| v.into_pointer_value()))
13481369
}
13491370

@@ -1356,9 +1377,10 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
13561377
if align <= 1 {
13571378
return Ok(());
13581379
}
1359-
let value = err!(self
1360-
.builder
1361-
.build_ptr_to_int(ptr, self.intrinsics.i64_ty, ""));
1380+
let value =
1381+
err!(self
1382+
.builder
1383+
.build_ptr_to_int(ptr, self.intrinsics.i64_ty, "mischeck_value"));
13621384
let and = err!(self.builder.build_and(
13631385
value,
13641386
self.intrinsics.i64_ty.const_int((align - 1).into(), false),
@@ -1368,15 +1390,15 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
13681390
IntPredicate::EQ,
13691391
and,
13701392
self.intrinsics.i64_zero,
1371-
""
1393+
"is_aligned"
13721394
));
13731395
let aligned = err!(self.builder.build_call(
13741396
self.intrinsics.expect_i1,
13751397
&[
13761398
aligned.into(),
13771399
self.intrinsics.i1_ty.const_int(1, false).into(),
13781400
],
1379-
"",
1401+
"is_aligned_expect",
13801402
))
13811403
.try_as_basic_value()
13821404
.left()
@@ -2583,7 +2605,11 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
25832605
// Operate on self.locals.
25842606
Operator::LocalGet { local_index } => {
25852607
let (type_value, pointer_value) = self.locals[local_index as usize];
2586-
let v = err!(self.builder.build_load(type_value, pointer_value, ""));
2608+
let v = err!(self.builder.build_load(
2609+
type_value,
2610+
pointer_value,
2611+
&format!("local_{local_index}_get")
2612+
));
25872613
tbaa_label(
25882614
self.module,
25892615
self.intrinsics,
@@ -10022,10 +10048,11 @@ impl<'ctx, 'a> LLVMFunctionCodeGenerator<'ctx, 'a> {
1002210048
4,
1002310049
)?;
1002410050
self.trap_if_misaligned(memarg, effective_address, 4)?;
10025-
let result =
10026-
err!(self
10027-
.builder
10028-
.build_load(self.intrinsics.i32_ty, effective_address, ""));
10051+
let result = err!(self.builder.build_load(
10052+
self.intrinsics.i32_ty,
10053+
effective_address,
10054+
"atomic_load"
10055+
));
1002910056
let load = result.as_instruction_value().unwrap();
1003010057
self.annotate_user_memaccess(memory_index, memarg, 4, load)?;
1003110058
load.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)

lib/compiler-llvm/src/translator/intrinsics.rs

+6
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ pub struct Intrinsics<'ctx> {
252252

253253
// Debug
254254
pub debug_ptr: FunctionValue<'ctx>,
255+
pub debug_str: FunctionValue<'ctx>,
255256

256257
// VM builtins.
257258
pub vmfunction_import_ty: StructType<'ctx>,
@@ -1041,6 +1042,11 @@ impl<'ctx> Intrinsics<'ctx> {
10411042
void_ty.fn_type(&[ptr_ty.into()], false),
10421043
None,
10431044
),
1045+
debug_str: module.add_function(
1046+
"wasmer_vm_dbg_str",
1047+
void_ty.fn_type(&[ptr_ty.into(), i32_ty.into()], false),
1048+
None,
1049+
),
10441050
memory_wait32: module.add_function(
10451051
"wasmer_vm_memory32_atomic_wait32",
10461052
i32_ty.fn_type(

lib/types/src/libcalls.rs

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ pub enum LibCall {
156156

157157
/// debug_usize
158158
DebugUsize,
159+
/// debug_str
160+
DebugStr,
159161
}
160162

161163
impl LibCall {
@@ -211,6 +213,7 @@ impl LibCall {
211213
Self::DeleteException => "wasmer_vm_delete_exception",
212214
Self::ReadException => "wasmer_vm_read_exception",
213215
Self::DebugUsize => "wasmer_vm_dbg_usize",
216+
Self::DebugStr => "wasmer_vm_dbg_str",
214217
}
215218
}
216219
}

lib/types/src/vmoffsets.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,14 @@ impl VMBuiltinFunctionIndex {
172172
Self(35)
173173
}
174174

175+
/// Returns an index for wasm's imported `debug_str` builtin function.
176+
pub const fn get_imported_debug_str_index() -> Self {
177+
Self(36)
178+
}
179+
175180
/// Returns the total number of builtin functions.
176181
pub const fn builtin_functions_total_number() -> u32 {
177-
36
182+
37
178183
}
179184

180185
/// Return the index as an u32 number.

lib/vm/src/libcalls.rs

+12
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,17 @@ pub extern "C-unwind" fn wasmer_vm_dbg_usize(value: usize) {
693693
}
694694
}
695695

696+
/// (debug) Print a string.
697+
#[no_mangle]
698+
pub extern "C-unwind" fn wasmer_vm_dbg_str(ptr: usize, len: u32) {
699+
#[allow(clippy::print_stdout)]
700+
unsafe {
701+
let str = std::str::from_utf8(std::slice::from_raw_parts(ptr as _, len as _))
702+
.unwrap_or("wasmer_vm_dbg_str failed");
703+
eprintln!("{str}");
704+
}
705+
}
706+
696707
/// Implementation for allocating an exception.
697708
#[no_mangle]
698709
pub extern "C-unwind" fn wasmer_vm_alloc_exception(size: usize) -> u64 {
@@ -936,5 +947,6 @@ pub fn function_pointer(libcall: LibCall) -> usize {
936947
LibCall::DeleteException => wasmer_vm_delete_exception as usize,
937948
LibCall::ReadException => wasmer_vm_read_exception as usize,
938949
LibCall::DebugUsize => wasmer_vm_dbg_usize as usize,
950+
LibCall::DebugStr => wasmer_vm_dbg_str as usize,
939951
}
940952
}

lib/vm/src/vmcontext.rs

+2
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ impl VMBuiltinFunctionsArray {
768768

769769
ptrs[VMBuiltinFunctionIndex::get_imported_debug_usize_index().index() as usize] =
770770
wasmer_vm_dbg_usize as usize;
771+
ptrs[VMBuiltinFunctionIndex::get_imported_debug_str_index().index() as usize] =
772+
wasmer_vm_dbg_str as usize;
771773

772774
debug_assert!(ptrs.iter().cloned().all(|p| p != 0));
773775

0 commit comments

Comments
 (0)