From 0478ead3f80aa7e798d2218ddb1b4a86edac78fb Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:50:41 +0200 Subject: [PATCH] Handle signature() for more libcalls (#6174) * Handle signature() for more libcalls This is necessary to be able to call them in the interpreter. All the remaining libcalls which signature() doesn't handle are never used in clif ir. Only in code compiled by a backend. * Fix libcall declarations in cranelift-frontend * Add function signatures * Use correct pointer type instead of I64 --- cranelift/codegen/src/ir/libcall.rs | 37 ++++++++++++++++----- cranelift/codegen/src/isa/x64/lower.rs | 2 +- cranelift/codegen/src/isa/x64/lower/isle.rs | 4 +-- cranelift/frontend/src/frontend.rs | 31 +++++++++-------- cranelift/fuzzgen/src/function_generator.rs | 6 +++- cranelift/interpreter/src/state.rs | 7 ++-- 6 files changed, 57 insertions(+), 30 deletions(-) diff --git a/cranelift/codegen/src/ir/libcall.rs b/cranelift/codegen/src/ir/libcall.rs index 6734258ed7..e6b2d539d0 100644 --- a/cranelift/codegen/src/ir/libcall.rs +++ b/cranelift/codegen/src/ir/libcall.rs @@ -1,7 +1,7 @@ //! Naming well-known routines in the runtime library. use crate::{ - ir::{types, AbiParam, ExternalName, FuncRef, Function, Signature}, + ir::{types, AbiParam, ExternalName, FuncRef, Function, Signature, Type}, isa::CallConv, }; use core::fmt; @@ -119,7 +119,7 @@ impl LibCall { } /// Get a [Signature] for the function targeted by this [LibCall]. - pub fn signature(&self, call_conv: CallConv) -> Signature { + pub fn signature(&self, call_conv: CallConv, pointer_type: Type) -> Signature { use types::*; let mut sig = Signature::new(call_conv); @@ -140,13 +140,32 @@ impl LibCall { sig.params.push(AbiParam::new(ty)); sig.returns.push(AbiParam::new(ty)); } - LibCall::Probestack - | LibCall::Memcpy - | LibCall::Memset - | LibCall::Memmove - | LibCall::Memcmp - | LibCall::ElfTlsGetAddr - | LibCall::ElfTlsGetOffset => unimplemented!(), + LibCall::Memcpy | LibCall::Memmove => { + // void* memcpy(void *dest, const void *src, size_t count); + // void* memmove(void* dest, const void* src, size_t count); + sig.params.push(AbiParam::new(pointer_type)); + sig.params.push(AbiParam::new(pointer_type)); + sig.params.push(AbiParam::new(pointer_type)); + sig.returns.push(AbiParam::new(pointer_type)); + } + LibCall::Memset => { + // void *memset(void *dest, int ch, size_t count); + sig.params.push(AbiParam::new(pointer_type)); + sig.params.push(AbiParam::new(I32)); + sig.params.push(AbiParam::new(pointer_type)); + sig.returns.push(AbiParam::new(pointer_type)); + } + LibCall::Memcmp => { + // void* memcpy(void *dest, const void *src, size_t count); + sig.params.push(AbiParam::new(pointer_type)); + sig.params.push(AbiParam::new(pointer_type)); + sig.params.push(AbiParam::new(pointer_type)); + sig.returns.push(AbiParam::new(I32)) + } + + LibCall::Probestack | LibCall::ElfTlsGetAddr | LibCall::ElfTlsGetOffset => { + unimplemented!() + } } sig diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index bd3b6e8dcd..d40eaecdc4 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -150,7 +150,7 @@ fn emit_vm_call( // TODO avoid recreating signatures for every single Libcall function. let call_conv = CallConv::for_libcall(flags, CallConv::triple_default(triple)); - let sig = libcall.signature(call_conv); + let sig = libcall.signature(call_conv, types::I64); let caller_conv = ctx.abi().call_conv(ctx.sigs()); if !ctx.sigs().have_abi_sig_for_signature(&sig) { diff --git a/cranelift/codegen/src/isa/x64/lower/isle.rs b/cranelift/codegen/src/isa/x64/lower/isle.rs index 1ca927ec31..bf328b5268 100644 --- a/cranelift/codegen/src/isa/x64/lower/isle.rs +++ b/cranelift/codegen/src/isa/x64/lower/isle.rs @@ -629,7 +629,7 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> { fn libcall_1(&mut self, libcall: &LibCall, a: Reg) -> Reg { let call_conv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()); - let ret_ty = libcall.signature(call_conv).returns[0].value_type; + let ret_ty = libcall.signature(call_conv, I64).returns[0].value_type; let output_reg = self.lower_ctx.alloc_tmp(ret_ty).only_reg().unwrap(); emit_vm_call( @@ -647,7 +647,7 @@ impl Context for IsleContext<'_, '_, MInst, X64Backend> { fn libcall_3(&mut self, libcall: &LibCall, a: Reg, b: Reg, c: Reg) -> Reg { let call_conv = self.lower_ctx.abi().call_conv(self.lower_ctx.sigs()); - let ret_ty = libcall.signature(call_conv).returns[0].value_type; + let ret_ty = libcall.signature(call_conv, I64).returns[0].value_type; let output_reg = self.lower_ctx.alloc_tmp(ret_ty).only_reg().unwrap(); emit_vm_call( diff --git a/cranelift/frontend/src/frontend.rs b/cranelift/frontend/src/frontend.rs index ecef10ba76..631f6ba8cb 100644 --- a/cranelift/frontend/src/frontend.rs +++ b/cranelift/frontend/src/frontend.rs @@ -753,6 +753,7 @@ impl<'a> FunctionBuilder<'a> { s.params.push(AbiParam::new(pointer_type)); s.params.push(AbiParam::new(pointer_type)); s.params.push(AbiParam::new(pointer_type)); + s.returns.push(AbiParam::new(pointer_type)); self.import_signature(s) }; @@ -853,6 +854,7 @@ impl<'a> FunctionBuilder<'a> { s.params.push(AbiParam::new(pointer_type)); s.params.push(AbiParam::new(types::I32)); s.params.push(AbiParam::new(pointer_type)); + s.returns.push(AbiParam::new(pointer_type)); self.import_signature(s) }; @@ -949,6 +951,7 @@ impl<'a> FunctionBuilder<'a> { s.params.push(AbiParam::new(pointer_type)); s.params.push(AbiParam::new(pointer_type)); s.params.push(AbiParam::new(pointer_type)); + s.returns.push(AbiParam::new(pointer_type)); self.import_signature(s) }; @@ -1283,15 +1286,15 @@ mod tests { check( &func, "function %sample() -> i32 system_v { - sig0 = (i64, i64, i64) system_v + sig0 = (i64, i64, i64) -> i64 system_v fn0 = %Memcpy sig0 block0: + v4 = iconst.i64 0 + v1 -> v4 v3 = iconst.i64 0 - v1 -> v3 - v2 = iconst.i64 0 - v0 -> v2 - call fn0(v1, v0, v1) ; v1 = 0, v0 = 0, v1 = 0 + v0 -> v3 + v2 = call fn0(v1, v0, v1) ; v1 = 0, v0 = 0, v1 = 0 return v1 ; v1 = 0 } ", @@ -1393,16 +1396,16 @@ block0: check( &func, "function %sample() -> i32 system_v { - sig0 = (i64, i64, i64) system_v + sig0 = (i64, i64, i64) -> i64 system_v fn0 = %Memcpy sig0 block0: + v5 = iconst.i64 0 + v1 -> v5 v4 = iconst.i64 0 - v1 -> v4 - v3 = iconst.i64 0 - v0 -> v3 + v0 -> v4 v2 = iconst.i64 8192 - call fn0(v1, v0, v2) ; v1 = 0, v0 = 0, v2 = 8192 + v3 = call fn0(v1, v0, v2) ; v1 = 0, v0 = 0, v2 = 8192 return v1 ; v1 = 0 } ", @@ -1478,16 +1481,16 @@ block0: check( &func, "function %sample() -> i32 system_v { - sig0 = (i64, i32, i64) system_v + sig0 = (i64, i32, i64) -> i64 system_v fn0 = %Memset sig0 block0: - v4 = iconst.i64 0 - v0 -> v4 + v5 = iconst.i64 0 + v0 -> v5 v1 = iconst.i8 1 v2 = iconst.i64 8192 v3 = uextend.i32 v1 ; v1 = 1 - call fn0(v0, v3, v2) ; v0 = 0, v2 = 8192 + v4 = call fn0(v0, v3, v2) ; v0 = 0, v2 = 8192 return v0 ; v0 = 0 } ", diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs index 52f89db231..a6e28b73b8 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -1863,7 +1863,11 @@ where .libcalls .iter() .map(|libcall| { - let signature = libcall.signature(lib_callconv); + let pointer_type = Type::int_with_byte_size( + self.target_triple.pointer_width().unwrap().bytes().into(), + ) + .unwrap(); + let signature = libcall.signature(lib_callconv, pointer_type); let name = ExternalName::LibCall(*libcall); (name, signature) }) diff --git a/cranelift/interpreter/src/state.rs b/cranelift/interpreter/src/state.rs index 6e01d4b943..5c5d7a685b 100644 --- a/cranelift/interpreter/src/state.rs +++ b/cranelift/interpreter/src/state.rs @@ -5,8 +5,8 @@ use crate::frame::Frame; use crate::interpreter::LibCallHandler; use cranelift_codegen::data_value::DataValue; use cranelift_codegen::ir::{ - ExternalName, FuncRef, Function, GlobalValue, LibCall, MemFlags, Signature, StackSlot, Type, - Value, + types, ExternalName, FuncRef, Function, GlobalValue, LibCall, MemFlags, Signature, StackSlot, + Type, Value, }; use cranelift_codegen::isa::CallConv; use smallvec::SmallVec; @@ -96,7 +96,8 @@ impl<'a> InterpreterFunctionRef<'a> { match self { InterpreterFunctionRef::Function(f) => f.stencil.signature.clone(), // CallConv here is sort of irrelevant, since we don't use it for anything - InterpreterFunctionRef::LibCall(lc) => lc.signature(CallConv::SystemV), + // FIXME handle non-64bit systems + InterpreterFunctionRef::LibCall(lc) => lc.signature(CallConv::SystemV, types::I64), } } }