From 10cb0645b745970ea41f578ddccb8f7377e2ec55 Mon Sep 17 00:00:00 2001 From: Marius Wachtler Date: Mon, 16 Sep 2019 23:22:56 -0300 Subject: [PATCH] fix panic when encountering memcpy, memset, memove intrinsics when encountering the example below we rewrote the intrinsics name to e.g. "memcpy" but because this string was likely not yet in string table get_extname() asserted. Instead of manually creating the string table entries I decided to start moving to the ExternalName::LibCall functionality. I did not want to introduce an new dependency on cranelift-module (and also didn't want to add the `Box` everywhere) so instead I hardcoded the name of the three functions for now. ```llvm define dso_local void @foo(i8* nocapture readonly, i8* nocapture, i8* nocapture, i8* nocapture) local_unnamed_addr { tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* align 1 %0, i64 42, i1 false) tail call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 %2, i8* align 1 %0, i64 42, i1 false) tail call void @llvm.memset.p0i8.i64(i8* align 1 %3, i8 0, i64 42, i1 false) ret void } declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) ``` --- lib/llvm/src/operations.rs | 10 ++++++++-- lib/llvm/src/string_table.rs | 8 ++++++++ lib/llvm/src/translate.rs | 24 ++++++++++++++++-------- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/llvm/src/operations.rs b/lib/llvm/src/operations.rs index b7e6c12..ab2afdc 100644 --- a/lib/llvm/src/operations.rs +++ b/lib/llvm/src/operations.rs @@ -858,7 +858,13 @@ fn translate_mem_intrinsic( // start optimizing these libcalls. let args = [dst_arg, src_arg, len_arg]; - let funcname = strings.get_extname(name); + let libcall = match name { + "memcpy" => ir::LibCall::Memcpy, + "memmove" => ir::LibCall::Memmove, + "memset" => ir::LibCall::Memset, + _ => panic!("not handled {}", name) + }; + // TODO: Translate the calling convention. let mut sig = ir::Signature::new(CallConv::SystemV); sig.params.resize(3, ir::AbiParam::new(pointer_type)); @@ -868,7 +874,7 @@ fn translate_mem_intrinsic( sig.returns.resize(1, ir::AbiParam::new(pointer_type)); let signature = ctx.builder.import_signature(sig); let data = ir::ExtFuncData { - name: funcname, + name: ir::ExternalName::LibCall(libcall), signature, colocated: false, // TODO: Set the colocated flag based on the visibility. }; diff --git a/lib/llvm/src/string_table.rs b/lib/llvm/src/string_table.rs index dcbc1a2..679be7f 100644 --- a/lib/llvm/src/string_table.rs +++ b/lib/llvm/src/string_table.rs @@ -26,6 +26,14 @@ impl StringTable { .0 .as_str() } + ir::ExternalName::LibCall(libcall) => { + match libcall { + ir::LibCall::Memcpy => "memcpy", + ir::LibCall::Memmove => "memmove", + ir::LibCall::Memset => "memset", + _ => panic!("unhandled LibCall {}", libcall), + } + } _ => panic!("non-user names not yet implemented"), } } diff --git a/lib/llvm/src/translate.rs b/lib/llvm/src/translate.rs index 2e82ef9..945008d 100644 --- a/lib/llvm/src/translate.rs +++ b/lib/llvm/src/translate.rs @@ -103,14 +103,22 @@ pub fn translate_module( // Collect externally referenced symbols for the module. for func_ref in func.il.dfg.ext_funcs.keys() { let name = &func.il.dfg.ext_funcs[func_ref].name; - // If this function is defined inside the module, don't list it - // as an import. - let c_str = ffi::CString::new(result.strings.get_str(name)) - .map_err(|err| err.description().to_string())?; - let llvm_str = c_str.as_ptr(); - let llvm_func = unsafe { LLVMGetNamedFunction(llvm_mod, llvm_str) }; - if llvm_func.is_null() || unsafe { LLVMIsDeclaration(llvm_func) } != 0 { - result.imports.push((name.clone(), SymbolKind::Function)); + match name { + ir::ExternalName::User{..} => { + // If this function is defined inside the module, don't list it + // as an import. + let c_str = ffi::CString::new(result.strings.get_str(name)) + .map_err(|err| err.description().to_string())?; + let llvm_str = c_str.as_ptr(); + let llvm_func = unsafe { LLVMGetNamedFunction(llvm_mod, llvm_str) }; + if llvm_func.is_null() || unsafe { LLVMIsDeclaration(llvm_func) } != 0 { + result.imports.push((name.clone(), SymbolKind::Function)); + } + } + ir::ExternalName::LibCall{..} => { + result.imports.push((name.clone(), SymbolKind::Function)); + } + _ => panic!("unhandled: {}", name) } } for global_var in func.il.global_values.keys() {