From 799f1fde66e68686afb675320ec89d0e07412398 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 26 Jan 2021 10:49:09 -0800 Subject: [PATCH 1/2] Add align, nofree and nonnull to vmctx pointer. Adding dereferenceable is still TODO. --- lib/compiler-llvm/src/abi/aarch64_systemv.rs | 85 +++++++++++++---- lib/compiler-llvm/src/abi/x86_64_systemv.rs | 96 +++++++++++++++----- lib/compiler-llvm/src/translator/code.rs | 3 - 3 files changed, 139 insertions(+), 45 deletions(-) diff --git a/lib/compiler-llvm/src/abi/aarch64_systemv.rs b/lib/compiler-llvm/src/abi/aarch64_systemv.rs index c4a5fc36ebb..4d55b3ce894 100644 --- a/lib/compiler-llvm/src/abi/aarch64_systemv.rs +++ b/lib/compiler-llvm/src/abi/aarch64_systemv.rs @@ -11,6 +11,8 @@ use inkwell::{ use wasmer_compiler::CompileError; use wasmer_types::{FunctionType as FuncSig, Type}; +use std::convert::TryInto; + /// Implementation of the [`Abi`] trait for the Aarch64 ABI on Linux. pub struct Aarch64SystemV {} @@ -47,19 +49,36 @@ impl Abi for Aarch64SystemV { let param_types = std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); + let vmctx_attributes = vec![ + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), + context.create_enum_attribute( + Attribute::get_named_enum_kind_id("align"), + std::mem::align_of::() + .try_into() + .unwrap(), + ), + ]; + Ok(match sig.results() { [] => ( intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [_] => { let single_value = sig.results()[0]; ( type_to_llvm(intrinsics, single_value)? .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [Type::F32, Type::F32] => { @@ -68,7 +87,10 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [Type::F64, Type::F64] => { @@ -77,7 +99,10 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f64_ty, f64_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [Type::F32, Type::F32, Type::F32] => { @@ -86,7 +111,10 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [Type::F32, Type::F32, Type::F32, Type::F32] => { @@ -95,7 +123,10 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty, f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } _ => { @@ -115,7 +146,10 @@ impl Abi for Aarch64SystemV { intrinsics .i64_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [32, 64] | [64, 32] @@ -128,7 +162,10 @@ impl Abi for Aarch64SystemV { .i64_ty .array_type(2) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), _ => { let basic_types: Vec<_> = sig @@ -154,7 +191,14 @@ impl Abi for Aarch64SystemV { 0, ), AttributeLoc::Param(0), - )], + )] + .into_iter() + .chain( + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(1))), + ) + .collect(), ) } } @@ -393,17 +437,18 @@ impl Abi for Aarch64SystemV { }) .collect::, _>>()?; - Ok(!matches!(func_sig_returns_bitwidths.as_slice(), - [] - | [_] - | [32, 32] - | [32, 64] - | [64, 32] - | [64, 64] - | [32, 32, 32] - | [32, 32, 64] - | [64, 32, 32] - | [32, 32, 32, 32])) + Ok(!matches!( + func_sig_returns_bitwidths.as_slice(), + [] | [_] + | [32, 32] + | [32, 64] + | [64, 32] + | [64, 64] + | [32, 32, 32] + | [32, 32, 64] + | [64, 32, 32] + | [32, 32, 32, 32] + )) } fn pack_values_for_register_return<'ctx>( diff --git a/lib/compiler-llvm/src/abi/x86_64_systemv.rs b/lib/compiler-llvm/src/abi/x86_64_systemv.rs index a6fd67622c7..3da58e5d567 100644 --- a/lib/compiler-llvm/src/abi/x86_64_systemv.rs +++ b/lib/compiler-llvm/src/abi/x86_64_systemv.rs @@ -14,6 +14,8 @@ use inkwell::{ use wasmer_compiler::CompileError; use wasmer_types::{FunctionType as FuncSig, Type}; +use std::convert::TryInto; + /// Implementation of the [`Abi`] trait for the AMD64 SystemV ABI. pub struct X86_64SystemV {} @@ -50,6 +52,18 @@ impl Abi for X86_64SystemV { let param_types = std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); + // TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.) + let vmctx_attributes = vec![ + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), + context.create_enum_attribute( + Attribute::get_named_enum_kind_id("align"), + std::mem::align_of::() + .try_into() + .unwrap(), + ), + ]; + let sig_returns_bitwidths = sig .results() .iter() @@ -67,14 +81,20 @@ impl Abi for X86_64SystemV { intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [_] => { let single_value = sig.results()[0]; ( type_to_llvm(intrinsics, single_value)? .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [32, 64] | [64, 32] | [64, 64] => { @@ -88,7 +108,10 @@ impl Abi for X86_64SystemV { context .struct_type(&basic_types, false) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ) } [32, 32] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( @@ -96,13 +119,19 @@ impl Abi for X86_64SystemV { .f32_ty .vec_type(2) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [32, 32] => ( intrinsics .i64_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [32, 32, _] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( context @@ -114,7 +143,10 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [32, 32, _] => ( context @@ -126,7 +158,10 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [64, 32, 32] if sig.results()[1] == Type::F32 && sig.results()[2] == Type::F32 => ( context @@ -138,7 +173,10 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [64, 32, 32] => ( context @@ -150,7 +188,10 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), [32, 32, 32, 32] => ( context @@ -170,7 +211,10 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vec![], + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(0))) + .collect(), ), _ => { let basic_types: Vec<_> = sig @@ -192,7 +236,14 @@ impl Abi for X86_64SystemV { vec![( context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0), AttributeLoc::Param(0), - )], + )] + .into_iter() + .chain( + vmctx_attributes + .into_iter() + .map(|x| (x, AttributeLoc::Param(1))), + ) + .collect(), ) } }) @@ -447,17 +498,18 @@ impl Abi for X86_64SystemV { }) .collect::, _>>()?; - Ok(!matches!(func_sig_returns_bitwidths.as_slice(), - [] - | [_] - | [32, 32] - | [32, 64] - | [64, 32] - | [64, 64] - | [32, 32, 32] - | [32, 32, 64] - | [64, 32, 32] - | [32, 32, 32, 32])) + Ok(!matches!( + func_sig_returns_bitwidths.as_slice(), + [] | [_] + | [32, 32] + | [32, 64] + | [64, 32] + | [64, 64] + | [32, 32, 32] + | [32, 32, 64] + | [64, 32, 32] + | [32, 32, 32, 32] + )) } fn pack_values_for_register_return<'ctx>( diff --git a/lib/compiler-llvm/src/translator/code.rs b/lib/compiler-llvm/src/translator/code.rs index 8e2c617c4f4..674f58507e1 100644 --- a/lib/compiler-llvm/src/translator/code.rs +++ b/lib/compiler-llvm/src/translator/code.rs @@ -111,9 +111,6 @@ impl FuncTranslator { func.add_attribute(*attr_loc, *attr); } - // TODO: mark vmctx align 16 - // TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.) - // TODO: mark vmctx nofree func.add_attribute(AttributeLoc::Function, intrinsics.stack_probe); func.set_personality_function(intrinsics.personality); func.as_global_value().set_section(FUNCTION_SECTION); From a79a8ed79c5d495a2bfdbe5e6db13d21b506bdc6 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Tue, 26 Jan 2021 11:17:13 -0800 Subject: [PATCH 2/2] Refactor duplicate code for vmctx attributes. --- lib/compiler-llvm/src/abi/aarch64_systemv.rs | 95 ++++++++----------- lib/compiler-llvm/src/abi/x86_64_systemv.rs | 99 ++++++++------------ 2 files changed, 77 insertions(+), 117 deletions(-) diff --git a/lib/compiler-llvm/src/abi/aarch64_systemv.rs b/lib/compiler-llvm/src/abi/aarch64_systemv.rs index 4d55b3ce894..329d4ea8cad 100644 --- a/lib/compiler-llvm/src/abi/aarch64_systemv.rs +++ b/lib/compiler-llvm/src/abi/aarch64_systemv.rs @@ -49,36 +49,41 @@ impl Abi for Aarch64SystemV { let param_types = std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); - let vmctx_attributes = vec![ - context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), - context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), - context.create_enum_attribute( - Attribute::get_named_enum_kind_id("align"), - std::mem::align_of::() - .try_into() - .unwrap(), - ), - ]; + let vmctx_attributes = |i: u32| { + vec![ + ( + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), + AttributeLoc::Param(i), + ), + ( + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), + AttributeLoc::Param(i), + ), + ( + context.create_enum_attribute( + Attribute::get_named_enum_kind_id("align"), + std::mem::align_of::() + .try_into() + .unwrap(), + ), + AttributeLoc::Param(i), + ), + ] + }; Ok(match sig.results() { [] => ( intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [_] => { let single_value = sig.results()[0]; ( type_to_llvm(intrinsics, single_value)? .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [Type::F32, Type::F32] => { @@ -87,10 +92,7 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [Type::F64, Type::F64] => { @@ -99,10 +101,7 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f64_ty, f64_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [Type::F32, Type::F32, Type::F32] => { @@ -111,10 +110,7 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [Type::F32, Type::F32, Type::F32, Type::F32] => { @@ -123,10 +119,7 @@ impl Abi for Aarch64SystemV { context .struct_type(&[f32_ty, f32_ty, f32_ty, f32_ty], false) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } _ => { @@ -146,10 +139,7 @@ impl Abi for Aarch64SystemV { intrinsics .i64_ty .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [32, 64] | [64, 32] @@ -162,10 +152,7 @@ impl Abi for Aarch64SystemV { .i64_ty .array_type(2) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), _ => { let basic_types: Vec<_> = sig @@ -181,24 +168,20 @@ impl Abi for Aarch64SystemV { let param_types = std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types); + let mut attributes = vec![( + context.create_enum_attribute( + Attribute::get_named_enum_kind_id("sret"), + 0, + ), + AttributeLoc::Param(0), + )]; + attributes.append(&mut vmctx_attributes(1)); + ( intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![( - context.create_enum_attribute( - Attribute::get_named_enum_kind_id("sret"), - 0, - ), - AttributeLoc::Param(0), - )] - .into_iter() - .chain( - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(1))), - ) - .collect(), + attributes, ) } } diff --git a/lib/compiler-llvm/src/abi/x86_64_systemv.rs b/lib/compiler-llvm/src/abi/x86_64_systemv.rs index 3da58e5d567..799d20056e9 100644 --- a/lib/compiler-llvm/src/abi/x86_64_systemv.rs +++ b/lib/compiler-llvm/src/abi/x86_64_systemv.rs @@ -53,16 +53,27 @@ impl Abi for X86_64SystemV { std::iter::once(Ok(intrinsics.ctx_ptr_ty.as_basic_type_enum())).chain(user_param_types); // TODO: figure out how many bytes long vmctx is, and mark it dereferenceable. (no need to mark it nonnull once we do this.) - let vmctx_attributes = vec![ - context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), - context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), - context.create_enum_attribute( - Attribute::get_named_enum_kind_id("align"), - std::mem::align_of::() - .try_into() - .unwrap(), - ), - ]; + let vmctx_attributes = |i: u32| { + vec![ + ( + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nofree"), 0), + AttributeLoc::Param(i), + ), + ( + context.create_enum_attribute(Attribute::get_named_enum_kind_id("nonnull"), 0), + AttributeLoc::Param(i), + ), + ( + context.create_enum_attribute( + Attribute::get_named_enum_kind_id("align"), + std::mem::align_of::() + .try_into() + .unwrap(), + ), + AttributeLoc::Param(i), + ), + ] + }; let sig_returns_bitwidths = sig .results() @@ -81,20 +92,14 @@ impl Abi for X86_64SystemV { intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [_] => { let single_value = sig.results()[0]; ( type_to_llvm(intrinsics, single_value)? .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [32, 64] | [64, 32] | [64, 64] => { @@ -108,10 +113,7 @@ impl Abi for X86_64SystemV { context .struct_type(&basic_types, false) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ) } [32, 32] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( @@ -119,19 +121,13 @@ impl Abi for X86_64SystemV { .f32_ty .vec_type(2) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [32, 32] => ( intrinsics .i64_ty .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [32, 32, _] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => ( context @@ -143,10 +139,7 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [32, 32, _] => ( context @@ -158,10 +151,7 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [64, 32, 32] if sig.results()[1] == Type::F32 && sig.results()[2] == Type::F32 => ( context @@ -173,10 +163,7 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [64, 32, 32] => ( context @@ -188,10 +175,7 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), [32, 32, 32, 32] => ( context @@ -211,10 +195,7 @@ impl Abi for X86_64SystemV { false, ) .fn_type(¶m_types.collect::, _>>()?, false), - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(0))) - .collect(), + vmctx_attributes(0), ), _ => { let basic_types: Vec<_> = sig @@ -229,21 +210,17 @@ impl Abi for X86_64SystemV { let param_types = std::iter::once(Ok(sret.as_basic_type_enum())).chain(param_types); + let mut attributes = vec![( + context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0), + AttributeLoc::Param(0), + )]; + attributes.append(&mut vmctx_attributes(1)); + ( intrinsics .void_ty .fn_type(¶m_types.collect::, _>>()?, false), - vec![( - context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0), - AttributeLoc::Param(0), - )] - .into_iter() - .chain( - vmctx_attributes - .into_iter() - .map(|x| (x, AttributeLoc::Param(1))), - ) - .collect(), + attributes, ) } })