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
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */]
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue