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:
Brendan Hansknecht 2024-03-21 21:54:58 -07:00
parent 185262510c
commit 6dc5bfb1b7
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
72 changed files with 1008 additions and 1371 deletions

View file

@ -21,7 +21,7 @@ impl LlvmAlignment<'_> for IntWidth {
// 128-bit integers are not consistently represented by LLVM.
// - AArch64 uses 16-byte alignment (https://godbolt.org/z/dYrfG5o4b)
// - x86-64 uses 8-byte alignment (https://godbolt.org/z/qj5Mann6b)
let arch = interner.target_info().architecture;
let arch = interner.target().architecture();
match arch {
Architecture::X86_64 => 8,
_ => 16,
@ -33,7 +33,7 @@ impl LlvmAlignment<'_> for IntWidth {
impl<'a> LlvmAlignment<'a> for FloatWidth {
fn llvm_alignment_bytes(&self, interner: &STLayoutInterner<'a>) -> u32 {
self.alignment_bytes(interner.target_info())
self.alignment_bytes(interner.target())
}
}
@ -48,7 +48,7 @@ impl<'a> LlvmAlignment<'a> for Builtin<'a> {
use std::mem::align_of;
use Builtin::*;
let ptr_width = interner.target_info().ptr_width() as u32;
let ptr_width = interner.target().ptr_width() as u32;
// for our data structures, what counts is the alignment of the `( ptr, len )` tuple, and
// since both of those are one pointer size, the alignment of that structure is a pointer
@ -99,7 +99,7 @@ impl<'a> LlvmAlignment<'a> for UnionLayout<'a> {
Recursive(_)
| NullableWrapped { .. }
| NullableUnwrapped { .. }
| NonNullableUnwrapped(_) => interner.target_info().ptr_width() as u32,
| NonNullableUnwrapped(_) => interner.target().ptr_width() as u32,
}
}
}
@ -120,7 +120,7 @@ impl<'a> LlvmAlignment<'a> for LayoutRepr<'a> {
.llvm_alignment_bytes(interner),
Builtin(builtin) => builtin.llvm_alignment_bytes(interner),
RecursivePointer(_) | Ptr(_) | FunctionPointer(_) | Erased(_) => {
interner.target_info().ptr_width() as u32
interner.target().ptr_width() as u32
}
}
}

View file

@ -37,7 +37,7 @@ pub fn call_bitcode_fn<'ctx>(
panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}")
});
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
if env.target.operating_system() == roc_target::OperatingSystem::Windows {
// On windows zig uses a vector type <2xi64> instead of a i128 value
let vec_type = env.context.i64_type().vec_type(2);
if ret.get_type() == vec_type.into() {
@ -70,7 +70,7 @@ fn call_bitcode_fn_help<'ctx>(
let it = args
.iter()
.map(|x| {
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
if env.target.operating_system() == roc_target::OperatingSystem::Windows {
if x.get_type() == env.context.i128_type().into() {
let parent = env
.builder
@ -1067,7 +1067,7 @@ pub(crate) fn call_str_bitcode_fn<'ctx>(
use bumpalo::collections::Vec;
use roc_target::Architecture::*;
match env.target_info.architecture {
match env.target.architecture() {
Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> =
Vec::with_capacity_in(other_arguments.len() + 2 * strings.len(), env.arena);
@ -1123,7 +1123,7 @@ pub(crate) fn call_list_bitcode_fn<'ctx>(
use bumpalo::collections::Vec;
use roc_target::Architecture::*;
match env.target_info.architecture {
match env.target.architecture() {
Aarch32 | X86_32 => {
let mut arguments: Vec<BasicValueEnum> =
Vec::with_capacity_in(other_arguments.len() + 2 * lists.len(), env.arena);

View file

@ -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);

View file

@ -378,7 +378,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>(
// the list has the same alignment as a usize / ptr. The element comes first in the struct if
// its alignment is bigger than that of a list.
let element_align = layout_interner.alignment_bytes(element_layout);
let element_first = element_align > env.target_info.ptr_width() as u32;
let element_first = element_align > env.target.ptr_width() as u32;
let fields = if element_first {
[element_layout, Layout::LIST_U8 /* any list works */]

View file

@ -11,7 +11,7 @@ use roc_mono::layout::{
round_up_to_alignment, Builtin, FunctionPointer, InLayout, Layout, LayoutInterner, LayoutRepr,
STLayoutInterner, UnionLayout,
};
use roc_target::TargetInfo;
use roc_target::Target;
use super::struct_::RocStruct;
@ -106,7 +106,7 @@ pub fn struct_type_from_union_layout<'a, 'ctx>(
| NullableWrapped {
other_tags: tags, ..
} => {
if union_layout.stores_tag_id_as_data(env.target_info) {
if union_layout.stores_tag_id_as_data(env.target) {
RocUnion::tagged_from_slices(layout_interner, env.context, tags).struct_type()
} else {
RocUnion::untagged_from_slices(layout_interner, env.context, tags).struct_type()
@ -489,8 +489,8 @@ impl<'ctx> RocUnion<'ctx> {
}
/// The int type that the C ABI turns our RocList/RocStr into
pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> {
match target_info.ptr_width() {
pub fn str_list_int(ctx: &Context, target: Target) -> IntType<'_> {
match target.ptr_width() {
roc_target::PtrWidth::Bytes4 => ctx.i64_type(),
roc_target::PtrWidth::Bytes8 => ctx.i128_type(),
}

View file

@ -184,8 +184,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>(
let after_header = offset;
let space_for_offsets = env.ptr_int().const_int(
(lookups.len() * env.target_info.ptr_size() + lookups.len() * std::mem::size_of::<u32>())
as _,
(lookups.len() * env.target.ptr_size() + lookups.len() * std::mem::size_of::<u32>()) as _,
false,
);
@ -232,9 +231,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx>(
{
build_copy(env, original_ptr, offset, lookup_start.into());
let ptr_width = env
.ptr_int()
.const_int(env.target_info.ptr_size() as _, false);
let ptr_width = env.ptr_int().const_int(env.target.ptr_size() as _, false);
offset = env.builder.new_build_int_add(offset, ptr_width, "offset");
}
@ -698,7 +695,7 @@ fn build_clone_tag_help<'a, 'ctx>(
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
let layout = LayoutRepr::struct_(field_layouts);
let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) {
let layout = if union_layout.stores_tag_id_in_pointer(env.target) {
layout
} else {
// [...fields, tag ID]
@ -914,7 +911,7 @@ fn write_pointer_with_tag_id<'a, 'ctx>(
union_layout: UnionLayout<'a>,
tag_id: usize,
) {
if union_layout.stores_tag_id_in_pointer(env.target_info) {
if union_layout.stores_tag_id_in_pointer(env.target) {
// first, store tag id as u32
let tag_id_intval = env.context.i32_type().const_int(tag_id as _, false);
build_copy(env, ptr, offset, tag_id_intval.into());

View file

@ -195,7 +195,7 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
}
}
match env.target_info.operating_system {
match env.target.operating_system() {
roc_target::OperatingSystem::Windows => {
// We don't need these functions on Windows
}
@ -266,7 +266,7 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
// write our error message to the RocStr pointer
{
let loaded_roc_str = match env.target_info.ptr_width() {
let loaded_roc_str = match env.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => roc_str_arg,
// On 64-bit we pass RocStrs by reference internally
roc_target::PtrWidth::Bytes8 => {
@ -315,12 +315,12 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
pub fn build_longjmp_call(env: &Env) {
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
let tag = env.context.i32_type().const_int(1, false);
let _call =
call_void_bitcode_fn(env, &[jmp_buf.into(), tag.into()], bitcode::UTILS_LONGJMP);
} else if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
} else if env.target.operating_system() == roc_target::OperatingSystem::Windows {
let tag = env.context.i32_type().const_int(1, false);
let _call = call_void_bitcode_fn(
env,

View file

@ -20,7 +20,7 @@ use roc_mono::{
},
list_element_layout,
};
use roc_target::{PtrWidth, TargetInfo};
use roc_target::{PtrWidth, Target};
use crate::llvm::{
bitcode::{
@ -129,7 +129,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Str.joinWith : List Str, Str -> Str
arguments!(list, string);
match env.target_info.ptr_width() {
match env.target.ptr_width() {
PtrWidth::Bytes4 => {
// list and string are both stored as structs on the stack on 32-bit targets
call_str_bitcode_fn(
@ -197,7 +197,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
};
use roc_target::Architecture::*;
let result = match env.target_info.architecture {
let result = match env.target.architecture() {
Aarch32 | X86_32 => {
let zig_function = env.module.get_function(intrinsic).unwrap();
let zig_function_type = zig_function.get_type();
@ -283,14 +283,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
};
use roc_target::OperatingSystem::*;
let cc_return_by_pointer = match env.target_info.operating_system {
let cc_return_by_pointer = match env.target.operating_system() {
Windows => {
// there is just one return register on Windows
(width + 1) as usize > env.target_info.ptr_size()
(width + 1) as usize > env.target.ptr_size()
}
_ => {
// on other systems we have two return registers
(width + 1) as usize > 2 * env.target_info.ptr_size()
(width + 1) as usize > 2 * env.target.ptr_size()
}
};
@ -415,7 +415,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
.new_build_alloca(result_type, "alloca_utf8_validate_bytes_result");
use roc_target::Architecture::*;
match env.target_info.architecture {
match env.target.architecture() {
Aarch32 | X86_32 => {
arguments!(list);
let (a, b) = pass_list_or_string_to_zig_32bit(env, list.into_struct_value());
@ -1299,7 +1299,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let value_ptr = match layout_interner.runtime_representation(data_layout) {
LayoutRepr::Union(union_layout)
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, ptr)
}
@ -1898,7 +1898,7 @@ fn dec_split_into_words<'ctx>(
fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
match env.target_info.operating_system {
match env.target.operating_system() {
Windows => {
let dec_type = zig_dec_type(env);
@ -1917,8 +1917,8 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu
alloca.into()
}
Unix => {
if matches!(env.target_info.architecture, X86_32 | X86_64) {
Linux | Mac => {
if matches!(env.target.architecture(), X86_32 | X86_64) {
internal_error!("X86 unix does not pass with a dec alloc instead it splits into high and low halves");
}
let i64_type = env.context.i64_type();
@ -1937,21 +1937,15 @@ fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> BasicValu
env.builder
.new_build_load(i64_type.array_type(2), alloca, "load as array")
}
Wasi => unimplemented!(),
Freestanding => unimplemented!(),
}
}
fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec = dec.into_int_value();
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
let (low, high) = dec_split_into_words(env, dec);
call_str_bitcode_fn(
@ -1962,10 +1956,7 @@ fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> Basic
bitcode::DEC_TO_STR,
)
}
TargetInfo {
architecture: Wasm32,
operating_system: Unix,
} => call_str_bitcode_fn(
Target::Wasm32 => call_str_bitcode_fn(
env,
&[],
&[dec.into()],
@ -1987,22 +1978,13 @@ fn dec_unary_op<'ctx>(
fn_name: &str,
dec: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec = dec.into_int_value();
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
let (low, high) = dec_split_into_words(env, dec);
call_bitcode_fn(env, &[low.into(), high.into()], fn_name)
}
TargetInfo {
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[dec.into()], fn_name),
Target::Wasm32 => call_bitcode_fn(env, &[dec.into()], fn_name),
_ => call_bitcode_fn(env, &[dec_alloca(env, dec)], fn_name),
}
}
@ -2013,17 +1995,11 @@ fn dec_binary_op<'ctx>(
dec1: BasicValueEnum<'ctx>,
dec2: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let dec1 = dec1.into_int_value();
let dec2 = dec2.into_int_value();
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
let (low1, high1) = dec_split_into_words(env, dec1);
let (low2, high2) = dec_split_into_words(env, dec2);
let lowr_highr = call_bitcode_fn(
@ -2043,10 +2019,7 @@ fn dec_binary_op<'ctx>(
.build_load(env.context.i128_type(), ptr, "to_i128")
.unwrap()
}
TargetInfo {
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name),
Target::Wasm32 => call_bitcode_fn(env, &[dec1.into(), dec2.into()], fn_name),
_ => call_bitcode_fn(
env,
&[dec_alloca(env, dec1), dec_alloca(env, dec2)],
@ -2061,20 +2034,14 @@ fn dec_binop_with_overflow<'ctx>(
lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>,
) -> StructValue<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value();
let return_type = zig_with_overflow_roc_dec(env);
let return_alloca = env.builder.new_build_alloca(return_type, "return_alloca");
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_void_bitcode_fn(
@ -2089,10 +2056,7 @@ fn dec_binop_with_overflow<'ctx>(
fn_name,
);
}
TargetInfo {
architecture: Wasm32,
operating_system: Unix,
} => {
Target::Wasm32 => {
call_void_bitcode_fn(
env,
&[return_alloca.into(), lhs.into(), rhs.into()],
@ -2123,17 +2087,11 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::Architecture::*;
use roc_target::OperatingSystem::*;
let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value();
match env.target_info {
TargetInfo {
architecture: X86_64 | X86_32,
operating_system: Unix,
} => {
match env.target {
Target::LinuxX32 | Target::LinuxX64 | Target::MacX64 => {
let (lhs_low, lhs_high) = dec_split_into_words(env, lhs);
let (rhs_low, rhs_high) = dec_split_into_words(env, rhs);
call_bitcode_fn(
@ -2147,10 +2105,7 @@ pub(crate) fn dec_binop_with_unchecked<'ctx>(
fn_name,
)
}
TargetInfo {
architecture: Wasm32,
operating_system: Unix,
} => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name),
Target::Wasm32 => call_bitcode_fn(env, &[lhs.into(), rhs.into()], fn_name),
_ => call_bitcode_fn(env, &[dec_alloca(env, lhs), dec_alloca(env, rhs)], fn_name),
}
}
@ -2432,7 +2387,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
&bitcode::NUM_INT_TO_INT_CHECKING_MAX_AND_MIN[target_int_width][arg_width]
};
let result = match env.target_info.ptr_width() {
let result = match env.target.ptr_width() {
PtrWidth::Bytes4 => {
let zig_function = env.module.get_function(intrinsic).unwrap();
let zig_function_type = zig_function.get_type();
@ -2489,12 +2444,11 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
}
PtrWidth::Bytes8 => {
let return_by_pointer = {
if env.target_info.operating_system
== roc_target::OperatingSystem::Windows
if env.target.operating_system() == roc_target::OperatingSystem::Windows
{
target_int_width.stack_size() as usize >= env.target_info.ptr_size()
target_int_width.stack_size() as usize >= env.target.ptr_size()
} else {
target_int_width.stack_size() as usize > env.target_info.ptr_size()
target_int_width.stack_size() as usize > env.target.ptr_size()
}
};
if return_by_pointer {

View file

@ -80,7 +80,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
pub fn is_1<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>) -> IntValue<'ctx> {
let current = self.get_refcount(env);
let one = match env.target_info.ptr_width() {
let one = match env.target.ptr_width() {
roc_target::PtrWidth::Bytes4 => {
env.context.i32_type().const_int(i32::MIN as u64, false)
}
@ -128,7 +128,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
) {
let alignment = layout
.allocation_alignment_bytes(layout_interner)
.max(env.target_info.ptr_width() as u32);
.max(env.target.ptr_width() as u32);
let context = env.context;
let block = env.builder.get_insert_block().expect("to be in a function");
@ -1034,7 +1034,7 @@ pub fn build_header_help<'ctx>(
// this should be `Linkage::Private`, but that will remove all of the code for the inc/dec
// functions on windows. LLVM just does not emit the assembly for them. Investigate why this is
let linkage = if let roc_target::OperatingSystem::Windows = env.target_info.operating_system {
let linkage = if let roc_target::OperatingSystem::Windows = env.target.operating_system() {
Linkage::External
} else {
Linkage::Private
@ -1162,7 +1162,7 @@ fn build_rec_union_help<'a, 'ctx>(
debug_assert!(arg_val.is_pointer_value());
let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val);
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) {
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target) {
tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
} else {
arg_val.into_pointer_value()