Skip to content

Commit

Permalink
Merge #2060
Browse files Browse the repository at this point in the history
2060: Add align, nofree and nonnull to vmctx pointer. Dereferenceable is still TODO. r=nlewycky a=nlewycky

This gives LLVM more information about the vmctx pointer which it can use for better code generation and faster reasoning while compiling.


Co-authored-by: Nick Lewycky <[email protected]>
Co-authored-by: nlewycky <[email protected]>
  • Loading branch information
bors[bot] and nlewycky authored Jan 26, 2021
2 parents ff237fb + 9b63855 commit dabc454
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 54 deletions.
80 changes: 54 additions & 26 deletions lib/compiler-llvm/src/abi/aarch64_systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

Expand Down Expand Up @@ -47,19 +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 = |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::<wasmer_vm::VMContext>()
.try_into()
.unwrap(),
),
AttributeLoc::Param(i),
),
]
};

Ok(match sig.results() {
[] => (
intrinsics
.void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[_] => {
let single_value = sig.results()[0];
(
type_to_llvm(intrinsics, single_value)?
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[Type::F32, Type::F32] => {
Expand All @@ -68,7 +92,7 @@ impl Abi for Aarch64SystemV {
context
.struct_type(&[f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[Type::F64, Type::F64] => {
Expand All @@ -77,7 +101,7 @@ impl Abi for Aarch64SystemV {
context
.struct_type(&[f64_ty, f64_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[Type::F32, Type::F32, Type::F32] => {
Expand All @@ -86,7 +110,7 @@ impl Abi for Aarch64SystemV {
context
.struct_type(&[f32_ty, f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[Type::F32, Type::F32, Type::F32, Type::F32] => {
Expand All @@ -95,7 +119,7 @@ impl Abi for Aarch64SystemV {
context
.struct_type(&[f32_ty, f32_ty, f32_ty, f32_ty], false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
_ => {
Expand All @@ -115,7 +139,7 @@ impl Abi for Aarch64SystemV {
intrinsics
.i64_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[32, 64]
| [64, 32]
Expand All @@ -128,7 +152,7 @@ impl Abi for Aarch64SystemV {
.i64_ty
.array_type(2)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
_ => {
let basic_types: Vec<_> = sig
Expand All @@ -144,17 +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(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![(
context.create_enum_attribute(
Attribute::get_named_enum_kind_id("sret"),
0,
),
AttributeLoc::Param(0),
)],
attributes,
)
}
}
Expand Down Expand Up @@ -393,17 +420,18 @@ impl Abi for Aarch64SystemV {
})
.collect::<Result<Vec<i32>, _>>()?;

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>(
Expand Down
79 changes: 54 additions & 25 deletions lib/compiler-llvm/src/abi/x86_64_systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

Expand Down Expand Up @@ -50,6 +52,29 @@ 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 = |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::<wasmer_vm::VMContext>()
.try_into()
.unwrap(),
),
AttributeLoc::Param(i),
),
]
};

let sig_returns_bitwidths = sig
.results()
.iter()
Expand All @@ -67,14 +92,14 @@ impl Abi for X86_64SystemV {
intrinsics
.void_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[_] => {
let single_value = sig.results()[0];
(
type_to_llvm(intrinsics, single_value)?
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[32, 64] | [64, 32] | [64, 64] => {
Expand All @@ -88,21 +113,21 @@ impl Abi for X86_64SystemV {
context
.struct_type(&basic_types, false)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
)
}
[32, 32] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => (
intrinsics
.f32_ty
.vec_type(2)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[32, 32] => (
intrinsics
.i64_ty
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[32, 32, _] if sig.results()[0] == Type::F32 && sig.results()[1] == Type::F32 => (
context
Expand All @@ -114,7 +139,7 @@ impl Abi for X86_64SystemV {
false,
)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[32, 32, _] => (
context
Expand All @@ -126,7 +151,7 @@ impl Abi for X86_64SystemV {
false,
)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[64, 32, 32] if sig.results()[1] == Type::F32 && sig.results()[2] == Type::F32 => (
context
Expand All @@ -138,7 +163,7 @@ impl Abi for X86_64SystemV {
false,
)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[64, 32, 32] => (
context
Expand All @@ -150,7 +175,7 @@ impl Abi for X86_64SystemV {
false,
)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
[32, 32, 32, 32] => (
context
Expand All @@ -170,7 +195,7 @@ impl Abi for X86_64SystemV {
false,
)
.fn_type(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![],
vmctx_attributes(0),
),
_ => {
let basic_types: Vec<_> = sig
Expand All @@ -185,14 +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(&param_types.collect::<Result<Vec<_>, _>>()?, false),
vec![(
context.create_enum_attribute(Attribute::get_named_enum_kind_id("sret"), 0),
AttributeLoc::Param(0),
)],
attributes,
)
}
})
Expand Down Expand Up @@ -447,17 +475,18 @@ impl Abi for X86_64SystemV {
})
.collect::<Result<Vec<i32>, _>>()?;

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>(
Expand Down
3 changes: 0 additions & 3 deletions lib/compiler-llvm/src/translator/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit dabc454

Please sign in to comment.