mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Use roc_target over target_lexicon
Tailors a target class for our needs. Replaces tons of uses across the entire compiler. This is a base for later adding new targets like thumb.
This commit is contained in:
parent
185262510c
commit
6dc5bfb1b7
72 changed files with 1008 additions and 1371 deletions
|
@ -52,10 +52,9 @@ use roc_mono::layout::{
|
|||
RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
};
|
||||
use roc_std::RocDec;
|
||||
use roc_target::{PtrWidth, TargetInfo};
|
||||
use roc_target::{PtrWidth, Target};
|
||||
use std::convert::TryInto;
|
||||
use std::path::Path;
|
||||
use target_lexicon::{Aarch64Architecture, Architecture, OperatingSystem, Triple};
|
||||
|
||||
use super::convert::{struct_type_from_union_layout, RocUnion};
|
||||
use super::intrinsics::{
|
||||
|
@ -737,7 +736,7 @@ pub struct Env<'a, 'ctx, 'env> {
|
|||
pub compile_unit: &'env DICompileUnit<'ctx>,
|
||||
pub module: &'ctx Module<'ctx>,
|
||||
pub interns: Interns,
|
||||
pub target_info: TargetInfo,
|
||||
pub target: Target,
|
||||
pub mode: LlvmBackendMode,
|
||||
pub exposed_to_host: MutSet<Symbol>,
|
||||
}
|
||||
|
@ -750,7 +749,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
pub fn ptr_int(&self) -> IntType<'ctx> {
|
||||
let ctx = self.context;
|
||||
|
||||
match self.target_info.ptr_width() {
|
||||
match self.target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i32_type(),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i64_type(),
|
||||
}
|
||||
|
@ -763,14 +762,14 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
pub fn twice_ptr_int(&self) -> IntType<'ctx> {
|
||||
let ctx = self.context;
|
||||
|
||||
match self.target_info.ptr_width() {
|
||||
match self.target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i64_type(),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn small_str_bytes(&self) -> u32 {
|
||||
self.target_info.ptr_width() as u32 * 3
|
||||
self.target.ptr_width() as u32 * 3
|
||||
}
|
||||
|
||||
pub fn build_intrinsic_call(
|
||||
|
@ -872,7 +871,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
) -> CallSiteValue<'ctx> {
|
||||
let false_val = self.context.bool_type().const_int(0, false);
|
||||
|
||||
let intrinsic_name = match self.target_info.ptr_width() {
|
||||
let intrinsic_name = match self.target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => LLVM_MEMSET_I64,
|
||||
roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32,
|
||||
};
|
||||
|
@ -932,7 +931,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
string: BasicValueEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match env.target_info.ptr_width() {
|
||||
match env.target.ptr_width() {
|
||||
PtrWidth::Bytes4 => {
|
||||
// we need to pass the string by reference, but we currently hold the value.
|
||||
let alloca = env
|
||||
|
@ -1011,48 +1010,29 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
}
|
||||
|
||||
pub fn module_from_builtins<'ctx>(
|
||||
target: &target_lexicon::Triple,
|
||||
target: Target,
|
||||
ctx: &'ctx Context,
|
||||
module_name: &str,
|
||||
) -> Module<'ctx> {
|
||||
// In the build script for the builtins module, we compile the builtins into LLVM bitcode
|
||||
|
||||
let bitcode_bytes: &[u8] = if target == &target_lexicon::Triple::host() {
|
||||
let bitcode_bytes: &[u8] = if target == target_lexicon::Triple::host().into() {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-host.bc")
|
||||
} else {
|
||||
match target {
|
||||
Triple {
|
||||
architecture: Architecture::Wasm32,
|
||||
..
|
||||
} => {
|
||||
Target::Wasm32 => {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-wasm32.bc")
|
||||
}
|
||||
Triple {
|
||||
architecture: Architecture::X86_32(_),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => {
|
||||
Target::LinuxX32 => {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86.bc")
|
||||
}
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => {
|
||||
Target::LinuxX64 => {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-x86_64.bc")
|
||||
}
|
||||
Triple {
|
||||
architecture: Architecture::Aarch64(Aarch64Architecture::Aarch64),
|
||||
operating_system: OperatingSystem::Linux,
|
||||
..
|
||||
} => {
|
||||
Target::LinuxArm64 => {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-aarch64.bc")
|
||||
}
|
||||
Triple {
|
||||
architecture: Architecture::X86_64,
|
||||
operating_system: OperatingSystem::Windows,
|
||||
..
|
||||
} => {
|
||||
Target::WinX64 => {
|
||||
include_bytes!("../../../builtins/bitcode/zig-out/builtins-windows-x86_64.bc")
|
||||
}
|
||||
_ => panic!("The zig builtins are not currently built for this target: {target:?}"),
|
||||
|
@ -1416,7 +1396,7 @@ fn build_string_literal<'ctx>(
|
|||
|
||||
let alloca = const_str_alloca_ptr(env, parent, ptr, number_of_elements, number_of_elements);
|
||||
|
||||
match env.target_info.ptr_width() {
|
||||
match env.target.ptr_width() {
|
||||
PtrWidth::Bytes4 => {
|
||||
env.builder
|
||||
.new_build_load(zig_str_type(env), alloca, "load_const_str")
|
||||
|
@ -1449,7 +1429,7 @@ fn small_str_ptr_width_8<'ctx>(
|
|||
parent: FunctionValue<'ctx>,
|
||||
str_literal: &str,
|
||||
) -> PointerValue<'ctx> {
|
||||
debug_assert_eq!(env.target_info.ptr_width() as u8, 8);
|
||||
debug_assert_eq!(env.target.ptr_width() as u8, 8);
|
||||
|
||||
let mut array = [0u8; 24];
|
||||
|
||||
|
@ -1473,7 +1453,7 @@ fn small_str_ptr_width_8<'ctx>(
|
|||
}
|
||||
|
||||
fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> {
|
||||
debug_assert_eq!(env.target_info.ptr_width() as u8, 4);
|
||||
debug_assert_eq!(env.target.ptr_width() as u8, 4);
|
||||
|
||||
let mut array = [0u8; 12];
|
||||
|
||||
|
@ -1779,7 +1759,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(
|
||||
env,
|
||||
if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
if union_layout.stores_tag_id_in_pointer(env.target) {
|
||||
tag_pointer_clear_tag_id(env, tag_ptr)
|
||||
} else {
|
||||
tag_ptr
|
||||
|
@ -1876,7 +1856,7 @@ pub(crate) fn build_exp_expr<'a, 'ctx>(
|
|||
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(
|
||||
env,
|
||||
if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
if union_layout.stores_tag_id_in_pointer(env.target) {
|
||||
tag_pointer_clear_tag_id(env, tag_ptr)
|
||||
} else {
|
||||
tag_ptr
|
||||
|
@ -2261,7 +2241,7 @@ fn build_wrapped_tag<'a, 'ctx>(
|
|||
);
|
||||
let struct_type = env.context.struct_type(&field_types, false);
|
||||
|
||||
if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
if union_layout.stores_tag_id_as_data(env.target) {
|
||||
let tag_id_ptr = builder.new_build_struct_gep(
|
||||
union_struct_type,
|
||||
raw_data_ptr,
|
||||
|
@ -2556,7 +2536,7 @@ fn tag_pointer_set_tag_id<'ctx>(
|
|||
pointer: PointerValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
// we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3)
|
||||
debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32);
|
||||
debug_assert!((tag_id as u32) < env.target.ptr_width() as u32);
|
||||
|
||||
let tag_id_intval = env.ptr_int().const_int(tag_id as u64, false);
|
||||
|
||||
|
@ -2580,8 +2560,8 @@ fn tag_pointer_set_tag_id<'ctx>(
|
|||
.new_build_pointer_cast(indexed_pointer, pointer.get_type(), "cast_from_i8_ptr")
|
||||
}
|
||||
|
||||
pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) {
|
||||
match target_info.ptr_width() {
|
||||
pub fn tag_pointer_tag_id_bits_and_mask(target: Target) -> (u64, u64) {
|
||||
match target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111),
|
||||
roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011),
|
||||
}
|
||||
|
@ -2591,7 +2571,7 @@ pub fn tag_pointer_read_tag_id<'ctx>(
|
|||
env: &Env<'_, 'ctx, '_>,
|
||||
pointer: PointerValue<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target_info);
|
||||
let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target);
|
||||
let ptr_int = env.ptr_int();
|
||||
|
||||
let as_int = env.builder.new_build_ptr_to_int(pointer, ptr_int, "to_int");
|
||||
|
@ -2607,7 +2587,7 @@ pub fn tag_pointer_clear_tag_id<'ctx>(
|
|||
env: &Env<'_, 'ctx, '_>,
|
||||
pointer: PointerValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target_info);
|
||||
let (_, tag_id_bits_mask) = tag_pointer_tag_id_bits_and_mask(env.target);
|
||||
|
||||
let as_int = env
|
||||
.builder
|
||||
|
@ -2725,7 +2705,7 @@ pub fn get_tag_id<'a, 'ctx>(
|
|||
UnionLayout::Recursive(_) => {
|
||||
let argument_ptr = argument.into_pointer_value();
|
||||
|
||||
if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
if union_layout.stores_tag_id_as_data(env.target) {
|
||||
get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
|
||||
} else {
|
||||
tag_pointer_read_tag_id(env, argument_ptr)
|
||||
|
@ -2756,7 +2736,7 @@ pub fn get_tag_id<'a, 'ctx>(
|
|||
{
|
||||
env.builder.position_at_end(else_block);
|
||||
|
||||
let tag_id = if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
let tag_id = if union_layout.stores_tag_id_as_data(env.target) {
|
||||
get_tag_id_wrapped(env, layout_interner, *union_layout, argument_ptr)
|
||||
} else {
|
||||
tag_pointer_read_tag_id(env, argument_ptr)
|
||||
|
@ -2894,7 +2874,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
|
|||
union_layout: UnionLayout<'a>,
|
||||
fields: &[&[InLayout<'a>]],
|
||||
) -> PointerValue<'ctx> {
|
||||
let ptr_bytes = env.target_info;
|
||||
let ptr_bytes = env.target;
|
||||
|
||||
let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) {
|
||||
RocUnion::tagged_from_slices(layout_interner, env.context, fields)
|
||||
|
@ -2988,11 +2968,11 @@ fn list_literal<'a, 'ctx>(
|
|||
let size = list_length * element_width as usize;
|
||||
let alignment = layout_interner
|
||||
.alignment_bytes(element_layout)
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
.max(env.target.ptr_width() as u32);
|
||||
|
||||
let mut is_all_constant = true;
|
||||
let zero_elements =
|
||||
(env.target_info.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize;
|
||||
(env.target.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize;
|
||||
|
||||
// runtime-evaluated elements
|
||||
let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena);
|
||||
|
@ -3498,7 +3478,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
if value.is_pointer_value() {
|
||||
let clear_tag_id = match other_layout {
|
||||
LayoutRepr::Union(union_layout) => {
|
||||
union_layout.stores_tag_id_in_pointer(env.target_info)
|
||||
union_layout.stores_tag_id_in_pointer(env.target)
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
@ -3562,7 +3542,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
let value = value.into_pointer_value();
|
||||
|
||||
let clear_tag_id = match layout_interner.runtime_representation(layout) {
|
||||
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target_info),
|
||||
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
@ -3640,7 +3620,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
if env.mode.runs_expects() {
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
match env.target_info.ptr_width() {
|
||||
match env.target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => {
|
||||
let shared_memory = SharedMemoryPointer::get(env);
|
||||
|
||||
|
@ -3712,7 +3692,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
|||
if env.mode.runs_expects() {
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
match env.target_info.ptr_width() {
|
||||
match env.target.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => {
|
||||
let shared_memory = SharedMemoryPointer::get(env);
|
||||
|
||||
|
@ -4891,7 +4871,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
|
|||
// On x86_*, Modify the argument to specify it is passed by value and nonnull
|
||||
// Aarch*, just passes in the pointer directly.
|
||||
if matches!(
|
||||
env.target_info.architecture,
|
||||
env.target.architecture(),
|
||||
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
|
||||
) {
|
||||
let c_abi_type = match layout_interner.get_repr(*layout) {
|
||||
|
@ -5072,7 +5052,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx>(
|
|||
}
|
||||
|
||||
pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
||||
let word_type = match env.target_info.ptr_width() {
|
||||
let word_type = match env.target.ptr_width() {
|
||||
PtrWidth::Bytes4 => env.context.i32_type(),
|
||||
PtrWidth::Bytes8 => env.context.i64_type(),
|
||||
};
|
||||
|
@ -5088,7 +5068,7 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
|||
// The following three words are available for use in a target-specific manner.
|
||||
//
|
||||
// So, let's create a 5-word buffer.
|
||||
let size = if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||
let size = if env.target.operating_system() == roc_target::OperatingSystem::Windows {
|
||||
// Due to https://github.com/llvm/llvm-project/issues/72908
|
||||
// on windows, we store the register contents into this buffer directly!
|
||||
30
|
||||
|
@ -5114,10 +5094,10 @@ pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
|
|||
|
||||
pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
|
||||
let jmp_buf = get_sjlj_buffer(env);
|
||||
if env.target_info.architecture == roc_target::Architecture::Aarch64 {
|
||||
if env.target.architecture() == roc_target::Architecture::Aarch64 {
|
||||
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
|
||||
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_SETJMP)
|
||||
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
|
||||
} else if env.target.operating_system() == roc_target::OperatingSystem::Windows {
|
||||
// Due to https://github.com/llvm/llvm-project/issues/72908, we use a setjmp defined as asm in Zig
|
||||
call_bitcode_fn(env, &[jmp_buf.into()], bitcode::UTILS_WINDOWS_SETJMP)
|
||||
} else {
|
||||
|
@ -6770,10 +6750,14 @@ pub fn to_cc_return<'a>(
|
|||
layout: InLayout<'a>,
|
||||
) -> CCReturn {
|
||||
let return_size = layout_interner.stack_size(layout);
|
||||
let pass_result_by_pointer = match env.target_info.operating_system {
|
||||
roc_target::OperatingSystem::Windows => return_size > env.target_info.ptr_width() as u32,
|
||||
roc_target::OperatingSystem::Unix => return_size > 2 * env.target_info.ptr_width() as u32,
|
||||
roc_target::OperatingSystem::Wasi => return_size > 2 * env.target_info.ptr_width() as u32,
|
||||
// TODO: loop back and update this. It actually cares about the full abi (arch + os)
|
||||
let pass_result_by_pointer = match env.target.operating_system() {
|
||||
roc_target::OperatingSystem::Windows => return_size > env.target.ptr_width() as u32,
|
||||
roc_target::OperatingSystem::Linux
|
||||
| roc_target::OperatingSystem::Mac
|
||||
| roc_target::OperatingSystem::Freestanding => {
|
||||
return_size > 2 * env.target.ptr_width() as u32
|
||||
}
|
||||
};
|
||||
|
||||
if return_size == 0 {
|
||||
|
@ -6996,7 +6980,7 @@ fn define_global_str_literal_ptr<'ctx>(
|
|||
ptr,
|
||||
&[env
|
||||
.ptr_int()
|
||||
.const_int(env.target_info.ptr_width() as u64, false)],
|
||||
.const_int(env.target.ptr_width() as u64, false)],
|
||||
"get_rc_ptr",
|
||||
)
|
||||
};
|
||||
|
@ -7026,11 +7010,11 @@ fn define_global_str_literal<'ctx>(
|
|||
Some(current) => current,
|
||||
|
||||
None => {
|
||||
let size = message.bytes().len() + env.target_info.ptr_width() as usize;
|
||||
let size = message.bytes().len() + env.target.ptr_width() as usize;
|
||||
let mut bytes = Vec::with_capacity_in(size, env.arena);
|
||||
|
||||
// insert NULL bytes for the refcount
|
||||
for _ in 0..env.target_info.ptr_width() as usize {
|
||||
for _ in 0..env.target.ptr_width() as usize {
|
||||
bytes.push(env.context.i8_type().const_zero());
|
||||
}
|
||||
|
||||
|
@ -7049,7 +7033,7 @@ fn define_global_str_literal<'ctx>(
|
|||
// strings are NULL-terminated, which means we can't store the refcount (which is 8
|
||||
// NULL bytes)
|
||||
global.set_constant(true);
|
||||
global.set_alignment(env.target_info.ptr_width() as u32);
|
||||
global.set_alignment(env.target.ptr_width() as u32);
|
||||
global.set_unnamed_addr(true);
|
||||
global.set_linkage(inkwell::module::Linkage::Private);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue