mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-20 07:17:50 +03:00
Merge pull request #5731 from roc-lang/folkert-windows-branch
Fix 2 bugs in windows dev backend
This commit is contained in:
commit
713afc71c3
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -4784,7 +4784,6 @@ dependencies = [
|
||||
"criterion",
|
||||
"indoc",
|
||||
"inkwell",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"libloading",
|
||||
"roc_bitcode",
|
||||
|
@ -985,7 +985,8 @@ impl<
|
||||
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
|
||||
ASM::mov_freg64_freg64(&mut self.buf, dst_reg, CC::FLOAT_RETURN_REGS[0]);
|
||||
}
|
||||
LayoutRepr::I128 | LayoutRepr::U128 => {
|
||||
// Note that on windows there is only 1 general return register so we can't use this optimisation
|
||||
LayoutRepr::I128 | LayoutRepr::U128 if CC::GENERAL_RETURN_REGS.len() > 1 => {
|
||||
let offset = self.storage_manager.claim_stack_area(dst, 16);
|
||||
|
||||
ASM::mov_base32_reg64(&mut self.buf, offset, CC::GENERAL_RETURN_REGS[0]);
|
||||
|
@ -8,7 +8,7 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
|
||||
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
|
||||
};
|
||||
|
||||
use super::{CompareOperation, RegisterWidth};
|
||||
@ -1130,6 +1130,9 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
];
|
||||
const SHADOW_SPACE_SIZE: u8 = 32;
|
||||
|
||||
// Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
|
||||
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile.
|
||||
// > They must be saved and restored by a function that uses them.
|
||||
#[inline(always)]
|
||||
fn general_callee_saved(reg: &X86_64GeneralReg) -> bool {
|
||||
matches!(
|
||||
@ -1146,16 +1149,23 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
)
|
||||
}
|
||||
|
||||
// Refer https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#callercallee-saved-registers
|
||||
// > The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile.
|
||||
// > They must be saved and restored by a function that uses them.
|
||||
#[inline(always)]
|
||||
fn float_callee_saved(reg: &X86_64FloatReg) -> bool {
|
||||
matches!(
|
||||
reg,
|
||||
X86_64FloatReg::XMM0
|
||||
| X86_64FloatReg::XMM1
|
||||
| X86_64FloatReg::XMM2
|
||||
| X86_64FloatReg::XMM3
|
||||
| X86_64FloatReg::XMM4
|
||||
| X86_64FloatReg::XMM5
|
||||
X86_64FloatReg::XMM6
|
||||
| X86_64FloatReg::XMM7
|
||||
| X86_64FloatReg::XMM8
|
||||
| X86_64FloatReg::XMM9
|
||||
| X86_64FloatReg::XMM10
|
||||
| X86_64FloatReg::XMM11
|
||||
| X86_64FloatReg::XMM12
|
||||
| X86_64FloatReg::XMM13
|
||||
| X86_64FloatReg::XMM14
|
||||
| X86_64FloatReg::XMM15
|
||||
)
|
||||
}
|
||||
|
||||
@ -1286,6 +1296,16 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
single_register_layouts!() => {
|
||||
internal_error!("single register layouts are not complex symbols");
|
||||
}
|
||||
// For windows (and zig 0.9 changes in zig 0.10) we need to match what zig does,
|
||||
// in this case uses RAX & RDX to return the value
|
||||
LayoutRepr::I128 | LayoutRepr::U128 => {
|
||||
let (base_offset, size) = storage_manager.stack_offset_and_size(sym);
|
||||
debug_assert_eq!(base_offset % 8, 0);
|
||||
debug_assert_eq!(size, 16);
|
||||
|
||||
X86_64Assembler::mov_reg64_base32(buf, X86_64GeneralReg::RAX, base_offset);
|
||||
X86_64Assembler::mov_reg64_base32(buf, X86_64GeneralReg::RDX, base_offset + 0x08);
|
||||
}
|
||||
_ if layout_interner.stack_size(*layout) == 0 => {}
|
||||
_ if !Self::returns_via_arg_pointer(layout_interner, layout) => {
|
||||
let (base_offset, size) = storage_manager.stack_offset_and_size(sym);
|
||||
@ -1333,6 +1353,14 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
||||
single_register_layouts!() => {
|
||||
internal_error!("single register layouts are not complex symbols");
|
||||
}
|
||||
// For windows (and zig 0.9 changes in zig 0.10) we need to match what zig does,
|
||||
// in this case uses RAX & RDX to return the value
|
||||
LayoutRepr::I128 | LayoutRepr::U128 => {
|
||||
let size = layout_interner.stack_size(*layout);
|
||||
let offset = storage_manager.claim_stack_area(sym, size);
|
||||
X86_64Assembler::mov_base32_reg64(buf, offset, X86_64GeneralReg::RAX);
|
||||
X86_64Assembler::mov_base32_reg64(buf, offset + 0x08, X86_64GeneralReg::RDX);
|
||||
}
|
||||
_ if layout_interner.stack_size(*layout) == 0 => {
|
||||
storage_manager.no_data(sym);
|
||||
}
|
||||
@ -1508,7 +1536,10 @@ impl X86_64WindowsFastcall {
|
||||
) -> bool {
|
||||
// TODO: This is not fully correct there are some exceptions for "vector" types.
|
||||
// details here: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160#return-values
|
||||
interner.stack_size(*ret_layout) > 8
|
||||
match *ret_layout {
|
||||
Layout::I128 | Layout::U128 => false,
|
||||
_ => interner.stack_size(*ret_layout) > 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,13 @@ wasi_libc_sys = { path = "../../wasi-libc-sys" }
|
||||
|
||||
tempfile.workspace = true
|
||||
|
||||
[dependencies]
|
||||
roc_gen_llvm = { path = "../gen_llvm", optional = true }
|
||||
inkwell = { workspace = true, optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_bitcode = { path = "../builtins/bitcode" }
|
||||
roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] }
|
||||
roc_builtins = { path = "../builtins" }
|
||||
@ -28,9 +34,6 @@ roc_command_utils = { path = "../../utils/command" }
|
||||
roc_constrain = { path = "../constrain" }
|
||||
roc_debug_flags = { path = "../debug_flags" }
|
||||
roc_error_macros = { path = "../../error_macros" }
|
||||
roc_gen_dev = { path = "../gen_dev" }
|
||||
roc_gen_llvm = { path = "../gen_llvm" }
|
||||
roc_gen_wasm = { path = "../gen_wasm" }
|
||||
roc_load = { path = "../load" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_mono = { path = "../mono" }
|
||||
@ -50,8 +53,6 @@ roc_wasm_module = { path = "../../wasm_module" }
|
||||
bumpalo.workspace = true
|
||||
criterion.workspace = true
|
||||
indoc.workspace = true
|
||||
inkwell.workspace = true
|
||||
lazy_static.workspace = true
|
||||
libc.workspace = true
|
||||
libloading.workspace = true
|
||||
target-lexicon.workspace = true
|
||||
@ -61,7 +62,7 @@ tempfile.workspace = true
|
||||
[features]
|
||||
default = ["gen-llvm"]
|
||||
gen-dev = []
|
||||
gen-llvm = []
|
||||
gen-llvm = ["roc_gen_llvm", "inkwell"]
|
||||
gen-llvm-wasm = ["gen-llvm"]
|
||||
gen-wasm = []
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::mem::MaybeUninit;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use inkwell::module::Module;
|
||||
use libloading::Library;
|
||||
@ -414,10 +415,6 @@ fn write_final_wasm() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref TEMP_DIR: tempfile::TempDir = tempfile::tempdir().unwrap();
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn compile_to_wasm_bytes<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
@ -426,13 +423,17 @@ fn compile_to_wasm_bytes<'a>(
|
||||
context: &'a inkwell::context::Context,
|
||||
function_kind: FunctionKind,
|
||||
) -> Vec<u8> {
|
||||
// globally cache the temporary directory
|
||||
static TEMP_DIR: OnceLock<tempfile::TempDir> = OnceLock::new();
|
||||
let temp_dir = TEMP_DIR.get_or_init(|| tempfile::tempdir().unwrap());
|
||||
|
||||
let target = wasm32_target_tripple();
|
||||
|
||||
let (_main_fn_name, _delayed_errors, llvm_module) =
|
||||
create_llvm_module(arena, src, config, context, &target, function_kind);
|
||||
|
||||
let content_hash = crate::helpers::src_hash(src);
|
||||
let wasm_file = llvm_module_to_wasm_file(&TEMP_DIR, content_hash, llvm_module);
|
||||
let wasm_file = llvm_module_to_wasm_file(temp_dir, content_hash, llvm_module);
|
||||
let compiled_bytes = std::fs::read(wasm_file).unwrap();
|
||||
|
||||
if write_final_wasm() {
|
||||
|
Loading…
Reference in New Issue
Block a user