Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/compiler-llvm/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ impl LLVMCompiler {
let merged_bitcode = function_body_inputs.into_iter().par_bridge().map_init(
|| {
let target_machine = self.config().target_machine(target);
FuncTranslator::new(target_machine, binary_format).unwrap()
let pointer_width = target.triple().pointer_width().unwrap().bytes();
FuncTranslator::new(target_machine, binary_format, pointer_width).unwrap()
},
|func_translator, (i, input)| {
let module = func_translator.translate_to_module(
Expand Down Expand Up @@ -356,7 +357,8 @@ impl Compiler for LLVMCompiler {
.map_init(
|| {
let target_machine = self.config().target_machine(target);
FuncTranslator::new(target_machine, binary_format).unwrap()
let pointer_width = target.triple().pointer_width().unwrap().bytes();
FuncTranslator::new(target_machine, binary_format, pointer_width).unwrap()
},
|func_translator, (i, input)| {
// TODO: remove (to serialize)
Expand Down
93 changes: 39 additions & 54 deletions lib/compiler-llvm/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::compiler::LLVMCompiler;
use inkwell::targets::{
CodeModel, InitializationConfig, RelocMode, Target as InkwellTarget, TargetMachine,
TargetTriple,
TargetMachineOptions, TargetTriple,
};
pub use inkwell::OptimizationLevel as LLVMOptLevel;
use itertools::Itertools;
Expand Down Expand Up @@ -205,6 +205,14 @@ impl LLVM {
info: true,
machine_code: true,
}),
Architecture::Riscv32(_) => InkwellTarget::initialize_riscv(&InitializationConfig {
asm_parser: true,
asm_printer: true,
base: true,
disassembler: true,
info: true,
machine_code: true,
}),
Architecture::LoongArch64 => {
InkwellTarget::initialize_loongarch(&InitializationConfig {
asm_parser: true,
Expand Down Expand Up @@ -236,61 +244,38 @@ impl LLVM {

let target_triple = self.target_triple(target);
let llvm_target = InkwellTarget::from_triple(&target_triple).unwrap();
let llvm_target_machine = llvm_target
.create_target_machine(
&target_triple,
match triple.architecture {
Architecture::Riscv64(_) => "generic-rv64",
Architecture::LoongArch64 => "generic-la64",
_ => "generic",
},
match triple.architecture {
Architecture::Riscv64(_) => "+m,+a,+c,+d,+f",
Architecture::LoongArch64 => "+f,+d",
_ => &llvm_cpu_features,
},
self.opt_level,
self.reloc_mode(self.target_binary_format(target)),
match triple.architecture {
Architecture::LoongArch64 | Architecture::Riscv64(_) => CodeModel::Medium,
_ => self.code_model(self.target_binary_format(target)),
},
)
.unwrap();

if let Architecture::Riscv64(_) = triple.architecture {
// TODO: totally non-portable way to change ABI
unsafe {
// This structure mimic the internal structure from inkwell
// that is defined as
// #[derive(Debug)]
// pub struct TargetMachine {
// pub(crate) target_machine: LLVMTargetMachineRef,
// }
pub struct MyTargetMachine {
pub target_machine: *const u8,
let mut llvm_target_machine_options = TargetMachineOptions::new()
.set_cpu(match triple.architecture {
Architecture::Riscv64(_) => "generic-rv64",
Architecture::Riscv32(_) => "generic-rv32",
Architecture::LoongArch64 => "generic-la64",
_ => "generic",
})
.set_features(match triple.architecture {
Architecture::Riscv64(_) => "+m,+a,+c,+d,+f",
// TODO: WASM modules requires these features to function, however,
// it is also possible to disable those features by generating floating
// point routine functions and multiplication routine functions. It might
// be worthwhile to allow turning them off, and generate references to
// proper routine functions.
Architecture::Riscv32(_) => "+m,+d,+f",
Architecture::LoongArch64 => "+f,+d",
_ => &llvm_cpu_features,
})
.set_level(self.opt_level)
.set_reloc_mode(self.reloc_mode(self.target_binary_format(target)))
.set_code_model(match triple.architecture {
Architecture::LoongArch64 | Architecture::Riscv64(_) | Architecture::Riscv32(_) => {
CodeModel::Medium
}
// It is use to live patch the create LLVMTargetMachine
// to hard change the ABI and force "-mabi=lp64d" ABI
// instead of the default that don't use float registers
// because there is no current way to do this change

let my_target_machine: MyTargetMachine = std::mem::transmute(llvm_target_machine);

*((my_target_machine.target_machine as *mut u8).offset(0x410) as *mut u64) = 5;
std::ptr::copy_nonoverlapping(
"lp64d\0".as_ptr(),
(my_target_machine.target_machine as *mut u8).offset(0x418),
6,
);

std::mem::transmute::<MyTargetMachine, inkwell::targets::TargetMachine>(
my_target_machine,
)
}
} else {
llvm_target_machine
_ => self.code_model(self.target_binary_format(target)),
});
if let Architecture::Riscv64(_) = triple.architecture {
llvm_target_machine_options = llvm_target_machine_options.set_abi("lp64d");
}
llvm_target
.create_target_machine_from_options(&target_triple, llvm_target_machine_options)
.unwrap()
}
}

Expand Down
64 changes: 61 additions & 3 deletions lib/compiler-llvm/src/object_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,64 @@ static LIBCALLS_ELF: phf::Map<&'static str, LibCall> = phf::phf_map! {
"wasmer_vm_read_exception" => LibCall::ReadException,
"wasmer_vm_dbg_usize" => LibCall::DebugUsize,
"wasmer_eh_personality" => LibCall::EHPersonality,
// Floating-point & 64-bit mul/div routie functions. Those might
// be generated by LLVM when generating objects for 32-bit platforms,
// or platforms without floating point supports. Modern Rust & C toolchains
// provide implementations for thos functions by default.
"__adddf3" => LibCall::Adddf3,
"__addsf3" => LibCall::Addsf3,
"__divdf3" => LibCall::Divdf3,
"__divdi3" => LibCall::Divdi3,
"__divsf3" => LibCall::Divsf3,
"__divsi3" => LibCall::Divsi3,
"__eqdf2" => LibCall::Eqdf2,
"__eqsf2" => LibCall::Eqsf2,
"__extendsfdf2" => LibCall::Extendsfdf2,
"__fixdfdi" => LibCall::Fixdfdi,
"__fixdfsi" => LibCall::Fixdfsi,
"__fixsfdi" => LibCall::Fixsfdi,
"__fixsfsi" => LibCall::Fixsfsi,
"__fixunsdfdi" => LibCall::Fixunsdfdi,
"__fixunsdfsi" => LibCall::Fixunsdfsi,
"__fixunssfdi" => LibCall::Fixunssfdi,
"__fixunssfsi" => LibCall::Fixunssfsi,
"__floatdidf" => LibCall::Floatdidf,
"__floatdisf" => LibCall::Floatdisf,
"__floatsidf" => LibCall::Floatsidf,
"__floatsisf" => LibCall::Floatsisf,
"__floatundidf" => LibCall::Floatundidf,
"__floatundisf" => LibCall::Floatundisf,
"__floatunsidf" => LibCall::Floatunsidf,
"__floatunsisf" => LibCall::Floatunsisf,
"__gedf2" => LibCall::Gedf2,
"__gesf2" => LibCall::Gesf2,
"__gtdf2" => LibCall::Gtdf2,
"__gtsf2" => LibCall::Gtsf2,
"__ledf2" => LibCall::Ledf2,
"__lesf2" => LibCall::Lesf2,
"__ltdf2" => LibCall::Ltdf2,
"__ltsf2" => LibCall::Ltsf2,
"__moddi3" => LibCall::Moddi3,
"__modsi3" => LibCall::Modsi3,
"__muldf3" => LibCall::Muldf3,
"__muldi3" => LibCall::Muldi3,
"__mulsf3" => LibCall::Mulsf3,
"__mulsi3" => LibCall::Mulsi3,
"__nedf2" => LibCall::Nedf2,
"__negdf2" => LibCall::Negdf2,
"__negsf2" => LibCall::Negsf2,
"__nesf2" => LibCall::Nesf2,
"__subdf3" => LibCall::Subdf3,
"__subsf3" => LibCall::Subsf3,
"__truncdfsf2" => LibCall::Truncdfsf2,
"__udivdi3" => LibCall::Udivdi3,
"__udivsi3" => LibCall::Udivsi3,
"__umoddi3" => LibCall::Umoddi3,
"__umodsi3" => LibCall::Umodsi3,
"__unorddf2" => LibCall::Unorddf2,
"__unordsf2" => LibCall::Unordsf2,
"memset" => LibCall::Memset,
"sqrt" => LibCall::Sqrt,
};

static LIBCALLS_MACHO: phf::Map<&'static str, LibCall> = phf::phf_map! {
Expand Down Expand Up @@ -401,17 +459,17 @@ where
0,
) => RelocationKind::Arm64Movw3,
(
object::Architecture::Riscv64,
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationKind::Elf(object::elf::R_RISCV_CALL_PLT),
0,
) => RelocationKind::RiscvCall,
(
object::Architecture::Riscv64,
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_HI20),
0,
) => RelocationKind::RiscvPCRelHi20,
(
object::Architecture::Riscv64,
object::Architecture::Riscv64 | object::Architecture::Riscv32,
object::RelocationKind::Elf(object::elf::R_RISCV_PCREL_LO12_I),
0,
) => RelocationKind::RiscvPCRelLo12I,
Expand Down
15 changes: 12 additions & 3 deletions lib/compiler-llvm/src/translator/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ pub struct FuncTranslator {
abi: Box<dyn Abi>,
binary_fmt: BinaryFormat,
func_section: String,
pointer_width: u8,
}

impl FuncTranslator {
pub fn new(
target_machine: TargetMachine,
binary_fmt: BinaryFormat,
pointer_width: u8,
) -> Result<Self, CompileError> {
let abi = get_abi(&target_machine);
Ok(Self {
Expand All @@ -81,6 +83,7 @@ impl FuncTranslator {
}
},
binary_fmt,
pointer_width,
})
}

Expand Down Expand Up @@ -125,8 +128,7 @@ impl FuncTranslator {
.get(wasm_module.functions[func_index])
.unwrap();

// TODO: pointer width
let offsets = VMOffsets::new(8, wasm_module);
let offsets = VMOffsets::new(self.pointer_width, wasm_module);
let intrinsics = Intrinsics::declare(&module, &self.ctx, &target_data, &self.binary_fmt);
let (func_type, func_attrs) = self.abi.func_type_to_llvm(
&self.ctx,
Expand Down Expand Up @@ -271,7 +273,14 @@ impl FuncTranslator {
state,
function: func,
locals: params_locals,
ctx: CtxType::new(wasm_module, &func, &cache_builder, &*self.abi, config),
ctx: CtxType::new(
wasm_module,
&func,
&cache_builder,
&*self.abi,
config,
self.pointer_width,
),
unreachable_depth: 0,
memory_styles,
_table_styles,
Expand Down
4 changes: 2 additions & 2 deletions lib/compiler-llvm/src/translator/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,7 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
cache_builder: &'a Builder<'ctx>,
abi: &'a dyn Abi,
config: &'a LLVM,
pointer_width: u8,
) -> CtxType<'ctx, 'a> {
CtxType {
config,
Expand All @@ -1252,8 +1253,7 @@ impl<'ctx, 'a> CtxType<'ctx, 'a> {
cached_memory_grow: HashMap::new(),
cached_memory_size: HashMap::new(),

// TODO: pointer width
offsets: VMOffsets::new(8, wasm_module),
offsets: VMOffsets::new(pointer_width, wasm_module),
}
}

Expand Down
4 changes: 3 additions & 1 deletion lib/compiler/src/engine/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1112,11 +1112,13 @@ impl Artifact {
_ => 1,
};

// MetadataHeader::parse requires that metadata must be aligned
// by 8 bytes.
let offset = emit_data(
&mut obj,
object_name.as_bytes(),
metadata_builder.placeholder_data(),
default_align,
std::cmp::max(8, default_align),
)
.map_err(to_compile_error)?;
metadata_builder.set_section_offset(offset);
Expand Down
Loading
Loading