From 70d39123908e29cde9fbfb540869e03ab86694e3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 31 Jul 2022 18:10:28 -0700 Subject: update Target, CPU, OS, ABI, etc. to LLVM 15 --- src/codegen/llvm.zig | 24 ++++++++++++++++++++++++ src/codegen/llvm/bindings.zig | 10 ++++++++++ 2 files changed, 34 insertions(+) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 664edb0304..132b5ef7a5 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -41,7 +41,10 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .bpfel => "bpfel", .bpfeb => "bpfeb", .csky => "csky", + .dxil => "dxil", .hexagon => "hexagon", + .loongarch32 => "loongarch32", + .loongarch64 => "loongarch64", .m68k => "m68k", .mips => "mips", .mipsel => "mipsel", @@ -116,6 +119,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .nvcl => "nvcl", .amdhsa => "amdhsa", .ps4 => "ps4", + .ps5 => "ps5", .elfiamcu => "elfiamcu", .mesa3d => "mesa3d", .contiki => "contiki", @@ -129,6 +133,8 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .ios => "ios", .tvos => "tvos", .watchos => "watchos", + .driverkit => "driverkit", + .shadermodel => "shadermodel", .opencl, .glsl450, .vulkan, @@ -171,6 +177,21 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .coreclr => "coreclr", .simulator => "simulator", .macabi => "macabi", + .pixel => "pixel", + .vertex => "vertex", + .geometry => "geometry", + .hull => "hull", + .domain => "domain", + .compute => "compute", + .library => "library", + .raygeneration => "raygeneration", + .intersection => "intersection", + .anyhit => "anyhit", + .closesthit => "closesthit", + .miss => "miss", + .callable => "callable", + .mesh => "mesh", + .amplification => "amplification", }; try llvm_triple.appendSlice(llvm_abi); @@ -9030,6 +9051,9 @@ fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { .kalimba, .renderscript32, .renderscript64, + .dxil, + .loongarch32, + .loongarch64, => {}, .spu_2 => unreachable, // LLVM does not support this backend diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index e4357b8060..7ce4727793 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -1212,9 +1212,11 @@ pub const LinkWasm = ZigLLDLinkWasm; pub const ObjectFormatType = enum(c_int) { Unknown, COFF, + DXContainer, ELF, GOFF, MachO, + SPIRV, Wasm, XCOFF, }; @@ -1254,9 +1256,11 @@ pub const OSType = enum(c_int) { NVCL, AMDHSA, PS4, + PS5, ELFIAMCU, TvOS, WatchOS, + DriverKit, Mesa3D, Contiki, AMDPAL, @@ -1264,6 +1268,7 @@ pub const OSType = enum(c_int) { Hurd, WASI, Emscripten, + ShaderModel, }; pub const ArchType = enum(c_int) { @@ -1278,7 +1283,10 @@ pub const ArchType = enum(c_int) { bpfel, bpfeb, csky, + dxil, hexagon, + loongarch32, + loongarch64, m68k, mips, mipsel, @@ -1314,6 +1322,8 @@ pub const ArchType = enum(c_int) { hsail64, spir, spir64, + spirv32, + spirv64, kalimba, shave, lanai, -- cgit v1.2.3 From 0f793840aebcc31a678e49b1e8b2ad0a0d8656f4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 18:16:52 -0700 Subject: stage1: LLVM lowering to opaque pointers API --- CMakeLists.txt | 2 +- src/codegen/llvm/bindings.zig | 32 +- src/stage1/all_types.hpp | 1 + src/stage1/analyze.cpp | 1 + src/stage1/codegen.cpp | 851 ++++++++++++++++++++++++------------------ src/zig_llvm.cpp | 13 +- src/zig_llvm.h | 5 +- 7 files changed, 517 insertions(+), 388 deletions(-) (limited to 'src/codegen') diff --git a/CMakeLists.txt b/CMakeLists.txt index 506115214e..af34214bae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -858,7 +858,7 @@ endif() if(MSVC) set(EXE_CFLAGS "${EXE_CFLAGS}") else() - set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces -Wno-comment -Wno-deprecated-declarations") + set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces -Wno-comment") if(MINGW) set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-format") endif() diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 7ce4727793..7a3ed9ebd1 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -31,6 +31,9 @@ pub const Context = opaque { pub const createStringAttribute = LLVMCreateStringAttribute; extern fn LLVMCreateStringAttribute(*const Context, Key: [*]const u8, Key_Len: c_uint, Value: [*]const u8, Value_Len: c_uint) *const Attribute; + pub const pointerType = LLVMPointerTypeInContext; + extern fn LLVMPointerTypeInContext(C: *const Context, AddressSpace: c_uint) *const Type; + pub const intType = LLVMIntTypeInContext; extern fn LLVMIntTypeInContext(C: *const Context, NumBits: c_uint) *const Type; @@ -138,8 +141,9 @@ pub const Value = opaque { pub const setAliasee = LLVMAliasSetAliasee; extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void; - pub const constInBoundsGEP = LLVMConstInBoundsGEP; - extern fn LLVMConstInBoundsGEP( + pub const constInBoundsGEP = LLVMConstInBoundsGEP2; + extern fn LLVMConstInBoundsGEP2( + Ty: *const Type, ConstantVal: *const Value, ConstantIndices: [*]const *const Value, NumIndices: c_uint, @@ -276,9 +280,6 @@ pub const Type = opaque { pub const getUndef = LLVMGetUndef; extern fn LLVMGetUndef(Ty: *const Type) *const Value; - pub const pointerType = LLVMPointerType; - extern fn LLVMPointerType(ElementType: *const Type, AddressSpace: c_uint) *const Type; - pub const arrayType = LLVMArrayType; extern fn LLVMArrayType(ElementType: *const Type, ElementCount: c_uint) *const Type; @@ -506,6 +507,7 @@ pub const Builder = opaque { pub const buildCall = ZigLLVMBuildCall; extern fn ZigLLVMBuildCall( *const Builder, + *const Type, Fn: *const Value, Args: [*]const *const Value, NumArgs: c_uint, @@ -529,8 +531,8 @@ pub const Builder = opaque { pub const buildStore = LLVMBuildStore; extern fn LLVMBuildStore(*const Builder, Val: *const Value, Ptr: *const Value) *const Value; - pub const buildLoad = LLVMBuildLoad; - extern fn LLVMBuildLoad(*const Builder, PointerVal: *const Value, Name: [*:0]const u8) *const Value; + pub const buildLoad = LLVMBuildLoad2; + extern fn LLVMBuildLoad2(*const Builder, Ty: *const Type, PointerVal: *const Value, Name: [*:0]const u8) *const Value; pub const buildNeg = LLVMBuildNeg; extern fn LLVMBuildNeg(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value; @@ -655,16 +657,7 @@ pub const Builder = opaque { pub const buildBitCast = LLVMBuildBitCast; extern fn LLVMBuildBitCast(*const Builder, Val: *const Value, DestTy: *const Type, Name: [*:0]const u8) *const Value; - pub const buildInBoundsGEP = LLVMBuildInBoundsGEP; - extern fn LLVMBuildInBoundsGEP( - B: *const Builder, - Pointer: *const Value, - Indices: [*]const *const Value, - NumIndices: c_uint, - Name: [*:0]const u8, - ) *const Value; - - pub const buildInBoundsGEP2 = LLVMBuildInBoundsGEP2; + pub const buildInBoundsGEP = LLVMBuildInBoundsGEP2; extern fn LLVMBuildInBoundsGEP2( B: *const Builder, Ty: *const Type, @@ -741,9 +734,10 @@ pub const Builder = opaque { Name: [*:0]const u8, ) *const Value; - pub const buildStructGEP = LLVMBuildStructGEP; - extern fn LLVMBuildStructGEP( + pub const buildStructGEP = LLVMBuildStructGEP2; + extern fn LLVMBuildStructGEP2( B: *const Builder, + Ty: *const Type, Pointer: *const Value, Idx: c_uint, Name: [*:0]const u8, diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 4028c3872d..df48981f5f 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -2043,6 +2043,7 @@ struct CodeGen { LLVMValueRef wasm_memory_grow; LLVMValueRef prefetch; LLVMTypeRef anyframe_fn_type; + LLVMTypeRef any_frame_header_llvm_ty; // reminder: hash tables must be initialized before use HashMap import_table; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 08aa8bbf06..25376662b2 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -9746,6 +9746,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name)); LLVMTypeRef frame_header_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); + g->any_frame_header_llvm_ty = frame_header_type; any_frame_type->llvm_type = LLVMPointerType(frame_header_type, 0); unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 8b88446295..9b3e6607e5 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -88,8 +88,8 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val); static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, LLVMValueRef ptr); static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr, - LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, - LLVMValueRef result_loc, bool non_async); + LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr, + ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async); static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); @@ -911,10 +911,10 @@ static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile); } -static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile, - const char *name) +static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMTypeRef elem_llvm_ty, LLVMValueRef ptr, + uint32_t alignment, bool is_volatile, const char *name) { - LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, name); + LLVMValueRef result = LLVMBuildLoad2(g->builder, elem_llvm_ty, ptr, name); if (is_volatile) LLVMSetVolatile(result, true); if (alignment == 0) { LLVMSetAlignment(result, LLVMABIAlignmentOfType(g->target_data_ref, LLVMGetElementType(LLVMTypeOf(ptr)))); @@ -927,7 +927,9 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) { assert(ptr_type->id == ZigTypeIdPointer); uint32_t alignment = get_ptr_align(g, ptr_type); - return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); + bool is_volatile = ptr_type->data.pointer.is_volatile; + return gen_load_untyped(g, elem_llvm_ty, ptr, alignment, is_volatile, name); } static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) { @@ -1090,7 +1092,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace msg_arg, stack_trace_arg, }; - ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); + ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); if (!stack_trace_is_llvm_alloca) { // The stack trace argument is not in the stack of the caller, so // we'd like to set tail call here, but because slices (the type of msg_arg) are @@ -1265,26 +1267,37 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { LLVMValueRef address_value = LLVMGetParam(fn_val, 1); size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; - LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); + LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + err_ret_trace_ptr, (unsigned)index_field_index, ""); size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); + LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + err_ret_trace_ptr, (unsigned)addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); - - LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); - LLVMValueRef index_val = gen_load_untyped(g, index_field_ptr, 0, false, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)len_field_index, ""); + + LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + len_field_ptr, 0, false, ""); + LLVMValueRef index_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(index_field_ptr), + index_field_ptr, 0, false, ""); LLVMValueRef len_val_minus_one = LLVMBuildSub(g->builder, len_value, LLVMConstInt(usize_type_ref, 1, false), ""); LLVMValueRef masked_val = LLVMBuildAnd(g->builder, index_val, len_val_minus_one, ""); LLVMValueRef address_indices[] = { masked_val, }; - LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); - LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); + LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); + LLVMValueRef address_slot = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, ptr_value, address_indices, 1, ""); gen_store_untyped(g, address_value, address_slot, 0, false); @@ -1340,7 +1353,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32)); - LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef return_address_ptr = LLVMBuildCall2(g->builder, + LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); @@ -1355,7 +1369,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block); LLVMValueRef args[] = { err_ret_trace_ptr, return_address }; - ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, + ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMBuildRetVoid(g->builder); @@ -1446,25 +1461,32 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMConstNull(usize_ty->llvm_type), err_val, }; - LLVMValueRef err_name_val = LLVMBuildInBoundsGEP(g->builder, g->err_name_table, err_table_indices, 2, ""); + LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, + get_llvm_type(g, str_type), + g->err_name_table, err_table_indices, 2, ""); - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_ptr_index, ""); - LLVMValueRef err_name_ptr = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_ptr_index, ""); + LLVMValueRef err_name_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, ""); - LLVMValueRef err_name_len = gen_load_untyped(g, len_field_ptr, 0, false, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_len_index, ""); + LLVMValueRef err_name_len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + len_field_ptr, 0, false, ""); LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false); // Points to the beginning of msg_buffer LLVMValueRef msg_buffer_ptr_indices[] = { LLVMConstNull(usize_ty->llvm_type), }; - LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_indices, 1, ""); + LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer, + msg_buffer_ptr_indices, 1, ""); // Points to the beginning of the constant prefix message LLVMValueRef msg_prefix_ptr_indices[] = { LLVMConstNull(usize_ty->llvm_type), }; - LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP(msg_prefix, msg_prefix_ptr_indices, 1); + LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP2(LLVMInt8Type(), msg_prefix, msg_prefix_ptr_indices, 1); // Build the message using the prefix... ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr, 1, msg_prefix_ptr, 1, msg_prefix_len, false); @@ -1472,16 +1494,18 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMValueRef msg_buffer_ptr_after_indices[] = { msg_prefix_len, }; - LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_after_indices, 1, ""); + LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer, msg_buffer_ptr_after_indices, 1, ""); ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr_after, 1, err_name_ptr, 1, err_name_len, false); // Set the slice pointer - LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_ptr_index, ""); + LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, str_type), msg_slice, slice_ptr_index, ""); gen_store_untyped(g, msg_buffer_ptr, msg_slice_ptr_field_ptr, 0, false); // Set the slice length LLVMValueRef slice_len = LLVMBuildNUWAdd(g->builder, msg_prefix_len, err_name_len, ""); - LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_len_index, ""); + LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, str_type), msg_slice, slice_len_index, ""); gen_store_untyped(g, slice_len, msg_slice_len_field_ptr, 0, false); // Call panic() @@ -1522,13 +1546,15 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc err_ret_trace_val, err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, + call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } else { LLVMValueRef args[] = { err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1, + call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + safety_crash_err_fn, args, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } if (!is_llvm_alloca) { @@ -1573,7 +1599,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, static void add_sentinel_check(CodeGen *g, LLVMValueRef sentinel_elem_ptr, ZigValue *sentinel) { LLVMValueRef expected_sentinel = gen_const_val(g, sentinel, ""); - LLVMValueRef actual_sentinel = gen_load_untyped(g, sentinel_elem_ptr, 0, false, ""); + LLVMValueRef actual_sentinel = gen_load_untyped(g, LLVMTypeOf(expected_sentinel), sentinel_elem_ptr, 0, false, ""); LLVMValueRef ok_bit; if (sentinel->type->id == ZigTypeIdFloat) { ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, actual_sentinel, expected_sentinel, ""); @@ -1706,7 +1732,7 @@ static LLVMValueRef gen_soft_float_widen_or_shorten(CodeGen *g, ZigType *actual_ func_ref = LLVMAddFunction(g->module, fn_name, fn_type); } - result = LLVMBuildCall(g->builder, func_ref, &expr_val, 1, ""); + result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &expr_val, 1, ""); // On non-Arm platforms we need to bitcast __trunc<>fhf2 result back to f16 if (castTruncatedToF16) { @@ -1852,7 +1878,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul val1, val2, }; - LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); if (operand_type->id == ZigTypeIdVector) { @@ -2272,9 +2298,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ fn_walk->data.attrs.gen_i += 1; break; case FnWalkIdCall: { - LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0); - LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, val, ptr_to_int_type_ref, ""); - LLVMValueRef loaded = LLVMBuildLoad(g->builder, bitcasted, ""); + LLVMTypeRef ptr_elem_llvm_ty = LLVMIntType((unsigned)ty_size * 8); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, ptr_elem_llvm_ty, val, ""); fn_walk->data.call.gen_param_values->append(loaded); break; } @@ -2342,18 +2367,17 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ break; } case FnWalkIdCall: { - LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, val, LLVMPointerType(abi_type, 0), ""); if (number_of_regs == 1) { - LLVMValueRef loaded = LLVMBuildLoad(g->builder, abi_ptr_to_struct, ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, abi_type, val, ""); fn_walk->data.call.gen_param_values->append(loaded); break; } for (uint32_t i = 0; i < number_of_regs; i += 1) { - LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false); - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false); - LLVMValueRef indices[] = { zero, index }; - LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, ""); - LLVMValueRef loaded = LLVMBuildLoad(g->builder, adjusted_ptr_to_struct, ""); + LLVMValueRef adjusted_ptr_to_struct = LLVMBuildStructGEP2(g->builder, + abi_type, val, i, ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(adjusted_ptr_to_struct), + adjusted_ptr_to_struct, ""); fn_walk->data.call.gen_param_values->append(loaded); } break; @@ -2388,13 +2412,13 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, var->value_ref, ptr_to_int_type_ref, ""); gen_store_untyped(g, arg, bitcasted, var->align_bytes, false); } else { - LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, var->value_ref, LLVMPointerType(abi_type, 0), ""); for (uint32_t i = 0; i < number_of_regs; i += 1) { LLVMValueRef arg = LLVMGetParam(llvm_fn, fn_walk->data.inits.gen_i + i); LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false); LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false); LLVMValueRef indices[] = { zero, index }; - LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, ""); + LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP2(g->builder, + abi_type, var->value_ref, indices, 2, ""); LLVMBuildStore(g->builder, arg, adjusted_ptr_to_struct); } fn_walk->data.inits.gen_i += 1; @@ -2573,8 +2597,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(fn_val, "NonNull"); - LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index"); - LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frames_left"); + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; + LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frame_index"); + LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frames_left"); LLVMValueRef dest_stack_trace_ptr = LLVMGetParam(fn_val, 0); LLVMValueRef src_stack_trace_ptr = LLVMGetParam(fn_val, 1); @@ -2589,18 +2614,27 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, non_null_block); size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, + LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr, (unsigned)src_index_field_index, ""); - LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, + LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr, (unsigned)src_addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(src_addresses_field_ptr), + src_addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)len_field_index, ""); - LLVMValueRef src_index_val = LLVMBuildLoad(g->builder, src_index_field_ptr, ""); - LLVMValueRef src_ptr_val = LLVMBuildLoad(g->builder, src_ptr_field_ptr, ""); - LLVMValueRef src_len_val = LLVMBuildLoad(g->builder, src_len_field_ptr, ""); + LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(src_addresses_field_ptr), + src_addresses_field_ptr, (unsigned)len_field_index, ""); + LLVMValueRef src_index_val = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(src_index_field_ptr), src_index_field_ptr, ""); + LLVMValueRef src_ptr_val = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); + LLVMValueRef src_len_val = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(src_len_field_ptr), src_len_field_ptr, ""); LLVMValueRef no_wrap_bit = LLVMBuildICmp(g->builder, LLVMIntULT, src_index_val, src_len_val, ""); LLVMBasicBlockRef no_wrap_block = LLVMAppendBasicBlock(fn_val, "NoWrap"); LLVMBasicBlockRef yes_wrap_block = LLVMAppendBasicBlock(fn_val, "YesWrap"); @@ -2608,14 +2642,14 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildCondBr(g->builder, no_wrap_bit, no_wrap_block, yes_wrap_block); LLVMPositionBuilderAtEnd(g->builder, no_wrap_block); - LLVMValueRef usize_zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); + LLVMValueRef usize_zero = LLVMConstNull(usize_type_ref); LLVMBuildStore(g->builder, usize_zero, frame_index_ptr); LLVMBuildStore(g->builder, src_index_val, frames_left_ptr); LLVMValueRef frames_left_eq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_index_val, usize_zero, ""); LLVMBuildCondBr(g->builder, frames_left_eq_zero_bit, return_block, loop_block); LLVMPositionBuilderAtEnd(g->builder, yes_wrap_block); - LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false); + LLVMValueRef usize_one = LLVMConstInt(usize_type_ref, 1, false); LLVMValueRef plus_one = LLVMBuildNUWAdd(g->builder, src_index_val, usize_one, ""); LLVMValueRef mod_len = LLVMBuildURem(g->builder, plus_one, src_len_val, ""); LLVMBuildStore(g->builder, mod_len, frame_index_ptr); @@ -2623,12 +2657,15 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildBr(g->builder, loop_block); LLVMPositionBuilderAtEnd(g->builder, loop_block); - LLVMValueRef ptr_index = LLVMBuildLoad(g->builder, frame_index_ptr, ""); - LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, ""); - LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, ""); + LLVMValueRef ptr_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); + LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP2(g->builder, + usize_type_ref, src_ptr_val, &ptr_index, 1, ""); + LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, LLVMGetGEPSourceElementType(addr_ptr), + addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; - ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); - LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, ""); + ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); + LLVMValueRef prev_frames_left = LLVMBuildLoad2(g->builder, usize_type_ref, frames_left_ptr, ""); LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, ""); LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, ""); LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(fn_val, "Continue"); @@ -2639,7 +2676,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, continue_block); LLVMBuildStore(g->builder, new_frames_left, frames_left_ptr); - LLVMValueRef prev_index = LLVMBuildLoad(g->builder, frame_index_ptr, ""); + LLVMValueRef prev_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); LLVMValueRef index_plus_one = LLVMBuildNUWAdd(g->builder, prev_index, usize_one, ""); LLVMValueRef index_mod_len = LLVMBuildURem(g->builder, index_plus_one, src_len_val, ""); LLVMBuildStore(g->builder, index_mod_len, frame_index_ptr); @@ -2666,13 +2703,14 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executabl bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope, &is_llvm_alloca); - ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1, + ZigLLVMBuildCall(g->builder, LLVMTypeOf(return_err_fn), return_err_fn, &my_err_trace_val, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) { - LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, - frame_index_trace_arg(g, ret_type), ""); + ZigType *frame_type = get_fn_frame_type(g, g->cur_fn); + LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, frame_type), + g->cur_frame_ptr, frame_index_trace_arg(g, ret_type), ""); LLVMBuildStore(g->builder, my_err_trace_val, trace_ptr_ptr); } @@ -2702,16 +2740,20 @@ static void gen_assert_resume_id(CodeGen *g, Stage1AirInst *source_instr, Resume LLVMPositionBuilderAtEnd(g->builder, end_bb); } -static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr, ResumeId resume_id) { +static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr, + ResumeId resume_id) +{ LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; if (fn_val == nullptr) { - LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, ""); - fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); + LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, g->any_frame_header_llvm_ty, + target_frame_ptr, frame_fn_ptr_index, ""); + fn_val = LLVMBuildLoad2(g->builder, LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), + fn_ptr_ptr, ""); } LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref), LLVMConstInt(usize_type_ref, resume_id, false)); LLVMValueRef args[] = {target_frame_ptr, arg_val}; - return ZigLLVMBuildCall(g->builder, fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); + return ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); } static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { @@ -2733,11 +2775,11 @@ static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) { LLVMSetTailCall(call_inst, true); } -static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val, - LLVMAtomicOrdering order) +static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, + LLVMValueRef val, LLVMAtomicOrdering order) { if (g->is_single_threaded) { - LLVMValueRef loaded = LLVMBuildLoad(g->builder, ptr, ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, LLVMTypeOf(val), ptr, ""); LLVMValueRef modified; switch (op) { case LLVMAtomicRMWBinOpXchg: @@ -2811,8 +2853,11 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { // If the awaiter result pointer is non-null, we need to copy the result to there. LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); - LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, ""); - LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); + LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_ret_start + 1, ""); + LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad2(g->builder, + LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), awaiter_ret_ptr_ptr, ""); LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block); @@ -2831,20 +2876,25 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { LLVMPositionBuilderAtEnd(g->builder, copy_end_block); if (codegen_fn_has_err_ret_tracing_arg(g, ret_type)) { - LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, - frame_index_trace_arg(g, ret_type) + 1, ""); - LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, awaiter_trace_ptr_ptr, ""); + LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_index_trace_arg(g, ret_type) + 1, ""); + LLVMValueRef dest_trace_ptr = LLVMBuildLoad2(g->builder, + LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), + awaiter_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val }; - ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, + ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } } // Resume the caller by tail calling them. ZigType *any_frame_type = get_any_frame_type(g, ret_type); - LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val, get_llvm_type(g, any_frame_type), ""); + LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val, + get_llvm_type(g, any_frame_type), ""); LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn); set_tail_call_if_appropriate(g, call_inst); LLVMBuildRetVoid(g->builder); @@ -2853,21 +2903,14 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { static LLVMValueRef gen_convert_to_c_abi(CodeGen *g, LLVMValueRef location, LLVMValueRef value) { ZigType *return_type = g->cur_fn->type_entry->data.fn.gen_return_type; size_t size = type_size(g, return_type); - LLVMTypeRef abi_return_type = get_llvm_c_abi_type(g, return_type); - LLVMTypeRef abi_return_type_pointer = LLVMPointerType(abi_return_type, 0); if (size < 8) { - LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, value, abi_return_type_pointer, ""); - return LLVMBuildLoad(g->builder, bitcast, ""); + return LLVMBuildLoad2(g->builder, abi_return_type, value, ""); } else { - LLVMTypeRef i8ptr = LLVMPointerType(LLVMInt8Type(), 0); - LLVMValueRef bc_location = LLVMBuildBitCast(g->builder, location, i8ptr, ""); - LLVMValueRef bc_value = LLVMBuildBitCast(g->builder, value, i8ptr, ""); - LLVMValueRef len = LLVMConstInt(LLVMInt64Type(), size, false); - ZigLLVMBuildMemCpy(g->builder, bc_location, 8, bc_value, return_type->abi_align, len, false); - return LLVMBuildLoad(g->builder, location, ""); + ZigLLVMBuildMemCpy(g->builder, location, 8, value, return_type->abi_align, len, false); + return LLVMBuildLoad2(g->builder, abi_return_type, location, ""); } } @@ -2903,19 +2946,21 @@ static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, Stage1Ai } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync && handle_is_ptr(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type)) { + LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type); if (instruction->operand == nullptr) { - LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } else { LLVMValueRef value = ir_llvm_value(g, instruction->operand); - LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, ""); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, value, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } } else if (instruction->operand == nullptr) { if (g->cur_ret_ptr == nullptr) { LLVMBuildRetVoid(g->builder); } else { - LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); + LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } } else { @@ -3011,20 +3056,18 @@ static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *o float_un_op_to_name(op_id), libc_float_suffix(g, scalar_type)); LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type); - LLVMValueRef result; if (vector_len == 0) { - return LLVMBuildCall(g->builder, func_ref, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &op, 1, ""); } else { - result = build_alloca(g, operand_type, "", 0); + LLVMValueRef result = LLVMGetUndef(operand_type->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); LLVMValueRef param = LLVMBuildExtractElement(g->builder, op, index_value, ""); - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, ¶m, 1, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, ¶m, 1, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } - return LLVMBuildLoad(g->builder, result, ""); + return result; } } @@ -3038,7 +3081,7 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o return gen_soft_float_un_op(g, operand, operand_type, op); } LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); - return LLVMBuildCall(g->builder, float_op_fn, &operand, 1, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(float_op_fn), float_op_fn, &operand, 1, ""); } enum DivKind { @@ -3404,7 +3447,7 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - return LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); } static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { @@ -3440,7 +3483,7 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, ""); @@ -3553,12 +3596,12 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[2] = {op1_value, op2_value}; - result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); result = add_icmp(g, result, res_icmp); } else { ZigType *alloca_ty = operand_type; if (res_icmp != NONE) alloca_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool); - result = build_alloca(g, alloca_ty, "", 0); + result = LLVMGetUndef(alloca_ty->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { @@ -3567,13 +3610,10 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); call_result = add_icmp(g, call_result, res_icmp); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } - - result = LLVMBuildLoad(g->builder, result, ""); } // Some operations are implemented as compound ops and require us to perform some @@ -3703,7 +3743,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, } // TODO runtime safety - return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, ""); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, scalar_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, op1_value, + &subscript_value, 1, ""); } else if (scalar_type->id == ZigTypeIdFloat) { ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); return float_op[add_sub_mul](g->builder, op1_value, op2_value, ""); @@ -4044,20 +4086,23 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *execu assert(array_type->id == ZigTypeIdArray); if (type_has_bits(g, actual_type)) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), + result_loc, ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false), }; LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, ""); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); + LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, expr_val, + indices, 2, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (ir_want_runtime_safety(g, &instruction->base) && ptr_index != SIZE_MAX) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, ptr_index, ""); gen_undef_init(g, slice_ptr_type, slice_ptr_type, ptr_field_ptr); } - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, len_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, len_index, ""); LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); gen_store_untyped(g, len_value, len_field_ptr, 0, false); @@ -4102,20 +4147,20 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, Stage1Air *executable, bool actual_is_ptr = handle_is_ptr(g, actual_type); if (wanted_is_ptr == actual_is_ptr) { // We either bitcast the value directly or bitcast the pointer which does a pointer cast - LLVMTypeRef wanted_type_ref = wanted_is_ptr ? - LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type); - return LLVMBuildBitCast(g->builder, value, wanted_type_ref, ""); + if (wanted_is_ptr) { + return value; + } else { + LLVMTypeRef wanted_type_ref = get_llvm_type(g, wanted_type); + return LLVMBuildBitCast(g->builder, value, wanted_type_ref, ""); + } } else if (actual_is_ptr) { // A scalar is wanted but we got a pointer - LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0); - LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, ""); uint32_t alignment = get_abi_alignment(g, actual_type); - return gen_load_untyped(g, bitcasted_ptr, alignment, false, ""); + return gen_load_untyped(g, get_llvm_type(g, wanted_type), value, alignment, false, ""); } else { // A pointer is wanted but we got a scalar assert(actual_type->id == ZigTypeIdPointer); - LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0); - return LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, ""); + return value; } } @@ -4298,32 +4343,26 @@ static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, static LLVMValueRef gen_soft_float_neg(CodeGen *g, ZigType *operand_type, LLVMValueRef operand) { uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; - uint16_t num_bits = operand_type->data.floating.bit_count; + uint16_t num_bits = operand_type->id == ZigTypeIdVector ? + operand_type->data.vector.elem_type->data.floating.bit_count : + operand_type->data.floating.bit_count; ZigType *iX_type = get_int_type(g, true, num_bits); - LLVMValueRef sign_mask = LLVMConstInt(iX_type->llvm_type, 1, false); - sign_mask = LLVMConstShl(sign_mask, LLVMConstInt(iX_type->llvm_type, num_bits - 1, false)); + LLVMValueRef sign_mask = LLVMConstShl( + LLVMConstInt(iX_type->llvm_type, 1, false), + LLVMConstInt(iX_type->llvm_type, num_bits - 1, false)); - if (vector_len == 0) { - LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, iX_type->llvm_type, ""); - LLVMValueRef result = LLVMBuildXor(g->builder, bitcasted_operand, sign_mask, ""); + LLVMValueRef sign_mask_splat = (vector_len == 0) ? sign_mask : + LLVMBuildVectorSplat(g->builder, vector_len, sign_mask, ""); - return LLVMBuildBitCast(g->builder, result, operand_type->llvm_type, ""); - } else { - LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; - ZigType *iX_vector_type = get_vector_type(g, vector_len, iX_type); + LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, + (vector_len == 0) ? + iX_type->llvm_type : + get_vector_type(g, vector_len, iX_type)->llvm_type, + ""); - LLVMValueRef result = build_alloca(g, iX_vector_type, "", 0); - LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, iX_vector_type->llvm_type, ""); - for (uint32_t i = 0; i < vector_len; i++) { - LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); - LLVMValueRef elem = LLVMBuildExtractElement(g->builder, bitcasted_operand, index_value, ""); - LLVMValueRef result_elem = LLVMBuildXor(g->builder, elem, sign_mask, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - result_elem, index_value, ""); - } - return LLVMBuildBitCast(g->builder, LLVMBuildLoad(g->builder, result, ""), operand_type->llvm_type, ""); - } + LLVMValueRef result = LLVMBuildXor(g->builder, bitcasted_operand, sign_mask_splat, ""); + return LLVMBuildBitCast(g->builder, result, operand_type->llvm_type, ""); } static LLVMValueRef gen_negation(CodeGen *g, Stage1AirInst *inst, Stage1AirInst *operand, bool wrapping) { @@ -4398,7 +4437,7 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.vector_index, false); - LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, ""); + LLVMValueRef loaded_vector = LLVMBuildLoad2(g->builder, get_llvm_type(g, child_type), ptr, ""); return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, ""); } @@ -4524,7 +4563,8 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default zero, LLVMConstInt(usize_type_ref, i, false), }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, + array_ptr, indexes, 2, ""); LLVMBuildStore(g->builder, array_elements[i], elem_ptr); } @@ -4545,7 +4585,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template), buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack, LLVMInlineAsmDialectATT, false); - return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, input_and_output_count, ""); } } zig_unreachable(); @@ -4713,16 +4753,13 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 size_t host_int_bytes = ptr_type->data.pointer.host_int_bytes; if (host_int_bytes != 0) { uint32_t size_in_bits = type_size_bits(g, ptr_type->data.pointer.child_type); - LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); - LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); assert(size_in_bits % 8 == 0); LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, size_in_bits / 8, false); LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); - LLVMValueRef indices[] = { - byte_offset - }; - LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, ""); + LLVMValueRef indices[] = { byte_offset }; + LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), + array_ptr, indices, 1, ""); return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(get_llvm_type(g, child_type), 0), ""); } } @@ -4730,14 +4767,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), subscript_value }; - return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, child_type), array_ptr, + indices, 2, ""); } else if (array_type->id == ZigTypeIdPointer) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - LLVMValueRef indices[] = { - subscript_value - }; - return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, ""); + LLVMValueRef indices[] = { subscript_value }; + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 1, ""); } else if (array_type->id == ZigTypeIdStruct) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); assert(array_type->data.structure.special == StructSpecialSlice); @@ -4752,22 +4789,26 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 } assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); if (safety_check_on) { size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); - LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); - LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); + LLVMValueRef len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), + array_ptr, (unsigned)len_index, ""); + LLVMValueRef len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_ptr), len_ptr, + 0, false, ""); LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT; add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len); } size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); - LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); - LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); - return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, ""); + LLVMValueRef ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), + array_ptr, (unsigned)ptr_index, ""); + LLVMValueRef ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_ptr), ptr_ptr, 0, + false, ""); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, ptr, &subscript_value, 1, ""); } else if (array_type->id == ZigTypeIdVector) { return array_ptr_ptr; } else { @@ -4775,12 +4816,16 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 } } -static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, ""); +static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMTypeRef new_stack_llvm_ty, + LLVMValueRef new_stack) +{ + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_ptr_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_len_index, ""); - LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); - LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); + LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); + LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + len_field_ptr, 0, false, ""); LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), ""); LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, ""); @@ -4804,7 +4849,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { aligned_end_addr, }; - LLVMBuildCall(g->builder, write_register_fn_val, params, 2, ""); + LLVMBuildCall2(g->builder, LLVMTypeOf(write_register_fn_val), write_register_fn_val, params, 2, ""); } static void render_async_spills(CodeGen *g) { @@ -4834,7 +4879,9 @@ static void render_async_spills(CodeGen *g) { } calc_llvm_field_index_add(g, &arg_calc, var->var_type); - var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, arg_calc.field_index - 1, var->name); + var->value_ref = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, arg_calc.field_index - 1, var->name); if (var->decl_node) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, import->data.structure.root_struct->di_file, @@ -4852,7 +4899,9 @@ static void render_async_spills(CodeGen *g) { continue; size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index; - instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index, + instruction->base.llvm_value = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, gen_index, instruction->name_hint); } } @@ -4892,11 +4941,9 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { assert(g->need_frame_size_prefix_data); LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type; - LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0); - LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, ""); LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true); - LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP(g->builder, casted_fn_val, &negative_one, 1, ""); - LLVMValueRef load_inst = LLVMBuildLoad(g->builder, prefix_ptr, ""); + LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_llvm_type, fn_val, &negative_one, 1, ""); + LLVMValueRef load_inst = LLVMBuildLoad2(g->builder, usize_llvm_type, prefix_ptr, ""); // Some architectures (e.g SPARCv9) has different alignment requirements between a // function/usize pointer and also require all loads to be aligned. @@ -4910,17 +4957,23 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); + LLVMTypeRef stack_trace_llvm_ty = get_llvm_type(g, get_stack_trace_type(g)); - LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); + LLVMValueRef index_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 0, ""); LLVMBuildStore(g->builder, zero, index_ptr); - LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 1, ""); - LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_ptr_index, ""); + LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 1, ""); + LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addrs_slice_ptr), + addrs_slice_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; - LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP(g->builder, addrs_field_ptr, indices, 2, ""); + LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP2(g->builder, + usize_type_ref, addrs_field_ptr, indices, 2, ""); LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); - LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_len_index, ""); + LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addrs_slice_ptr), + addrs_slice_ptr, slice_len_index, ""); LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } @@ -4943,6 +4996,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI callee_is_async = fn_type->data.fn.fn_type_id.cc == CallingConventionAsync; } + LLVMTypeRef frame_struct_llvm_ty = (instruction->fn_entry != nullptr) ? + get_llvm_type(g, get_fn_frame_type(g, instruction->fn_entry)) : + g->any_frame_header_llvm_ty; + FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; ZigType *src_return_type = fn_type_id->return_type; @@ -4971,8 +5028,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); ir_assert(instruction->fn_entry != nullptr, &instruction->base); - frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, - LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); + frame_result_loc = frame_result_loc_uncasted; } } else { if (instruction->new_stack->value->type->id == ZigTypeIdPointer && @@ -4981,9 +5037,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI frame_result_loc = ir_llvm_value(g, instruction->new_stack); } else { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); + LLVMTypeRef frame_slice_llvm_ty = + get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type); if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, ""); - LLVMValueRef given_frame_len = LLVMBuildLoad(g->builder, given_len_ptr, ""); + LLVMValueRef given_len_ptr = LLVMBuildStructGEP2(g->builder, + frame_slice_llvm_ty, frame_slice_ptr, slice_len_index, ""); + LLVMValueRef given_frame_len = LLVMBuildLoad2(g->builder, usize_type_ref, given_len_ptr, ""); LLVMValueRef actual_frame_len = gen_frame_size(g, fn_val); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckFail"); @@ -4998,18 +5057,18 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMPositionBuilderAtEnd(g->builder, ok_block); } need_frame_ptr_ptr_spill = true; - LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, ""); - LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, ""); + LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_slice_llvm_ty, + frame_slice_ptr, slice_ptr_index, ""); + LLVMValueRef frame_ptr = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); - frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); + frame_result_loc = frame_ptr; } else { ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry); if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull))) codegen_report_errors_and_exit(g); - ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false); - frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, - get_llvm_type(g, ptr_frame_type), ""); + frame_result_loc = frame_ptr; } } } @@ -5019,7 +5078,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (ret_has_bits) { // Use the result location which is inside the frame if this is an async call. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); } } else { awaiter_init_val = zero; @@ -5030,7 +5090,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ret_ptr = result_loc; } else { // no result location provided to @asyncCall - use the one inside the frame. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); } } } @@ -5050,20 +5111,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (ret_has_bits) { if (result_loc == nullptr) { // return type is a scalar, but we still need a pointer to it. Use the async fn frame. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, ""); } else { // Use the call instruction's result location. ret_ptr = result_loc; } // Store a zero in the awaiter's result ptr to indicate we do not need a copy made. - LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, ""); + LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 1, ""); LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr))); LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); } if (prefix_arg_err_ret_stack) { - LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_index_trace_arg(g, src_return_type) + 1, ""); bool is_llvm_alloca; LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, @@ -5074,19 +5135,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI assert(frame_result_loc != nullptr); - LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, ""); + LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_fn_ptr_index, ""); LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), ""); LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); - LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_resume_index, ""); + LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_resume_index, ""); LLVMBuildStore(g->builder, zero, resume_index_ptr); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); if (ret_has_bits) { - LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); + LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, ""); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); } } else if (instruction->modifier == CallModifierAsync) { @@ -5097,12 +5158,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI frame_result_loc = result_loc; awaiter_init_val = LLVMConstAllOnes(usize_type_ref); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); if (ret_has_bits) { - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); - LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, ""); + LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, ""); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); if (first_arg_ret) { @@ -5113,11 +5174,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI // Then we have to wire up the StackTrace pointers. // Await is responsible for merging error return traces. uint32_t trace_field_index_start = frame_index_trace_arg(g, src_return_type); - LLVMValueRef callee_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef callee_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start, ""); - LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start + 2, ""); - LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start + 3, ""); LLVMBuildStore(g->builder, trace_field_ptr, callee_trace_ptr_ptr); @@ -5177,7 +5238,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI CalcLLVMFieldIndex arg_calc_start = {0}; frame_index_arg_calc(g, &arg_calc_start, fn_type->data.fn.fn_type_id.return_type); - LLVMValueRef casted_frame; + LLVMTypeRef casted_frame_llvm_ty; if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) { // We need the frame type to be a pointer to a struct that includes the args @@ -5208,17 +5269,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } LLVMTypeRef frame_with_args_type = LLVMStructType(field_types, field_count, false); heap::c_allocator.deallocate(field_types, field_count); - LLVMTypeRef ptr_frame_with_args_type = LLVMPointerType(frame_with_args_type, 0); - - casted_frame = LLVMBuildBitCast(g->builder, frame_result_loc, ptr_frame_with_args_type, ""); + casted_frame_llvm_ty = frame_with_args_type; } else { - casted_frame = frame_result_loc; + casted_frame_llvm_ty = frame_struct_llvm_ty; } CalcLLVMFieldIndex arg_calc = arg_calc_start; for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i)); - LLVMValueRef arg_ptr = LLVMBuildStructGEP(g->builder, casted_frame, arg_calc.field_index - 1, ""); + LLVMValueRef arg_ptr = LLVMBuildStructGEP2(g->builder, casted_frame_llvm_ty, frame_result_loc, arg_calc.field_index - 1, ""); gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true), gen_param_values.at(arg_i)); } @@ -5235,8 +5294,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, - frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_awaiter_index, ""); LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref); LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, all_ones, LLVMAtomicOrderingRelease); @@ -5255,7 +5314,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *result_type = instruction->base.value->type; ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); - return gen_await_early_return(g, &instruction->base, frame_result_loc, + return gen_await_early_return(g, &instruction->base, + frame_struct_llvm_ty, frame_result_loc, result_type, ptr_result_type, result_loc, true); } else { ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true); @@ -5284,8 +5344,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (need_frame_ptr_ptr_spill) { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); - LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, ""); - frame_result_loc_uncasted = LLVMBuildLoad(g->builder, frame_ptr_ptr, ""); + LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type), + frame_slice_ptr, slice_ptr_index, ""); + frame_result_loc_uncasted = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { @@ -5297,31 +5360,34 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } } - LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); - return LLVMBuildLoad(g->builder, result_ptr, ""); + LLVMValueRef result_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); + return LLVMBuildLoad2(g->builder, get_llvm_type(g, src_return_type), result_ptr, ""); } } else { gen_param_types.deinit(); } if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) { - result = ZigLLVMBuildCall(g->builder, fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); } else if (instruction->modifier == CallModifierAsync) { zig_panic("TODO @asyncCall of non-async function"); } else { - LLVMValueRef new_stack_addr = get_new_stack_addr(g, ir_llvm_value(g, instruction->new_stack)); + LLVMValueRef new_stack_addr = get_new_stack_addr(g, + get_llvm_type(g, instruction->new_stack->value->type), + ir_llvm_value(g, instruction->new_stack)); LLVMValueRef old_stack_ref; if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); - old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, ""); + old_stack_ref = LLVMBuildCall2(g->builder, LLVMTypeOf(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); } gen_set_stack_pointer(g, new_stack_addr); - result = ZigLLVMBuildCall(g->builder, fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); - LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, ""); + LLVMBuildCall2(g->builder, LLVMTypeOf(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); } } @@ -5361,6 +5427,8 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr); // not necessarily a pointer. could be ZigTypeIdStruct ZigType *struct_ptr_type = instruction->struct_ptr->value->type; + ZigType *struct_ty = (struct_ptr_type->id == ZigTypeIdPointer) ? + struct_ptr_type->data.pointer.child_type : struct_ptr_type; TypeStructField *field = instruction->field; if (!type_has_bits(g, field->type_entry)) @@ -5387,7 +5455,8 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable codegen_report_errors_and_exit(g); ir_assert(field->gen_index != SIZE_MAX, &instruction->base); - LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); + LLVMValueRef field_ptr_val = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, struct_ty), struct_ptr, (unsigned)field->gen_index, ""); ZigType *res_type = instruction->base.value->type; ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); if (res_type->data.pointer.host_int_bytes != 0) { @@ -5432,8 +5501,9 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMPointerType(tag_type_ref, 0), ""); } else { assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); - tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_tag_index, ""); + tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); } LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, @@ -5448,19 +5518,25 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0); if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, ""); + LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), union_ptr, 0, ""); LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); return bitcasted_union_field_ptr; } if (instruction->initializing) { - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), &field->enum_field->value); gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); + LLVMValueRef tag_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(tag_field_ptr), + tag_field_ptr, 0, false, ""); LLVMValueRef expected_tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), @@ -5476,10 +5552,9 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMPositionBuilderAtEnd(g->builder, ok_block); } - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_union_index, ""); - LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); - return bitcasted_union_field_ptr; + LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_union_index, ""); + return union_field_ptr; } static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok, Buf *src_template) { @@ -5660,7 +5735,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { if (param_needs_attr[i]) { @@ -5689,8 +5764,9 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR if (is_scalar) return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); - LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); - return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); + LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), maybe_handle, maybe_null_index, ""); + return gen_load_untyped(g, LLVMGetGEPSourceElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); } static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, @@ -5736,12 +5812,13 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, Stage1Air *executa } else { LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type); if (instruction->initializing) { - LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP(g->builder, optional_struct_ref, - maybe_null_index, ""); + LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), optional_struct_ref, maybe_null_index, ""); LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false); gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false); } - return LLVMBuildStructGEP(g->builder, optional_struct_ref, maybe_child_index, ""); + return LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), optional_struct_ref, maybe_child_index, ""); } } } @@ -5818,7 +5895,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5830,7 +5907,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5887,7 +5964,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, Stage ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &operand, 1, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5978,7 +6055,11 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; - return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); + ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, + PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); + ZigType *str_type = get_slice_type(g, u8_ptr_type); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, str_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, g->err_name_table, indices, 2, ""); } static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { @@ -6050,7 +6131,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMSetAlignment(str_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(str_init))); LLVMValueRef fields[] = { - LLVMConstGEP(str_global, array_ptr_indices, 2), + LLVMConstInBoundsGEP2(LLVMInt8Type(), str_global, array_ptr_indices, 2), LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false), }; LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, u8_slice_type), fields, 2); @@ -6099,7 +6180,8 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); - return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1, + return ZigLLVMBuildCall(g->builder, LLVMTypeOf(enum_name_function), enum_name_function, + &enum_tag_value, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -6166,8 +6248,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, Stag align_bytes = get_ptr_align(g, slice_ptr_type); size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, ""); - ptr_val = gen_load_untyped(g, ptr_val_ptr, 0, false, ""); + LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, instruction->target->value->type->data.pointer.child_type), + target_val, (unsigned)ptr_index, ""); + ptr_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); } else { zig_unreachable(); } @@ -6319,12 +6403,16 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, Stage1Air *executable, Stage1A if (actual_abi_type != nullptr) { payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), ""); } - LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); + LLVMTypeRef result_loc_struct_llvm_ty = get_llvm_type(g, + instruction->result_loc->value->type->data.pointer.child_type); + LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder, + result_loc_struct_llvm_ty, result_loc, maybe_child_index, ""); gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); - LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, ""); + LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_loc_struct_llvm_ty, result_loc, + maybe_null_index, ""); gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false); return result_loc; } @@ -6469,7 +6557,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, Stage1Ai static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemorySize *instruction) { // TODO adjust for wasm64 LLVMValueRef param = ir_llvm_value(g, instruction->index); - LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), ¶m, 1, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); return val; } @@ -6479,7 +6567,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable ir_llvm_value(g, instruction->index), ir_llvm_value(g, instruction->delta), }; - LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); return val; } @@ -6525,7 +6613,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstInt(LLVMInt32Type(), instruction->locality, false), LLVMConstInt(LLVMInt32Type(), instruction->cache, false), }; - LLVMValueRef val = LLVMBuildCall(g->builder, gen_prefetch(g), params, 4, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); return val; } @@ -6591,12 +6679,15 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); + if (want_runtime_safety && sentinel != nullptr) { LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), end_val, }; - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, + elem_llvm_ty, array_ptr, indices, 2, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } @@ -6604,7 +6695,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMConstNull(g->builtin_types.entry_usize->llvm_type), start_val, }; - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 2, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6623,27 +6714,31 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); + if (want_runtime_safety && sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &end_val, 1, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + array_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, + &start_val, 1, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); } else if (array_type->id == ZigTypeIdStruct) { assert(array_type->data.structure.special == StructSpecialSlice); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); const size_t gen_len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(gen_len_index != SIZE_MAX); LLVMValueRef prev_end = nullptr; if (!instruction->end || want_runtime_safety) { - LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, gen_len_index, ""); - prev_end = gen_load_untyped(g, src_len_ptr, 0, false, ""); + LLVMValueRef src_len_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, array_type), array_ptr, gen_len_index, ""); + prev_end = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_len_ptr), src_len_ptr, 0, false, ""); } LLVMValueRef start_val = ir_llvm_value(g, instruction->start); @@ -6682,18 +6777,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (ptr_has_bits) { + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_field_type->data.pointer.child_type); const size_t gen_ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(gen_ptr_index != SIZE_MAX); - LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, gen_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); + LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, array_type), array_ptr, gen_ptr_index, ""); + LLVMValueRef src_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_ptr_ptr), + src_ptr_ptr, 0, false, ""); if (sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &end_val, 1, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + src_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, src_ptr, &start_val, 1, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6735,7 +6834,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air // The slice may not have a pointer at all if it points to a zero-sized type const size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index; if (gen_ptr_index != SIZE_MAX) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, result_type), tmp_struct_ptr, gen_ptr_index, ""); if (slice_start_ptr != nullptr) { gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (want_runtime_safety) { @@ -6748,7 +6848,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air const size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index; assert(gen_len_index != SIZE_MAX); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, result_type), tmp_struct_ptr, gen_len_index, ""); gen_store_untyped(g, len_value, len_field_ptr, 0, false); return tmp_struct_ptr; @@ -6767,7 +6868,7 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, Stage1AirInstBreakpoint *instruction) { - LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); + LLVMBuildCall2(g->builder, LLVMTypeOf(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } @@ -6781,7 +6882,7 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, } LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6803,7 +6904,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6866,7 +6967,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, Sta op2, }; - LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); gen_store(g, result, ptr_result, instruction->result_ptr->value->type); @@ -6881,8 +6982,9 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, Stage1 LLVMValueRef err_val; if (type_has_bits(g, payload_type)) { - LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); + LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, err_union_type), err_union_handle, err_union_err_index, ""); + err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -6907,7 +7009,8 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, Stage1Air *executable, } else { // TODO assign undef to the payload LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); - return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); + return LLVMBuildStructGEP2(g->builder, get_llvm_type(g, err_union_type), err_union_handle, + err_union_err_index, ""); } } @@ -6946,11 +7049,14 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab return err_union_handle; } + LLVMTypeRef err_union_llvm_ty = get_llvm_type(g, err_union_type); + if (want_safety) { LLVMValueRef err_val; if (type_has_bits(g, payload_type)) { - LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); + LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, + err_union_handle, err_union_err_index, ""); + err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -6967,11 +7073,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab if (type_has_bits(g, payload_type)) { if (instruction->initializing) { - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, + err_union_handle, err_union_err_index, ""); LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); } - return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); + return LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, err_union_handle, + err_union_payload_index, ""); } else { if (instruction->initializing) { gen_store_untyped(g, zero, err_union_ptr, 0, false); @@ -7006,11 +7114,14 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, Stage1Air *executable, S } LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); + LLVMTypeRef result_llvm_struct_ty = get_llvm_type(g, wanted_type); - LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); + LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc, + maybe_child_index, ""); // child_type and instruction->value->value->type may differ by constness gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); - LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, ""); + LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc, + maybe_null_index, ""); gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false); return result_loc; @@ -7028,7 +7139,8 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, Stage1Air *executable, S LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, wanted_type), + result_loc, err_union_err_index, ""); gen_store_untyped(g, err_val, err_tag_ptr, 0, false); // TODO store undef to the payload @@ -7057,11 +7169,14 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, Stage1Air *executable LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand); + LLVMTypeRef result_struct_llvm_ty = get_llvm_type(g, wanted_type); - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc, + err_union_err_index, ""); gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); - LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, ""); + LLVMValueRef payload_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc, + err_union_payload_index, ""); gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val); return result_loc; @@ -7079,7 +7194,8 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, Stage1Air *executable, Stage return union_val; assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val, + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), union_val, union_type->data.unionation.gen_tag_index, ""); ZigType *ptr_type = get_pointer_to_type(g, tag_type, false); return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); @@ -7221,14 +7337,12 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); - LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[3] = { op1, op2, op3 }; - result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); - } else { - result = build_alloca(g, instruction->op1->value->type, "", 0); + return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); } + LLVMValueRef result = LLVMGetUndef(get_llvm_type(g, instruction->op1->value->type)); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); @@ -7238,12 +7352,8 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMBuildExtractElement(g->builder, op2, index_value, ""), LLVMBuildExtractElement(g->builder, op3, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); - } - if (vector_len != 0) { - result = LLVMBuildLoad(g->builder, result, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; } @@ -7262,7 +7372,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A instruction->base.value->type->id == ZigTypeIdVector); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); LLVMValueRef args[3] = { op1, op2, op3 }; - return LLVMBuildCall(g->builder, fn_val, args, 3, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, args, 3, ""); } static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1AirInstBswap *instruction) { @@ -7273,7 +7383,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air assert(int_type->id == ZigTypeIdInt); if (int_type->data.integral.bit_count % 16 == 0) { LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap); - return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); } // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, @@ -7292,7 +7402,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); - LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); + LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &extended, 1, ""); // ccbbaa00 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, ""); // 00ccbbaa @@ -7328,7 +7438,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, Sta ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value->type, BuiltinFnIdBitReverse); - return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); } static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, @@ -7341,6 +7451,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, LLVMValueRef vector = ir_llvm_value(g, instruction->vector); ZigType *elem_type = array_type->data.array.child_type; + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, elem_type); bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8; if (bitcast_ok) { LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, result_loc, @@ -7357,7 +7468,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); LLVMValueRef indexes[] = { zero, index_usize }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, result_loc, indexes, 2, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, result_loc, indexes, 2, ""); LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, ""); LLVMBuildStore(g->builder, elem, elem_ptr); } @@ -7377,12 +7488,10 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, ZigType *elem_type = vector_type->data.vector.elem_type; bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8; if (bitcast_ok) { - LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, - LLVMPointerType(vector_type_ref, 0), ""); ZigType *array_type = instruction->array->value->type; assert(array_type->id == ZigTypeIdArray); uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type); - return gen_load_untyped(g, casted_ptr, alignment, false, ""); + return gen_load_untyped(g, vector_type_ref, array_ptr, alignment, false, ""); } else { // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast // will not work, and we fall back to insertelement. @@ -7390,12 +7499,14 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, LLVMTypeRef u32_type_ref = LLVMInt32Type(); LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); LLVMValueRef vector = LLVMGetUndef(vector_type_ref); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, elem_type); for (uintptr_t i = 0; i < instruction->base.value->type->data.vector.len; i++) { LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); LLVMValueRef indexes[] = { zero, index_usize }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); - LLVMValueRef elem = LLVMBuildLoad(g->builder, elem_ptr, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, + indexes, 2, ""); + LLVMValueRef elem = LLVMBuildLoad2(g->builder, elem_llvm_ty, elem_ptr, ""); vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, ""); } return vector; @@ -7461,14 +7572,16 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, Stage1Air *executable, } static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr, - LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, - LLVMValueRef result_loc, bool non_async) + LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr, + ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef their_result_ptr = nullptr; if (type_has_bits(g, result_type) && (non_async || result_loc != nullptr)) { - LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, ""); - their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, ""); + LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP2(g->builder, + target_frame_struct_llvm_ty, target_frame_ptr, frame_ret_start, ""); + their_result_ptr = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); if (result_loc != nullptr) { LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, ""); @@ -7482,13 +7595,16 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins } } if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) { - LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, + LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + target_frame_struct_llvm_ty, target_frame_ptr, frame_index_trace_arg(g, result_type), ""); - LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, ""); + LLVMValueRef src_trace_ptr = LLVMBuildLoad2(g->builder, + LLVMGetGEPSourceElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; - ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, + ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } if (non_async && type_has_bits(g, result_type)) { @@ -7503,6 +7619,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); + LLVMTypeRef target_frame_llvm_ty = get_llvm_type(g, + instruction->frame->value->type->data.pointer.child_type); ZigType *result_type = instruction->base.value->type; ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); @@ -7512,8 +7630,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air if (instruction->is_nosuspend || (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn))) { - return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, - ptr_result_type, result_loc, true); + return gen_await_early_return(g, &instruction->base, target_frame_llvm_ty, + target_frame_ptr, result_type, ptr_result_type, result_loc, true); } // Prepare to be suspended @@ -7525,7 +7643,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air // supply the awaiter return pointer if (type_has_bits(g, result_type)) { - LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); + LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_ret_start + 1, ""); if (result_loc == nullptr) { // no copy needed LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), @@ -7540,14 +7659,15 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air bool is_llvm_alloca; LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); assert(my_err_ret_trace_val != nullptr); - LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, - frame_index_trace_arg(g, result_type) + 1, ""); + LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_index_trace_arg(g, result_type) + 1, ""); LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr); } // caller's own frame pointer LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_awaiter_index, ""); LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, LLVMAtomicOrderingRelease); @@ -7572,8 +7692,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air // Early return: The async function has already completed. We must copy the result and // the error return trace if applicable. LLVMPositionBuilderAtEnd(g->builder, early_return_block); - gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, ptr_result_type, - result_loc, false); + gen_await_early_return(g, &instruction->base, target_frame_llvm_ty, target_frame_ptr, + result_type, ptr_result_type, result_loc, false); LLVMBuildBr(g->builder, end_bb); LLVMPositionBuilderAtEnd(g->builder, resume_bb); @@ -7631,7 +7751,8 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, Stage1Air *executable, Stage zig_unreachable(); case SpillIdRetErrCode: { LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill); - return LLVMBuildLoad(g->builder, ptr, ""); + LLVMTypeRef llvm_ty = g->builtin_types.entry_global_error_set->llvm_type; + return LLVMBuildLoad2(g->builder, llvm_ty, ptr, ""); } } @@ -7923,24 +8044,12 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co ConstParent *parent = &array_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); - LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); - if (el_type == LLVMArrayTypeKind) { - ZigType *usize = g->builtin_types.entry_usize; - LLVMValueRef indices[] = { - LLVMConstNull(usize->llvm_type), - LLVMConstInt(usize->llvm_type, index, false), - }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); - } else if (el_type == LLVMStructTypeKind) { - ZigType *u32 = g->builtin_types.entry_u32; - LLVMValueRef indices[] = { - LLVMConstNull(get_llvm_type(g, u32)), - LLVMConstInt(get_llvm_type(g, u32), index, false), - }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); - } else { - return base_ptr; - } + ZigType *usize = g->builtin_types.entry_usize; + LLVMValueRef indices[] = { + LLVMConstNull(usize->llvm_type), + LLVMConstInt(usize->llvm_type, index, false), + }; + return LLVMConstInBoundsGEP2(get_llvm_type(g, array_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_const_val, size_t field_index) { @@ -7957,9 +8066,7 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_ // alignment purposes and have the following LLVM type: <{ %T, [N x i8] }>. // Add an extra bitcast as we're only interested in the %T part. assert(handle_is_ptr(g, struct_const_val->type)); - LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, - LLVMPointerType(get_llvm_type(g, struct_const_val->type), 0)); - return LLVMConstInBoundsGEP(casted_base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, struct_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) { @@ -7971,7 +8078,7 @@ static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), err_union_err_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigValue *err_union_const_val) { @@ -7983,7 +8090,7 @@ static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigVal LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), err_union_payload_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValue *optional_const_val) { @@ -7995,7 +8102,7 @@ static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValu LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), maybe_child_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, optional_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_const_val) { @@ -8012,7 +8119,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_co LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), union_payload_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, (union_payload_index != SIZE_MAX) ? 2 : 1); + return LLVMConstInBoundsGEP2(get_llvm_type(g, union_const_val->type), base_ptr, indices, (union_payload_index != SIZE_MAX) ? 2 : 1); } static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ZigValue *const_val) { @@ -9206,28 +9313,38 @@ static void do_code_gen(CodeGen *g) { } } + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; + // finishing error return trace setup. we have to do this after all the allocas. if (have_err_ret_trace_stack) { ZigType *usize = g->builtin_types.entry_usize; size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; - LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); + LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false); size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); + LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; - LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP(g->builder, err_ret_array_val, - indices, 2, ""); + LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP2(g->builder, + usize_type_ref, err_ret_array_val, indices, 2, ""); ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + LLVMGetGEPSourceElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -9235,7 +9352,6 @@ static void do_code_gen(CodeGen *g) { (void)get_llvm_type(g, fn_table_entry->frame_type); g->cur_resume_block_count = 0; - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); if (g->need_frame_size_prefix_data) { ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); @@ -9254,22 +9370,31 @@ static void do_code_gen(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); render_async_spills(g); - g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_awaiter_index, ""); - LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, ""); + g->cur_async_awaiter_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_awaiter_index, ""); + LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_resume_index, ""); g->cur_async_resume_index_ptr = resume_index_ptr; if (type_has_bits(g, fn_type_id->return_type)) { - LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, ""); - g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); + LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_ret_start, ""); + g->cur_ret_ptr = LLVMBuildLoad2(g->builder, + LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), cur_ret_ptr_ptr, ""); } uint32_t trace_field_index_stack = UINT32_MAX; if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) { trace_field_index_stack = frame_index_trace_stack(g, fn_table_entry); - g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack, ""); } - LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); + LLVMValueRef resume_index = LLVMBuildLoad2(g->builder, usize_type_ref, resume_index_ptr, ""); LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); g->cur_async_switch_instr = switch_instr; @@ -9293,15 +9418,21 @@ static void do_code_gen(CodeGen *g) { LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr); if (trace_field_index_stack != UINT32_MAX) { if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { - LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_index_trace_arg(g, fn_type_id->return_type), ""); LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(trace_ptr_ptr))); LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr); } - LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack, ""); - LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack + 1, ""); gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 52c202fded..a1b0f6a30c 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -417,12 +417,13 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, return wrap(func); } -LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) +LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, + const char *Name) { - Value *V = unwrap(Fn); - FunctionType *FnT = cast(V->getType()->getNonOpaquePointerElementType()); - CallInst *call_inst = CallInst::Create(FnT, V, makeArrayRef(unwrap(Args), NumArgs), Name); + FunctionType *FTy = unwrap(Ty); + CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn), makeArrayRef(unwrap(Args), + NumArgs), Name); call_inst->setCallingConv(static_cast(CC)); switch (attr) { case ZigLLVM_CallAttrAuto: @@ -440,7 +441,7 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *A call_inst->addFnAttr(Attribute::AlwaysInline); break; } - return wrap(unwrap(B)->Insert(call_inst)); + return wrap(call_inst); } LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, diff --git a/src/zig_llvm.h b/src/zig_llvm.h index c5923cba65..6bd6191217 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -125,8 +125,9 @@ enum ZigLLVM_CallAttr { ZigLLVM_CallAttrAlwaysTail, ZigLLVM_CallAttrAlwaysInline, }; -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, enum ZigLLVM_CallingConv CC, enum ZigLLVM_CallAttr attr, const char *Name); +ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type, + LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC, + enum ZigLLVM_CallAttr attr, const char *Name); ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile); -- cgit v1.2.3 From bc2aaf18c86007ffb997513a57af29692777002f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 20:55:17 -0700 Subject: stage2: LLVM lowering to opaque pointers API --- src/codegen/llvm.zig | 380 ++++++++++++++++++++++++------------------ src/codegen/llvm/bindings.zig | 22 ++- 2 files changed, 235 insertions(+), 167 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 132b5ef7a5..900c98c30d 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -841,7 +841,8 @@ pub const Object = struct { args.appendAssumeCapacity(param); } else { const alignment = param_ty.abiAlignment(target); - const load_inst = builder.buildLoad(param, ""); + const param_llvm_ty = try dg.lowerType(param_ty); + const load_inst = builder.buildLoad(param_llvm_ty, param, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } @@ -870,7 +871,7 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(arg_ptr); } else { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } @@ -921,14 +922,14 @@ pub const Object = struct { for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; @@ -3663,7 +3664,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_pl_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .Struct => { const field_ty = parent_ty.structFieldType(field_index); @@ -3693,7 +3695,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_field_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, } @@ -3707,7 +3710,8 @@ pub const DeclGen = struct { const indices: [1]*const llvm.Value = .{ llvm_usize.constInt(elem_ptr.index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty); + break :blk elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .opt_payload_ptr => blk: { const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; @@ -3730,7 +3734,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(0, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty); + break :blk opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .eu_payload_ptr => blk: { const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; @@ -3751,7 +3756,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(payload_offset, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty); + break :blk eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, }; @@ -4303,9 +4309,10 @@ pub const FuncGen = struct { const arg = args[it.zig_index - 1]; const param_ty = self.air.typeOf(arg); const llvm_arg = try self.resolveInst(arg); + const llvm_param_ty = try self.dg.lowerType(param_ty); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(llvm_arg, ""); + const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4315,7 +4322,6 @@ pub const FuncGen = struct { // which is always lowered to an LLVM type of `*i8`. // 2. The argument is a global which does act as a pointer, however // a bitcast is needed in order for the LLVM types to match. - const llvm_param_ty = try self.dg.lowerType(param_ty); const casted_ptr = self.builder.buildBitCast(llvm_arg, llvm_param_ty, ""); try llvm_args.append(casted_ptr); } else { @@ -4350,7 +4356,7 @@ pub const FuncGen = struct { if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); const casted_ptr = self.builder.buildBitCast(llvm_arg, int_ptr_llvm_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, casted_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4366,7 +4372,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(int_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } @@ -4403,8 +4409,8 @@ pub const FuncGen = struct { try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -4418,6 +4424,7 @@ pub const FuncGen = struct { }; const call = self.builder.buildCall( + try self.dg.lowerType(zig_fn_ty), llvm_fn, llvm_args.items.ptr, @intCast(c_uint, llvm_args.items.len), @@ -4443,7 +4450,7 @@ pub const FuncGen = struct { return rp; } else { // our by-ref status disagrees with sret so we must load. - const loaded = self.builder.buildLoad(rp, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); loaded.setAlignment(return_type.abiAlignment(target)); return loaded; } @@ -4465,7 +4472,7 @@ pub const FuncGen = struct { if (isByRef(return_type)) { return rp; } else { - const load_inst = self.builder.buildLoad(rp, ""); + const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -4523,7 +4530,7 @@ pub const FuncGen = struct { // operand is a pointer however self.ret_ptr is null so that means // we need to return a value. const casted_ptr = self.builder.buildBitCast(operand, ptr_abi_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4540,7 +4547,7 @@ pub const FuncGen = struct { const store_inst = self.builder.buildStore(operand, rp); store_inst.setAlignment(alignment); const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4575,7 +4582,7 @@ pub const FuncGen = struct { const ptr_abi_ty = abi_ret_ty.pointerType(0); break :p self.builder.buildBitCast(ptr, ptr_abi_ty, ""); }; - const loaded = self.builder.buildLoad(casted_ptr, ""); + const loaded = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); loaded.setAlignment(ret_ty.abiAlignment(target)); _ = self.builder.buildRet(loaded); return null; @@ -4615,7 +4622,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const llvm_fn = try self.getCmpLtErrorsLenFunction(); const args: [1]*const llvm.Value = .{operand}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn cmp( @@ -4642,8 +4649,9 @@ pub const FuncGen = struct { // We need to emit instructions to check for equality/inequality // of optionals that are not pointers. const is_by_ref = isByRef(scalar_ty); - const lhs_non_null = self.optIsNonNull(lhs, is_by_ref); - const rhs_non_null = self.optIsNonNull(rhs, is_by_ref); + const opt_llvm_ty = try self.dg.lowerType(scalar_ty); + const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); + const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); const llvm_i2 = self.context.intType(2); const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); @@ -4666,8 +4674,8 @@ pub const FuncGen = struct { _ = self.builder.buildBr(end_block); self.builder.positionBuilderAtEnd(both_pl_block); - const lhs_payload = self.optPayloadHandle(lhs, scalar_ty); - const rhs_payload = self.optPayloadHandle(rhs, scalar_ty); + const lhs_payload = self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); + const rhs_payload = self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); _ = self.builder.buildBr(end_block); const both_pl_block_end = self.builder.getInsertBlock(); @@ -4832,10 +4840,18 @@ pub const FuncGen = struct { return lowerTry(self, err_union_ptr, body, err_union_ty, true, result_ty); } - fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { + fn lowerTry( + fg: *FuncGen, + err_union: *const llvm.Value, + body: []const Air.Inst.Index, + err_union_ty: Type, + operand_is_ptr: bool, + result_ty: Type, + ) !?*const llvm.Value { const payload_ty = err_union_ty.errorUnionPayload(); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); const target = fg.dg.module.getTarget(); + const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { const is_err = err: { @@ -4843,14 +4859,17 @@ pub const FuncGen = struct { const zero = err_set_ty.constNull(); if (!payload_has_bits) { // TODO add alignment to this load - const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; + const loaded = if (operand_is_ptr) + fg.builder.buildLoad(err_set_ty, err_union, "") + else + err_union; break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); + const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); // TODO add alignment to this load - const loaded = fg.builder.buildLoad(err_field_ptr, ""); + const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); @@ -4876,13 +4895,13 @@ pub const FuncGen = struct { } const offset = errUnionPayloadOffset(payload_ty, target); if (operand_is_ptr or isByRef(payload_ty)) { - return fg.builder.buildStructGEP(err_union, offset, ""); + return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = fg.builder.buildStructGEP(err_union, offset, ""); + const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -4977,7 +4996,8 @@ pub const FuncGen = struct { const indices: [2]*const llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + const elem_llvm_ty = try self.dg.lowerType(array_ty.childType()); + const ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indices, indices.len, ""); const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); return self.builder.buildInsertValue(partial, len, 1, ""); } @@ -5038,7 +5058,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, dest_llvm_ty); const params = [1]*const llvm.Value{extended}; - return self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + return self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); } fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { @@ -5093,7 +5113,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*const llvm.Value{operand}; - var result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + var result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); @@ -5113,8 +5133,9 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); + const slice_llvm_ty = try self.dg.lowerType(self.air.typeOf(ty_op.operand).childType()); - return self.builder.buildStructGEP(slice_ptr, index, ""); + return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5124,7 +5145,10 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const ptr = self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); return self.load(ptr, slice_ty); } @@ -5132,10 +5156,14 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; + const slice_ty = self.air.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - return self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5146,13 +5174,14 @@ pub const FuncGen = struct { const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); if (isByRef(array_ty)) { - const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_val, &indices, indices.len, ""); const elem_ty = array_ty.childType(); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; + const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, array_llvm_val, &indices, indices.len, ""); if (isByRef(elem_ty)) { return elem_ptr; } else { - return self.builder.buildLoad(elem_ptr, ""); + return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } @@ -5165,15 +5194,16 @@ pub const FuncGen = struct { const ptr_ty = self.air.typeOf(bin_op.lhs); if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); const ptr = if (ptr_ty.isSinglePointer()) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else ptr: { const indices: [1]*const llvm.Value = .{rhs}; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); }; return self.load(ptr, ptr_ty); } @@ -5189,13 +5219,14 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + const llvm_elem_ty = try self.dg.lowerType(elem_ty); if (ptr_ty.isSinglePointer()) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{rhs}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -5279,20 +5310,22 @@ pub const FuncGen = struct { assert(struct_ty.containerLayout() != .Packed); var ptr_ty_buf: Type.Payload.Pointer = undefined; const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; - const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); return self.load(field_ptr, field_ptr_ty); }, .Union => { - const llvm_field_ty = try self.dg.lowerType(field_ty); + const union_llvm_ty = try self.dg.lowerType(struct_ty); const layout = struct_ty.unionGetLayout(target); const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, ""); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); + const llvm_field_ty = try self.dg.lowerType(field_ty); const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); if (isByRef(field_ty)) { return field_ptr; } else { - return self.builder.buildLoad(field_ptr, ""); + return self.builder.buildLoad(llvm_field_ty, field_ptr, ""); } }, else => unreachable, @@ -5605,10 +5638,11 @@ pub const FuncGen = struct { llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); } else { const alignment = arg_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(arg_llvm_value, ""); + const arg_llvm_ty = try self.dg.lowerType(arg_ty); + const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); load_inst.setAlignment(alignment); llvm_param_values[llvm_param_i] = load_inst; - llvm_param_types[llvm_param_i] = load_inst.typeOf(); + llvm_param_types[llvm_param_i] = arg_llvm_ty; } } else { if (constraintAllowsRegister(constraint)) { @@ -5769,6 +5803,7 @@ pub const FuncGen = struct { .False, ); const call = self.builder.buildCall( + asm_fn.typeOf(), asm_fn, llvm_param_values.ptr, @intCast(c_uint, param_count), @@ -5819,9 +5854,12 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; + const optional_llvm_ty = try self.dg.lowerType(optional_ty); if (optional_ty.optionalReprIsPayload()) { - const optional_llvm_ty = try self.dg.lowerType(optional_ty); - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } @@ -5830,13 +5868,16 @@ pub const FuncGen = struct { var buf: Type.Payload.ElemType = undefined; const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; const llvm_i8 = self.dg.context.intType(8); return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); } const is_by_ref = operand_is_ptr or isByRef(optional_ty); - const non_null_bit = self.optIsNonNull(operand, is_by_ref); + const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); if (pred == .EQ) { return self.builder.buildNot(non_null_bit, ""); } else { @@ -5857,7 +5898,7 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(); - const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); + const err_set_ty = try self.dg.lowerType(Type.anyerror); const zero = err_set_ty.constNull(); if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { @@ -5870,7 +5911,10 @@ pub const FuncGen = struct { } if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") + else + operand; return self.builder.buildICmp(op, loaded, zero, ""); } @@ -5878,8 +5922,9 @@ pub const FuncGen = struct { const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, err_field_index, ""); - const loaded = self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); + const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); return self.builder.buildICmp(op, loaded, zero, ""); } @@ -5900,7 +5945,7 @@ pub const FuncGen = struct { // We have a pointer to a zero-bit value and we need to return // a pointer to a zero-bit value. - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -5908,7 +5953,8 @@ pub const FuncGen = struct { // The payload and the optional are the same value. return operand; } - return self.builder.buildStructGEP(operand, 0, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5925,7 +5971,7 @@ pub const FuncGen = struct { // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. _ = self.builder.buildStore(non_null_bit, operand); - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -5936,7 +5982,8 @@ pub const FuncGen = struct { } // First set the non-null bit. - const non_null_ptr = self.builder.buildStructGEP(operand, 1, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const non_null_ptr = self.builder.buildStructGEP(optional_llvm_ty, operand, 1, ""); // TODO set alignment on this store _ = self.builder.buildStore(non_null_bit, non_null_ptr); @@ -5944,7 +5991,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; - return self.builder.buildStructGEP(operand, 0, ""); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5961,7 +6008,8 @@ pub const FuncGen = struct { return operand; } - return self.optPayloadHandle(operand, optional_ty); + const opt_llvm_ty = try self.dg.lowerType(optional_ty); + return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty); } fn airErrUnionPayload( @@ -5987,14 +6035,15 @@ pub const FuncGen = struct { return self.builder.buildBitCast(operand, res_ptr_ty, ""); } const offset = errUnionPayloadOffset(payload_ty, target); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); if (operand_is_ptr or isByRef(payload_ty)) { - return self.builder.buildStructGEP(operand, offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = self.builder.buildStructGEP(operand, offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = self.builder.buildLoad(payload_ptr, ""); + const load_inst = self.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -6022,18 +6071,21 @@ pub const FuncGen = struct { } } + const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); + const payload_ty = err_union_ty.errorUnionPayload(); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { if (!operand_is_ptr) return operand; - return self.builder.buildLoad(operand, ""); + return self.builder.buildLoad(err_set_llvm_ty, operand, ""); } const target = self.dg.module.getTarget(); const offset = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, offset, ""); - return self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); + return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); } return self.builder.buildExtractValue(operand, offset, ""); @@ -6042,19 +6094,20 @@ pub const FuncGen = struct { fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); - const error_union_ty = self.air.typeOf(ty_op.operand).childType(); + const err_union_ty = self.air.typeOf(ty_op.operand).childType(); - const payload_ty = error_union_ty.errorUnionPayload(); + const payload_ty = err_union_ty.errorUnionPayload(); const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { _ = self.builder.buildStore(non_error_val, operand); return operand; } const target = self.dg.module.getTarget(); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); { const error_offset = errUnionErrorOffset(payload_ty, target); // First set the non-error value. - const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, ""); + const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); } @@ -6063,7 +6116,7 @@ pub const FuncGen = struct { return null; const payload_offset = errUnionPayloadOffset(payload_ty, target); - return self.builder.buildStructGEP(operand, payload_offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); } fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { @@ -6093,14 +6146,14 @@ pub const FuncGen = struct { const llvm_optional_ty = try self.dg.lowerType(optional_ty); if (isByRef(optional_ty)) { const optional_ptr = self.buildAlloca(llvm_optional_ty); - const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); + const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, }; const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base); self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); - const non_null_ptr = self.builder.buildStructGEP(optional_ptr, 1, ""); + const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, ""); _ = self.builder.buildStore(non_null_bit, non_null_ptr); return optional_ptr; } @@ -6126,10 +6179,10 @@ pub const FuncGen = struct { const error_offset = errUnionErrorOffset(payload_ty, target); if (isByRef(inst_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(ok_err_code, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6160,10 +6213,10 @@ pub const FuncGen = struct { const error_offset = errUnionErrorOffset(payload_ty, target); if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(operand, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6188,7 +6241,7 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6201,7 +6254,7 @@ pub const FuncGen = struct { llvm_u32.constInt(index, .False), operand, }; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6504,15 +6557,16 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6525,15 +6579,16 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), negative_offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{negative_offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6564,7 +6619,7 @@ pub const FuncGen = struct { const tg = self.dg.module.getTarget(); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const result_struct = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); + const result_struct = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); const result = self.builder.buildExtractValue(result_struct, 0, ""); const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); @@ -6579,12 +6634,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -6616,7 +6671,7 @@ pub const FuncGen = struct { for (args_vectors) |arg_vector, k| { args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); } - const result_elem = self.builder.buildCall(llvm_fn, &args, args_len, .C, .Auto, ""); + const result_elem = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args_len, .C, .Auto, ""); result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); } return result; @@ -6743,7 +6798,7 @@ pub const FuncGen = struct { return self.builder.buildICmp(int_pred, result, zero_vector, ""); } - const result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + const result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); return self.builder.buildICmp(int_pred, result, zero, ""); } @@ -6871,7 +6926,7 @@ pub const FuncGen = struct { break :b libc_fn; }, }; - return self.builder.buildCall(llvm_fn, ¶ms, params_len, .C, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6931,12 +6986,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -7226,7 +7281,7 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_dest_ty, array_ptr, &indexes, indexes.len, ""); const elem = self.builder.buildExtractElement(operand, index_u32, ""); _ = self.builder.buildStore(elem, elem_ptr); } @@ -7243,7 +7298,7 @@ pub const FuncGen = struct { if (bitcast_ok) { const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0); const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, ""); - const vector = self.builder.buildLoad(casted_ptr, ""); + const vector = self.builder.buildLoad(llvm_vector_ty, casted_ptr, ""); // The array is aligned to the element's alignment, while the vector might have a completely // different alignment. This means we need to enforce the alignment of this load. vector.setAlignment(elem_ty.abiAlignment(target)); @@ -7251,6 +7306,7 @@ pub const FuncGen = struct { } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. + const elem_llvm_ty = try self.dg.lowerType(elem_ty); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); const zero = llvm_usize.constNull(); @@ -7261,8 +7317,8 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(operand, &indexes, indexes.len, ""); - const elem = self.builder.buildLoad(elem_ptr, ""); + const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indexes, indexes.len, ""); + const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); } @@ -7273,7 +7329,7 @@ pub const FuncGen = struct { if (operand_is_ref) { // Bitcast the operand pointer, then load. const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, casted_ptr, ""); load_inst.setAlignment(operand_ty.abiAlignment(target)); return load_inst; } @@ -7301,7 +7357,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(operand, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(result_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -7481,7 +7537,7 @@ pub const FuncGen = struct { fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { _ = inst; const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); - _ = self.builder.buildCall(llvm_fn, undefined, 0, .C, .Auto, ""); + _ = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, undefined, 0, .C, .Auto, ""); return null; } @@ -7498,7 +7554,7 @@ pub const FuncGen = struct { const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7515,7 +7571,7 @@ pub const FuncGen = struct { }; const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7740,8 +7796,9 @@ pub const FuncGen = struct { _ = self.builder.buildStore(new_tag, union_ptr); return null; } + const un_llvm_ty = try self.dg.lowerType(un_ty); const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, ""); + const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, ""); // TODO alignment on this store _ = self.builder.buildStore(new_tag, tag_field_ptr); return null; @@ -7757,12 +7814,13 @@ pub const FuncGen = struct { if (layout.tag_size == 0) return null; const union_handle = try self.resolveInst(ty_op.operand); if (isByRef(un_ty)) { + const llvm_un_ty = try self.dg.lowerType(un_ty); if (layout.payload_size == 0) { - return self.builder.buildLoad(union_handle, ""); + return self.builder.buildLoad(llvm_un_ty, union_handle, ""); } const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_handle, tag_index, ""); - return self.builder.buildLoad(tag_field_ptr, ""); + const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); + return self.builder.buildLoad(tag_field_ptr.getGEPSourceElementType(), tag_field_ptr, ""); } else { if (layout.payload_size == 0) { return union_handle; @@ -7805,7 +7863,7 @@ pub const FuncGen = struct { const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7832,7 +7890,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try self.dg.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7889,7 +7947,7 @@ pub const FuncGen = struct { const params = [_]*const llvm.Value{operand}; const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7912,7 +7970,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getEnumTagNameFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -7973,7 +8031,8 @@ pub const FuncGen = struct { for (fields.keys()) |name, field_index| { const str_init = self.dg.context.constString(name.ptr, @intCast(c_uint, name.len), .False); - const str_global = self.dg.object.llvm_module.addGlobal(str_init.typeOf(), ""); + const str_init_llvm_ty = str_init.typeOf(); + const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, ""); str_global.setInitializer(str_init); str_global.setLinkage(.Private); str_global.setGlobalConstant(.True); @@ -7981,7 +8040,7 @@ pub const FuncGen = struct { str_global.setAlignment(1); const slice_fields = [_]*const llvm.Value{ - str_global.constInBoundsGEP(&array_ptr_indices, array_ptr_indices.len), + str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len), usize_llvm_ty.constInt(name.len, .False), }; const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); @@ -8006,7 +8065,7 @@ pub const FuncGen = struct { switch_instr.addCase(this_tag_int_value, return_block); self.builder.positionBuilderAtEnd(return_block); - const loaded = self.builder.buildLoad(slice_global, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, slice_global, ""); loaded.setAlignment(slice_alignment); _ = self.builder.buildRet(loaded); } @@ -8040,12 +8099,15 @@ pub const FuncGen = struct { const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); + const slice_ty = self.air.typeOfIndex(inst); + const slice_llvm_ty = try self.dg.lowerType(slice_ty); const error_name_table_ptr = try self.getErrorNameTable(); - const error_name_table = self.builder.buildLoad(error_name_table_ptr, ""); + const ptr_slice_llvm_ty = slice_llvm_ty.pointerType(0); + const error_name_table = self.builder.buildLoad(ptr_slice_llvm_ty, error_name_table_ptr, ""); const indices = [_]*const llvm.Value{operand}; - const error_name_ptr = self.builder.buildInBoundsGEP(error_name_table, &indices, indices.len, ""); - return self.builder.buildLoad(error_name_ptr, ""); + const error_name_ptr = self.builder.buildInBoundsGEP(slice_llvm_ty, error_name_table, &indices, indices.len, ""); + return self.builder.buildLoad(slice_llvm_ty, error_name_ptr, ""); } fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -8222,7 +8284,7 @@ pub const FuncGen = struct { const llvm_elem = try self.resolveInst(elem); const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; indices[1] = llvm_u32.constInt(llvm_i, .False); - const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); var field_ptr_payload: Type.Payload.Pointer = .{ .data = .{ .pointee_type = self.air.typeOf(elem), @@ -8268,7 +8330,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.resolveInst(elem); self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); } @@ -8277,7 +8339,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, array_info.len), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.dg.lowerValue(.{ .ty = array_info.elem_type, .val = sent_val, @@ -8377,7 +8439,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); return result_ptr; } @@ -8389,7 +8451,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); } { @@ -8397,7 +8459,7 @@ pub const FuncGen = struct { index_type.constNull(), index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), }; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, indices.len, ""); const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); @@ -8464,7 +8526,7 @@ pub const FuncGen = struct { llvm_u32.constInt(prefetch.locality, .False), llvm_u32.constInt(@enumToInt(prefetch.cache), .False), }; - _ = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + _ = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); return null; } @@ -8544,7 +8606,7 @@ pub const FuncGen = struct { }; var args: [1]*const llvm.Value = .{arg}; - const result = self.builder.buildCall(llvm_fn, &args, args.len, .C, .Auto, ""); + const result = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .C, .Auto, ""); const final_cast_llvm_ty = final_cast orelse return result; return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); } @@ -8571,22 +8633,29 @@ pub const FuncGen = struct { } /// Assumes the optional is not pointer-like and payload has bits. - fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { + fn optIsNonNull( + self: *FuncGen, + opt_llvm_ty: *const llvm.Type, + opt_handle: *const llvm.Value, + is_by_ref: bool, + ) *const llvm.Value { + const non_null_llvm_ty = self.context.intType(8); const field = b: { if (is_by_ref) { - const field_ptr = self.builder.buildStructGEP(opt_handle, 1, ""); - break :b self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); + break :b self.builder.buildLoad(non_null_llvm_ty, field_ptr, ""); } break :b self.builder.buildExtractValue(opt_handle, 1, ""); }; comptime assert(optional_layout_version == 3); - return self.builder.buildICmp(.NE, field, self.context.intType(8).constInt(0, .False), ""); + return self.builder.buildICmp(.NE, field, non_null_llvm_ty.constInt(0, .False), ""); } /// Assumes the optional is not pointer-like and payload has bits. fn optPayloadHandle( fg: *FuncGen, + opt_llvm_ty: *const llvm.Type, opt_handle: *const llvm.Value, opt_ty: Type, ) *const llvm.Value { @@ -8595,14 +8664,14 @@ pub const FuncGen = struct { if (isByRef(opt_ty)) { // We have a pointer and we need to return a pointer to the first field. - const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, ""); + const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); if (isByRef(payload_ty)) { return payload_ptr; } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } @@ -8627,12 +8696,12 @@ pub const FuncGen = struct { alloca_inst.setAlignment(payload_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); const store_inst = self.builder.buildStore(payload, field_ptr); store_inst.setAlignment(payload_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 1, ""); const store_inst = self.builder.buildStore(non_null_field, field_ptr); store_inst.setAlignment(1); } @@ -8678,18 +8747,20 @@ pub const FuncGen = struct { if (byte_offset == 0) { return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); } - const llvm_bytes_ptr_ty = self.context.intType(8).pointerType(0); - const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, llvm_bytes_ptr_ty, ""); + const byte_llvm_ty = self.context.intType(8); + const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, byte_llvm_ty.pointerType(0), ""); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(byte_offset, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - const new_ptr = self.builder.buildInBoundsGEP(ptr_as_bytes, &indices, indices.len, ""); + const new_ptr = self.builder.buildInBoundsGEP(byte_llvm_ty, ptr_as_bytes, &indices, indices.len, ""); return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); }, else => { + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + var ty_buf: Type.Payload.Pointer = undefined; if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { - return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); + return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); } else { // If we found no index then this means this is a zero sized field at the // end of the struct. Treat our struct pointer as an array of two and get @@ -8698,7 +8769,7 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(1, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); } }, }, @@ -8716,27 +8787,18 @@ pub const FuncGen = struct { ) !?*const llvm.Value { const union_obj = union_ty.cast(Type.Payload.Union).?.data; const field = &union_obj.fields.values()[field_index]; - const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); if (!field.ty.hasRuntimeBitsIgnoreComptime()) { return null; } const target = self.dg.module.getTarget(); const layout = union_ty.unionGetLayout(target); const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, ""); + const union_llvm_ty = try self.dg.lowerType(union_ty); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); + const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); } - fn sliceElemPtr( - self: *FuncGen, - slice: *const llvm.Value, - index: *const llvm.Value, - ) *const llvm.Value { - const base_ptr = self.builder.buildExtractValue(slice, 0, ""); - const indices: [1]*const llvm.Value = .{index}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); - } - fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { const id = llvm.lookupIntrinsicID(name.ptr, name.len); assert(id != 0); @@ -8754,8 +8816,8 @@ pub const FuncGen = struct { const ptr_alignment = ptr_ty.ptrAlignment(target); const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); if (info.host_size == 0) { + const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); if (isByRef(info.pointee_type)) { - const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); const result_align = info.pointee_type.abiAlignment(target); const max_align = @maximum(result_align, ptr_alignment); const result_ptr = self.buildAlloca(elem_llvm_ty); @@ -8773,15 +8835,15 @@ pub const FuncGen = struct { ); return result_ptr; } - const llvm_inst = self.builder.buildLoad(ptr, ""); + const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); llvm_inst.setAlignment(ptr_alignment); llvm_inst.setVolatile(ptr_volatile); return llvm_inst; } - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); @@ -8828,9 +8890,9 @@ pub const FuncGen = struct { const ptr_alignment = ptr_ty.ptrAlignment(target); const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); if (info.host_size != 0) { - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); assert(ordering == .NotAtomic); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 7a3ed9ebd1..9c337cc287 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -141,14 +141,6 @@ pub const Value = opaque { pub const setAliasee = LLVMAliasSetAliasee; extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void; - pub const constInBoundsGEP = LLVMConstInBoundsGEP2; - extern fn LLVMConstInBoundsGEP2( - Ty: *const Type, - ConstantVal: *const Value, - ConstantIndices: [*]const *const Value, - NumIndices: c_uint, - ) *const Value; - pub const constBitCast = LLVMConstBitCast; extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value; @@ -249,6 +241,9 @@ pub const Value = opaque { pub const addFunctionAttr = ZigLLVMAddFunctionAttr; extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; + + pub const getGEPSourceElementType = LLVMGetGEPSourceElementType; + extern fn LLVMGetGEPSourceElementType(GEP: *const Value) *const Type; }; pub const Type = opaque { @@ -280,6 +275,9 @@ pub const Type = opaque { pub const getUndef = LLVMGetUndef; extern fn LLVMGetUndef(Ty: *const Type) *const Value; + pub const pointerType = LLVMPointerType; + extern fn LLVMPointerType(ElementType: *const Type, AddressSpace: c_uint) *const Type; + pub const arrayType = LLVMArrayType; extern fn LLVMArrayType(ElementType: *const Type, ElementCount: c_uint) *const Type; @@ -311,6 +309,14 @@ pub const Type = opaque { pub const isSized = LLVMTypeIsSized; extern fn LLVMTypeIsSized(Ty: *const Type) Bool; + + pub const constInBoundsGEP = LLVMConstInBoundsGEP2; + extern fn LLVMConstInBoundsGEP2( + Ty: *const Type, + ConstantVal: *const Value, + ConstantIndices: [*]const *const Value, + NumIndices: c_uint, + ) *const Value; }; pub const Module = opaque { -- cgit v1.2.3 From aa79cc10aa38c2c3641d5a430aa33b8bfa6a3d61 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 22:40:18 -0700 Subject: fix bugs from previous two commits --- src/codegen/llvm.zig | 36 +++++++-------- src/stage1/codegen.cpp | 120 ++++++++++++++++++++++++++++--------------------- 2 files changed, 87 insertions(+), 69 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 900c98c30d..ece704a04c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4622,7 +4622,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const llvm_fn = try self.getCmpLtErrorsLenFunction(); const args: [1]*const llvm.Value = .{operand}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn cmp( @@ -5058,7 +5058,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, dest_llvm_ty); const params = [1]*const llvm.Value{extended}; - return self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); } fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { @@ -5113,7 +5113,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*const llvm.Value{operand}; - var result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + var result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); @@ -6241,7 +6241,7 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6254,7 +6254,7 @@ pub const FuncGen = struct { llvm_u32.constInt(index, .False), operand, }; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6619,7 +6619,7 @@ pub const FuncGen = struct { const tg = self.dg.module.getTarget(); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const result_struct = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); + const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); const result = self.builder.buildExtractValue(result_struct, 0, ""); const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); @@ -6671,7 +6671,7 @@ pub const FuncGen = struct { for (args_vectors) |arg_vector, k| { args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); } - const result_elem = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args_len, .C, .Auto, ""); + const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args_len, .C, .Auto, ""); result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); } return result; @@ -6798,7 +6798,7 @@ pub const FuncGen = struct { return self.builder.buildICmp(int_pred, result, zero_vector, ""); } - const result = self.builder.buildCall(libc_fn.typeOf(), libc_fn, ¶ms, params.len, .C, .Auto, ""); + const result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); return self.builder.buildICmp(int_pred, result, zero, ""); } @@ -6926,7 +6926,7 @@ pub const FuncGen = struct { break :b libc_fn; }, }; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -7537,7 +7537,7 @@ pub const FuncGen = struct { fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { _ = inst; const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); - _ = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, undefined, 0, .C, .Auto, ""); + _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); return null; } @@ -7554,7 +7554,7 @@ pub const FuncGen = struct { const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7571,7 +7571,7 @@ pub const FuncGen = struct { }; const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7863,7 +7863,7 @@ pub const FuncGen = struct { const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7890,7 +7890,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try self.dg.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7947,7 +7947,7 @@ pub const FuncGen = struct { const params = [_]*const llvm.Value{operand}; const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -7970,7 +7970,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getEnumTagNameFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -8526,7 +8526,7 @@ pub const FuncGen = struct { llvm_u32.constInt(prefetch.locality, .False), llvm_u32.constInt(@enumToInt(prefetch.cache), .False), }; - _ = self.builder.buildCall(fn_val.typeOf(), fn_val, ¶ms, params.len, .C, .Auto, ""); + _ = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); return null; } @@ -8606,7 +8606,7 @@ pub const FuncGen = struct { }; var args: [1]*const llvm.Value = .{arg}; - const result = self.builder.buildCall(llvm_fn.typeOf(), llvm_fn, &args, args.len, .C, .Auto, ""); + const result = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .C, .Auto, ""); const final_cast_llvm_ty = final_cast orelse return result; return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); } diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 9b3e6607e5..a3d11471df 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1092,7 +1092,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace msg_arg, stack_trace_arg, }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); if (!stack_trace_is_llvm_alloca) { // The stack trace argument is not in the stack of the caller, so // we'd like to set tail call here, but because slices (the type of msg_arg) are @@ -1369,7 +1369,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block); LLVMValueRef args[] = { err_ret_trace_ptr, return_address }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMBuildRetVoid(g->builder); @@ -1546,14 +1546,14 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc err_ret_trace_val, err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } else { LLVMValueRef args[] = { err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, LLVMTypeOf(safety_crash_err_fn), + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), safety_crash_err_fn, args, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -1732,7 +1732,7 @@ static LLVMValueRef gen_soft_float_widen_or_shorten(CodeGen *g, ZigType *actual_ func_ref = LLVMAddFunction(g->module, fn_name, fn_type); } - result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &expr_val, 1, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &expr_val, 1, ""); // On non-Arm platforms we need to bitcast __trunc<>fhf2 result back to f16 if (castTruncatedToF16) { @@ -1878,7 +1878,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul val1, val2, }; - LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); if (operand_type->id == ZigTypeIdVector) { @@ -2663,7 +2663,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, LLVMGetGEPSourceElementType(addr_ptr), addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(add_error_return_trace_addr_fn_val), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMValueRef prev_frames_left = LLVMBuildLoad2(g->builder, usize_type_ref, frames_left_ptr, ""); LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, ""); @@ -2703,7 +2703,7 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executabl bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope, &is_llvm_alloca); - ZigLLVMBuildCall(g->builder, LLVMTypeOf(return_err_fn), return_err_fn, &my_err_trace_val, 1, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(return_err_fn), return_err_fn, &my_err_trace_val, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; @@ -2753,7 +2753,7 @@ static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef tar LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref), LLVMConstInt(usize_type_ref, resume_id, false)); LLVMValueRef args[] = {target_frame_ptr, arg_val}; - return ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); + return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); } static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { @@ -2885,7 +2885,7 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -3057,14 +3057,14 @@ static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *o LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type); if (vector_len == 0) { - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &op, 1, ""); } else { LLVMValueRef result = LLVMGetUndef(operand_type->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); LLVMValueRef param = LLVMBuildExtractElement(g->builder, op, index_value, ""); - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, ¶m, 1, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, ¶m, 1, ""); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; @@ -3081,7 +3081,7 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o return gen_soft_float_un_op(g, operand, operand_type, op); } LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); - return LLVMBuildCall2(g->builder, LLVMTypeOf(float_op_fn), float_op_fn, &operand, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(float_op_fn), float_op_fn, &operand, 1, ""); } enum DivKind { @@ -3447,7 +3447,7 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); } static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { @@ -3483,7 +3483,7 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, ""); @@ -3596,7 +3596,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[2] = {op1_value, op2_value}; - result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); result = add_icmp(g, result, res_icmp); } else { ZigType *alloca_ty = operand_type; @@ -3610,7 +3610,7 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, param_count, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); call_result = add_icmp(g, call_result, res_icmp); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } @@ -4585,7 +4585,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template), buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack, LLVMInlineAsmDialectATT, false); - return LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, input_and_output_count, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, input_and_output_count, ""); } } zig_unreachable(); @@ -4849,7 +4849,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { aligned_end_addr, }; - LLVMBuildCall2(g->builder, LLVMTypeOf(write_register_fn_val), write_register_fn_val, params, 2, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(write_register_fn_val), write_register_fn_val, params, 2, ""); } static void render_async_spills(CodeGen *g) { @@ -4996,10 +4996,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI callee_is_async = fn_type->data.fn.fn_type_id.cc == CallingConventionAsync; } - LLVMTypeRef frame_struct_llvm_ty = (instruction->fn_entry != nullptr) ? - get_llvm_type(g, get_fn_frame_type(g, instruction->fn_entry)) : - g->any_frame_header_llvm_ty; - FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; ZigType *src_return_type = fn_type_id->return_type; @@ -5018,23 +5014,33 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *anyframe_type = nullptr; LLVMValueRef frame_result_loc_uncasted = nullptr; LLVMValueRef frame_result_loc; + LLVMTypeRef frame_struct_llvm_ty; LLVMValueRef awaiter_init_val; LLVMValueRef ret_ptr; if (callee_is_async) { if (instruction->new_stack == nullptr) { if (instruction->modifier == CallModifierAsync) { frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } } else { ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); ir_assert(instruction->fn_entry != nullptr, &instruction->base); - frame_result_loc = frame_result_loc_uncasted; + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); + frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } } else { if (instruction->new_stack->value->type->id == ZigTypeIdPointer && instruction->new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame) { frame_result_loc = ir_llvm_value(g, instruction->new_stack); + frame_struct_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type); } else { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); LLVMTypeRef frame_slice_llvm_ty = @@ -5063,12 +5069,16 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); - frame_result_loc = frame_ptr; + frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = g->any_frame_header_llvm_ty; } else { ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry); if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull))) codegen_report_errors_and_exit(g); - frame_result_loc = frame_ptr; + ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false); + frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, + get_llvm_type(g, ptr_frame_type), ""); + frame_struct_llvm_ty = get_llvm_type(g, frame_type); } } } @@ -5156,6 +5166,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI zig_panic("TODO @asyncCall of non-async function"); } frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } awaiter_init_val = LLVMConstAllOnes(usize_type_ref); LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); @@ -5352,11 +5368,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, - LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } else { frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = g->any_frame_header_llvm_ty; } } @@ -5369,7 +5387,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI } if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) { - result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); } else if (instruction->modifier == CallModifierAsync) { zig_panic("TODO @asyncCall of non-async function"); @@ -5380,14 +5398,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef old_stack_ref; if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); - old_stack_ref = LLVMBuildCall2(g->builder, LLVMTypeOf(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); + old_stack_ref = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); } gen_set_stack_pointer(g, new_stack_addr); - result = ZigLLVMBuildCall(g->builder, LLVMTypeOf(fn_val), fn_val, + result = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); - LLVMBuildCall2(g->builder, LLVMTypeOf(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); } } @@ -5735,7 +5753,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMTypeOf(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { if (param_needs_attr[i]) { @@ -5895,7 +5913,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5907,7 +5925,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5964,7 +5982,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, Stage ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); - LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &operand, 1, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &operand, 1, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -6180,7 +6198,7 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); - return ZigLLVMBuildCall(g->builder, LLVMTypeOf(enum_name_function), enum_name_function, + return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(enum_name_function), enum_name_function, &enum_tag_value, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -6557,7 +6575,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, Stage1Ai static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemorySize *instruction) { // TODO adjust for wasm64 LLVMValueRef param = ir_llvm_value(g, instruction->index); - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); return val; } @@ -6567,7 +6585,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable ir_llvm_value(g, instruction->index), ir_llvm_value(g, instruction->delta), }; - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); return val; } @@ -6613,7 +6631,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstInt(LLVMInt32Type(), instruction->locality, false), LLVMConstInt(LLVMInt32Type(), instruction->cache, false), }; - LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMTypeOf(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); return val; } @@ -6868,7 +6886,7 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, Stage1AirInstBreakpoint *instruction) { - LLVMBuildCall2(g->builder, LLVMTypeOf(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } @@ -6882,7 +6900,7 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, } LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6904,7 +6922,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMTypeOf(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6967,7 +6985,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, Sta op2, }; - LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); gen_store(g, result, ptr_result, instruction->result_ptr->value->type); @@ -7339,7 +7357,7 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); if (vector_len == 0) { LLVMValueRef params[3] = { op1, op2, op3 }; - return LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); } LLVMValueRef result = LLVMGetUndef(get_llvm_type(g, instruction->op1->value->type)); @@ -7352,7 +7370,7 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMBuildExtractElement(g->builder, op2, index_value, ""), LLVMBuildExtractElement(g->builder, op3, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMTypeOf(func_ref), func_ref, params, 3, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; @@ -7372,7 +7390,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A instruction->base.value->type->id == ZigTypeIdVector); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); LLVMValueRef args[3] = { op1, op2, op3 }; - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, args, 3, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 3, ""); } static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1AirInstBswap *instruction) { @@ -7383,7 +7401,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air assert(int_type->id == ZigTypeIdInt); if (int_type->data.integral.bit_count % 16 == 0) { LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap); - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, @@ -7402,7 +7420,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); - LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &extended, 1, ""); + LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &extended, 1, ""); // ccbbaa00 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, ""); // 00ccbbaa @@ -7438,7 +7456,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, Sta ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value->type, BuiltinFnIdBitReverse); - return LLVMBuildCall2(g->builder, LLVMTypeOf(fn_val), fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, @@ -7603,7 +7621,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; - ZigLLVMBuildCall(g->builder, LLVMTypeOf(get_merge_err_ret_traces_fn_val(g)), + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -9337,7 +9355,7 @@ static void do_code_gen(CodeGen *g) { LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP2(g->builder, - usize_type_ref, err_ret_array_val, indices, 2, ""); + LLVMGetAllocatedType(err_ret_array_val), err_ret_array_val, indices, 2, ""); ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); -- cgit v1.2.3 From 44f833129c81bfa7117743fc7d54c44db09cc240 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Aug 2022 23:26:36 -0700 Subject: LLVM backends: work around poorly designed C API As part of the Opaque Pointers upgrade documentation, LLVM says that the function LLVMGetGEPSourceElementType() can be used to obtain element type information in lieu of LLVMGetElementType(), however, this function actually returns the struct type, not the field type. The GEP instruction does store the information we need, however, this is not exposed in the C API. It seems like they accidentally exposed the wrong field, because one would never need the struct type since one must already pass it directly to the GEP instruction, so one will always have it handy, whereas one will usually not have the field type handy. --- src/codegen/llvm.zig | 8 ++--- src/codegen/llvm/bindings.zig | 4 +-- src/stage1/codegen.cpp | 83 +++++++++++++++++++++---------------------- src/zig_llvm.cpp | 4 +++ src/zig_llvm.h | 2 ++ 5 files changed, 52 insertions(+), 49 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index ece704a04c..a1000a8945 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4901,7 +4901,7 @@ pub const FuncGen = struct { if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -6043,7 +6043,7 @@ pub const FuncGen = struct { if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = self.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = self.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -7820,7 +7820,7 @@ pub const FuncGen = struct { } const tag_index = @boolToInt(layout.tag_align < layout.payload_align); const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); - return self.builder.buildLoad(tag_field_ptr.getGEPSourceElementType(), tag_field_ptr, ""); + return self.builder.buildLoad(tag_field_ptr.getGEPResultElementType(), tag_field_ptr, ""); } else { if (layout.payload_size == 0) { return union_handle; @@ -8671,7 +8671,7 @@ pub const FuncGen = struct { } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPSourceElementType(), payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 9c337cc287..4090054800 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -242,8 +242,8 @@ pub const Value = opaque { pub const addFunctionAttr = ZigLLVMAddFunctionAttr; extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; - pub const getGEPSourceElementType = LLVMGetGEPSourceElementType; - extern fn LLVMGetGEPSourceElementType(GEP: *const Value) *const Type; + pub const getGEPResultElementType = ZigLLVMGetGEPResultElementType; + extern fn ZigLLVMGetGEPResultElementType(GEP: *const Value) *const Type; }; pub const Type = opaque { diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 88c7db2ec8..423e9b7085 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1276,16 +1276,16 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)len_field_index, ""); - LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); - LLVMValueRef index_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(index_field_ptr), + LLVMValueRef index_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(index_field_ptr), index_field_ptr, 0, false, ""); LLVMValueRef len_val_minus_one = LLVMBuildSub(g->builder, len_value, LLVMConstInt(usize_type_ref, 1, false), ""); LLVMValueRef masked_val = LLVMBuildAnd(g->builder, index_val, len_val_minus_one, ""); @@ -1293,7 +1293,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { masked_val, }; - LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); LLVMValueRef address_slot = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, ptr_value, address_indices, 1, ""); @@ -1455,22 +1455,19 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { } // Fetch the error name from the global table - LLVMValueRef err_table_indices[] = { - LLVMConstNull(usize_ty->llvm_type), - err_val, - }; + LLVMValueRef err_table_indices[] = { err_val }; LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, str_type), g->err_name_table, err_table_indices, 2, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_ptr_index, ""); - LLVMValueRef err_name_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_ptr_index, ""); + LLVMValueRef err_name_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(err_name_val), err_name_val, slice_len_index, ""); - LLVMValueRef err_name_len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_len_index, ""); + LLVMValueRef err_name_len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false); @@ -2374,7 +2371,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ LLVMValueRef adjusted_ptr_to_struct = LLVMBuildStructGEP2(g->builder, abi_type, val, i, ""); LLVMValueRef loaded = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(adjusted_ptr_to_struct), + ZigLLVMGetGEPResultElementType(adjusted_ptr_to_struct), adjusted_ptr_to_struct, ""); fn_walk->data.call.gen_param_values->append(loaded); } @@ -2621,18 +2618,18 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(src_addresses_field_ptr), + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), src_addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(src_addresses_field_ptr), + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), src_addresses_field_ptr, (unsigned)len_field_index, ""); LLVMValueRef src_index_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_index_field_ptr), src_index_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_index_field_ptr), src_index_field_ptr, ""); LLVMValueRef src_ptr_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); LLVMValueRef src_len_val = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(src_len_field_ptr), src_len_field_ptr, ""); + ZigLLVMGetGEPResultElementType(src_len_field_ptr), src_len_field_ptr, ""); LLVMValueRef no_wrap_bit = LLVMBuildICmp(g->builder, LLVMIntULT, src_index_val, src_len_val, ""); LLVMBasicBlockRef no_wrap_block = LLVMAppendBasicBlock(fn_val, "NoWrap"); LLVMBasicBlockRef yes_wrap_block = LLVMAppendBasicBlock(fn_val, "YesWrap"); @@ -2658,7 +2655,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMValueRef ptr_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, src_ptr_val, &ptr_index, 1, ""); - LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, LLVMGetGEPSourceElementType(addr_ptr), + LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(addr_ptr), addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), @@ -4793,7 +4790,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 assert(len_index != SIZE_MAX); LLVMValueRef len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, (unsigned)len_index, ""); - LLVMValueRef len = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_ptr), len_ptr, + LLVMValueRef len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_ptr), len_ptr, 0, false, ""); LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT; add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len); @@ -4803,7 +4800,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 assert(ptr_index != SIZE_MAX); LLVMValueRef ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, (unsigned)ptr_index, ""); - LLVMValueRef ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_ptr), ptr_ptr, 0, + LLVMValueRef ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_ptr), ptr_ptr, 0, false, ""); LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, ptr, &subscript_value, 1, ""); @@ -4820,9 +4817,9 @@ static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMTypeRef new_stack_llvm_ty LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_ptr_index, ""); LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_len_index, ""); - LLVMValueRef ptr_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_field_ptr), + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), ptr_field_ptr, 0, false, ""); - LLVMValueRef len_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(len_field_ptr), + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), len_field_ptr, 0, false, ""); LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), ""); @@ -4962,7 +4959,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 1, ""); LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addrs_slice_ptr), + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), addrs_slice_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP2(g->builder, @@ -4970,7 +4967,7 @@ static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMV LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addrs_slice_ptr), + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), addrs_slice_ptr, slice_len_index, ""); LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } @@ -5064,7 +5061,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_slice_llvm_ty, frame_slice_ptr, slice_ptr_index, ""); LLVMValueRef frame_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); @@ -5127,7 +5124,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI // Store a zero in the awaiter's result ptr to indicate we do not need a copy made. LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 1, ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetGEPSourceElementType(awaiter_ret_ptr)); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr)); LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); } @@ -5145,7 +5142,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_fn_ptr_index, ""); LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, - LLVMGetGEPSourceElementType(fn_ptr_ptr), ""); + ZigLLVMGetGEPResultElementType(fn_ptr_ptr), ""); LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_resume_index, ""); @@ -5362,7 +5359,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type), frame_slice_ptr, slice_ptr_index, ""); frame_result_loc_uncasted = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(frame_ptr_ptr), frame_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { @@ -5551,7 +5548,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, union_type), union_ptr, union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = gen_load_untyped(g, LLVMGetGEPSourceElementType(tag_field_ptr), + LLVMValueRef tag_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(tag_field_ptr), tag_field_ptr, 0, false, ""); @@ -5787,7 +5784,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, maybe_type), maybe_handle, maybe_null_index, ""); - return gen_load_untyped(g, LLVMGetGEPSourceElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); + return gen_load_untyped(g, ZigLLVMGetGEPResultElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); } static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, @@ -6272,7 +6269,7 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, Stag LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, instruction->target->value->type->data.pointer.child_type), target_val, (unsigned)ptr_index, ""); - ptr_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); + ptr_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); } else { zig_unreachable(); } @@ -6759,7 +6756,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air if (!instruction->end || want_runtime_safety) { LLVMValueRef src_len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, gen_len_index, ""); - prev_end = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_len_ptr), src_len_ptr, 0, false, ""); + prev_end = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_len_ptr), src_len_ptr, 0, false, ""); } LLVMValueRef start_val = ir_llvm_value(g, instruction->start); @@ -6804,7 +6801,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, gen_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, LLVMGetGEPSourceElementType(src_ptr_ptr), + LLVMValueRef src_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_ptr_ptr), src_ptr_ptr, 0, false, ""); if (sentinel != nullptr) { @@ -7005,7 +7002,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, Stage1 if (type_has_bits(g, payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, err_union_type), err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -7077,7 +7074,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab if (type_has_bits(g, payload_type)) { LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, LLVMGetGEPSourceElementType(err_val_ptr), err_val_ptr, 0, false, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -7602,7 +7599,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_struct_llvm_ty, target_frame_ptr, frame_ret_start, ""); their_result_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); if (result_loc != nullptr) { LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, ""); @@ -7620,7 +7617,7 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins target_frame_struct_llvm_ty, target_frame_ptr, frame_index_trace_arg(g, result_type), ""); LLVMValueRef src_trace_ptr = LLVMBuildLoad2(g->builder, - LLVMGetGEPSourceElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); + ZigLLVMGetGEPResultElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; @@ -7668,7 +7665,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air target_frame_ptr, frame_ret_start + 1, ""); if (result_loc == nullptr) { // no copy needed - LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetGEPSourceElementType(awaiter_ret_ptr_ptr)), + LLVMBuildStore(g->builder, LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr)), awaiter_ret_ptr_ptr); } else { LLVMBuildStore(g->builder, result_loc, awaiter_ret_ptr_ptr); @@ -9353,7 +9350,7 @@ static void do_code_gen(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; @@ -9364,7 +9361,7 @@ static void do_code_gen(CodeGen *g) { size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, - LLVMGetGEPSourceElementType(addresses_field_ptr), + ZigLLVMGetGEPResultElementType(addresses_field_ptr), addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -9443,7 +9440,7 @@ static void do_code_gen(CodeGen *g) { get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), g->cur_frame_ptr, frame_index_trace_arg(g, fn_type_id->return_type), ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetGEPSourceElementType(trace_ptr_ptr)); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(trace_ptr_ptr)); LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr); } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index a1b0f6a30c..4f9cd76c6a 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -1195,6 +1195,10 @@ void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); } +LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP) { + return wrap(unwrap(GEP)->getResultElementType()); +} + void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { unwrap(function)->setPrefixData(unwrap(data)); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 6bd6191217..7fdddda6a4 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -322,6 +322,8 @@ ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val); ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); +ZIG_EXTERN_C LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP); + ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); -- cgit v1.2.3 From 99318e7a95220c0bba88eb42b17747ef79da176d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Aug 2022 00:04:38 -0700 Subject: LLVM backend fixes Fixing assertions hit after upgrading to opaque pointers API. --- src/codegen/llvm.zig | 2 +- src/stage1/codegen.cpp | 45 +++++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 25 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a1000a8945..e3cb6f9cd8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5803,7 +5803,7 @@ pub const FuncGen = struct { .False, ); const call = self.builder.buildCall( - asm_fn.typeOf(), + llvm_fn_ty, asm_fn, llvm_param_values.ptr, @intCast(c_uint, param_count), diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 423e9b7085..960800317e 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -1352,7 +1352,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32)); LLVMValueRef return_address_ptr = LLVMBuildCall2(g->builder, - LLVMTypeOf(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); + LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); @@ -1455,9 +1455,12 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { } // Fetch the error name from the global table - LLVMValueRef err_table_indices[] = { err_val }; + LLVMValueRef err_table_indices[] = { + LLVMConstNull(usize_ty->llvm_type), + err_val, + }; LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, - get_llvm_type(g, str_type), + LLVMGlobalGetValueType(g->err_name_table), g->err_name_table, err_table_indices, 2, ""); LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, @@ -4088,9 +4091,8 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *execu LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false), }; LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); - LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, expr_val, - indices, 2, ""); + LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, + get_llvm_type(g, array_type), expr_val, indices, 2, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (ir_want_runtime_safety(g, &instruction->base) && ptr_index != SIZE_MAX) { LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, ptr_index, ""); @@ -4762,7 +4764,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), subscript_value }; - return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, child_type), array_ptr, + return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, indices, 2, ""); } else if (array_type->id == ZigTypeIdPointer) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); @@ -5440,8 +5442,6 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr); // not necessarily a pointer. could be ZigTypeIdStruct ZigType *struct_ptr_type = instruction->struct_ptr->value->type; - ZigType *struct_ty = (struct_ptr_type->id == ZigTypeIdPointer) ? - struct_ptr_type->data.pointer.child_type : struct_ptr_type; TypeStructField *field = instruction->field; if (!type_has_bits(g, field->type_entry)) @@ -5469,7 +5469,7 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable ir_assert(field->gen_index != SIZE_MAX, &instruction->base); LLVMValueRef field_ptr_val = LLVMBuildStructGEP2(g->builder, - get_llvm_type(g, struct_ty), struct_ptr, (unsigned)field->gen_index, ""); + get_llvm_type(g, struct_type), struct_ptr, (unsigned)field->gen_index, ""); ZigType *res_type = instruction->base.value->type; ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); if (res_type->data.pointer.host_int_bytes != 0) { @@ -5753,7 +5753,8 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(asm_fn), asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, function_type, + asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { if (param_needs_attr[i] != nullptr) { @@ -6073,11 +6074,9 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; - ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); - ZigType *str_type = get_slice_type(g, u8_ptr_type); - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, str_type); - return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, g->err_name_table, indices, 2, ""); + return LLVMBuildInBoundsGEP2(g->builder, + LLVMGlobalGetValueType(g->err_name_table), + g->err_name_table, indices, 2, ""); } static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { @@ -6697,15 +6696,14 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.array.child_type); - + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); if (want_runtime_safety && sentinel != nullptr) { LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), end_val, }; LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, - elem_llvm_ty, array_ptr, indices, 2, ""); + array_llvm_ty, array_ptr, indices, 2, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } @@ -6713,7 +6711,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMConstNull(g->builtin_types.entry_usize->llvm_type), start_val, }; - slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 2, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, indices, 2, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6732,15 +6730,14 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { - LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); - + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); if (want_runtime_safety && sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, &start_val, 1, ""); } -- cgit v1.2.3 From a3045b8abbba896da34a02266f2be89dd6c90ecc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 3 Aug 2022 16:42:27 -0700 Subject: LLVM backends: more LLVM 15 fixes uwtable now needs a "sync" or "async" parameter. more opaque pointer fixes --- src/codegen/llvm.zig | 16 +++++++++------- src/stage1/codegen.cpp | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e3cb6f9cd8..2439948639 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2365,7 +2365,7 @@ pub const DeclGen = struct { } dg.addFnAttr(llvm_fn, "nounwind"); if (comp.unwind_tables) { - dg.addFnAttr(llvm_fn, "uwtable"); + dg.addFnAttrString(llvm_fn, "uwtable", "sync"); } if (comp.bin_file.options.skip_linker_dependencies or comp.bin_file.options.no_builtin) @@ -4996,8 +4996,8 @@ pub const FuncGen = struct { const indices: [2]*const llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const elem_llvm_ty = try self.dg.lowerType(array_ty.childType()); - const ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indices, indices.len, ""); + const array_llvm_ty = try self.dg.lowerType(array_ty); + const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, ""); const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); return self.builder.buildInsertValue(partial, len, 1, ""); } @@ -5174,13 +5174,14 @@ pub const FuncGen = struct { const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); if (isByRef(array_ty)) { - const elem_ty = array_ty.childType(); - const elem_llvm_ty = try self.dg.lowerType(elem_ty); + const array_llvm_ty = try self.dg.lowerType(array_ty); const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, array_llvm_val, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); + const elem_ty = array_ty.childType(); if (isByRef(elem_ty)) { return elem_ptr; } else { + const elem_llvm_ty = try self.dg.lowerType(elem_ty); return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } @@ -7306,6 +7307,7 @@ pub const FuncGen = struct { } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. + const array_llvm_ty = try self.dg.lowerType(operand_ty); const elem_llvm_ty = try self.dg.lowerType(elem_ty); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); @@ -7317,7 +7319,7 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(elem_llvm_ty, operand, &indexes, indexes.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indexes, indexes.len, ""); const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); } diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index beb557ee99..111aa7a58f 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -223,7 +223,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) { static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { if (g->unwind_tables) { - addLLVMFnAttr(fn_val, "uwtable"); + addLLVMFnAttrStr(fn_val, "uwtable", "sync"); } } -- cgit v1.2.3 From ac5c6b6061c6454a891c22a8258069370b57c05b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Aug 2022 17:32:46 -0700 Subject: stage2 LLVM backend: opaque pointer fixes --- src/codegen/llvm.zig | 118 ++++++++++++++++++++++++++++++++------------------- src/type.zig | 5 +++ 2 files changed, 80 insertions(+), 43 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2439948639..a286f8ad01 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2523,16 +2523,7 @@ pub const DeclGen = struct { if (ptr_info.host_size != 0) { return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace); } - const elem_ty = ptr_info.pointee_type; - const lower_elem_ty = switch (elem_ty.zigTypeTag()) { - .Opaque, .Fn => true, - .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), - else => elem_ty.hasRuntimeBitsIgnoreComptime(), - }; - const llvm_elem_ty = if (lower_elem_ty) - try dg.lowerType(elem_ty) - else - dg.context.intType(8); + const llvm_elem_ty = try dg.lowerPtrElemTy(ptr_info.pointee_type); return llvm_elem_ty.pointerType(llvm_addrspace); }, .Opaque => switch (t.tag()) { @@ -2917,6 +2908,23 @@ pub const DeclGen = struct { ); } + /// Use this instead of lowerType when you want to handle correctly the case of elem_ty + /// being a zero bit type, but it should still be lowered as an i8 in such case. + /// There are other similar cases handled here as well. + fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*const llvm.Type { + const lower_elem_ty = switch (elem_ty.zigTypeTag()) { + .Opaque, .Fn => true, + .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), + else => elem_ty.hasRuntimeBitsIgnoreComptime(), + }; + const llvm_elem_ty = if (lower_elem_ty) + try dg.lowerType(elem_ty) + else + dg.context.intType(8); + + return llvm_elem_ty; + } + fn lowerValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value { if (tv.val.isUndef()) { const llvm_type = try dg.lowerType(tv.ty); @@ -4674,8 +4682,8 @@ pub const FuncGen = struct { _ = self.builder.buildBr(end_block); self.builder.positionBuilderAtEnd(both_pl_block); - const lhs_payload = self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); - const rhs_payload = self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); + const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); + const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); _ = self.builder.buildBr(end_block); const both_pl_block_end = self.builder.getInsertBlock(); @@ -5133,7 +5141,8 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); - const slice_llvm_ty = try self.dg.lowerType(self.air.typeOf(ty_op.operand).childType()); + const slice_ptr_ty = self.air.typeOf(ty_op.operand); + const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType()); return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } @@ -5145,7 +5154,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*const llvm.Value = .{index}; const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5160,7 +5169,7 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(slice_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); const base_ptr = self.builder.buildExtractValue(slice, 0, ""); const indices: [1]*const llvm.Value = .{index}; return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); @@ -5195,9 +5204,10 @@ pub const FuncGen = struct { const ptr_ty = self.air.typeOf(bin_op.lhs); if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch const ptr = if (ptr_ty.isSinglePointer()) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5220,7 +5230,7 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); - const llvm_elem_ty = try self.dg.lowerType(elem_ty); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); if (ptr_ty.isSinglePointer()) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; @@ -5555,7 +5565,9 @@ pub const FuncGen = struct { const max_param_count = inputs.len + outputs.len; const llvm_param_types = try arena.alloc(*const llvm.Type, max_param_count); const llvm_param_values = try arena.alloc(*const llvm.Value, max_param_count); - const llvm_param_attrs = try arena.alloc(bool, max_param_count); + // This stores whether we need to add an elementtype attribute and + // if so, the element type itself. + const llvm_param_attrs = try arena.alloc(?*const llvm.Type, max_param_count); const target = self.dg.module.getTarget(); var llvm_ret_i: usize = 0; @@ -5573,7 +5585,7 @@ pub const FuncGen = struct { // for the string, we still use the next u32 for the null terminator. extra_i += (constraint.len + name.len + (2 + 3)) / 4; - try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); + try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 3); if (total_i != 0) { llvm_constraints.appendAssumeCapacity(','); } @@ -5582,8 +5594,10 @@ pub const FuncGen = struct { // Pass any non-return outputs indirectly, if the constraint accepts a memory location llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint); if (output != .none) { - try llvm_constraints.ensureUnusedCapacity(self.gpa, llvm_constraints.capacity + 1); const output_inst = try self.resolveInst(output); + const output_ty = self.air.typeOf(output); + assert(output_ty.zigTypeTag() == .Pointer); + const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType()); if (llvm_ret_indirect[i]) { // Pass the result by reference as an indirect output (e.g. "=*m") @@ -5591,11 +5605,11 @@ pub const FuncGen = struct { llvm_param_values[llvm_param_i] = output_inst; llvm_param_types[llvm_param_i] = output_inst.typeOf(); - llvm_param_attrs[llvm_param_i] = true; + llvm_param_attrs[llvm_param_i] = elem_llvm_ty; llvm_param_i += 1; } else { // Pass the result directly (e.g. "=r") - llvm_ret_types[llvm_ret_i] = output_inst.typeOf().getElementType(); + llvm_ret_types[llvm_ret_i] = elem_llvm_ty; llvm_ret_i += 1; } } else { @@ -5633,7 +5647,9 @@ pub const FuncGen = struct { const arg_llvm_value = try self.resolveInst(input); const arg_ty = self.air.typeOf(input); + var llvm_elem_ty: ?*const llvm.Type = null; if (isByRef(arg_ty)) { + llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); if (constraintAllowsMemory(constraint)) { llvm_param_values[llvm_param_i] = arg_llvm_value; llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); @@ -5677,7 +5693,12 @@ pub const FuncGen = struct { // In the case of indirect inputs, LLVM requires the callsite to have // an elementtype() attribute. - llvm_param_attrs[llvm_param_i] = constraint[0] == '*'; + if (constraint[0] == '*') { + llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse + try self.dg.lowerPtrElemTy(arg_ty.childType()); + } else { + llvm_param_attrs[llvm_param_i] = null; + } llvm_param_i += 1; total_i += 1; @@ -5812,10 +5833,9 @@ pub const FuncGen = struct { .Auto, "", ); - for (llvm_param_attrs[0..param_count]) |need_elem_ty, i| { - if (need_elem_ty) { - const elem_ty = llvm_param_types[i].getElementType(); - llvm.setCallElemTypeAttr(call, i, elem_ty); + for (llvm_param_attrs[0..param_count]) |llvm_elem_ty, i| { + if (llvm_elem_ty) |llvm_ty| { + llvm.setCallElemTypeAttr(call, i, llvm_ty); } } @@ -6558,7 +6578,7 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.air.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ @@ -6580,7 +6600,7 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.air.typeOf(bin_op.lhs); - const llvm_elem_ty = try self.dg.lowerType(ptr_ty.childType()); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ @@ -7564,7 +7584,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const llvm_i32 = self.context.intType(32); - const llvm_fn_name = "llvm.frameaddress.p0i8"; + const llvm_fn_name = "llvm.frameaddress.p0"; const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const llvm_p0i8 = self.context.intType(8).pointerType(0); const param_types = [_]*const llvm.Type{llvm_i32}; @@ -7694,20 +7714,31 @@ pub const FuncGen = struct { const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.air.typeOf(atomic_load.ptr); - if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) + const ptr_info = ptr_ty.ptrInfo().data; + if (!ptr_info.@"volatile" and self.liveness.isUnused(inst)) + return null; + const elem_ty = ptr_info.pointee_type; + if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; const ordering = toLlvmAtomicOrdering(atomic_load.order); - const operand_ty = ptr_ty.elemType(); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); + const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); + const target = self.dg.module.getTarget(); + const ptr_alignment = ptr_info.alignment(target); + const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile"); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); - if (opt_abi_ty) |abi_ty| { + if (opt_abi_llvm_ty) |abi_llvm_ty| { // operand needs widening and truncating - const casted_ptr = self.builder.buildBitCast(ptr, abi_ty.pointerType(0), ""); - const load_inst = (try self.load(casted_ptr, ptr_ty)).?; + const casted_ptr = self.builder.buildBitCast(ptr, abi_llvm_ty.pointerType(0), ""); + const load_inst = self.builder.buildLoad(abi_llvm_ty, casted_ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); - return self.builder.buildTrunc(load_inst, try self.dg.lowerType(operand_ty), ""); + return self.builder.buildTrunc(load_inst, elem_llvm_ty, ""); } - const load_inst = (try self.load(ptr, ptr_ty)).?; + const load_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); return load_inst; } @@ -8508,7 +8539,7 @@ pub const FuncGen = struct { const llvm_ptr_u8 = llvm_u8.pointerType(0); const llvm_u32 = self.context.intType(32); - const llvm_fn_name = "llvm.prefetch.p0i8"; + const llvm_fn_name = "llvm.prefetch.p0"; const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { // declare void @llvm.prefetch(i8*, i32, i32, i32) const llvm_void = self.context.voidType(); @@ -8660,7 +8691,7 @@ pub const FuncGen = struct { opt_llvm_ty: *const llvm.Type, opt_handle: *const llvm.Value, opt_ty: Type, - ) *const llvm.Value { + ) !*const llvm.Value { var buf: Type.Payload.ElemType = undefined; const payload_ty = opt_ty.optionalChild(&buf); @@ -8673,7 +8704,8 @@ pub const FuncGen = struct { } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); + const payload_llvm_ty = try fg.dg.lowerType(payload_ty); + const load_inst = fg.builder.buildLoad(payload_llvm_ty, payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } @@ -8758,7 +8790,7 @@ pub const FuncGen = struct { return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); }, else => { - const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); var ty_buf: Type.Payload.Pointer = undefined; if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { @@ -8815,7 +8847,7 @@ pub const FuncGen = struct { if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null; const target = self.dg.module.getTarget(); - const ptr_alignment = ptr_ty.ptrAlignment(target); + const ptr_alignment = info.alignment(target); const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); if (info.host_size == 0) { const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); diff --git a/src/type.zig b/src/type.zig index e078170281..a585c830fb 100644 --- a/src/type.zig +++ b/src/type.zig @@ -6229,6 +6229,11 @@ pub const Type = extern union { mutable: bool = true, // TODO rename this to const, not mutable @"volatile": bool = false, size: std.builtin.Type.Pointer.Size = .One, + + pub fn alignment(data: Data, target: Target) u32 { + if (data.@"align" != 0) return data.@"align"; + return abiAlignment(data.pointee_type, target); + } }; }; -- cgit v1.2.3 From b5dc8b67bc2e5dd920a5cabbe32c999f8ea71257 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 29 Aug 2022 15:00:31 -0700 Subject: LLVM: update merged master branch code to opaque pointers --- src/codegen/llvm.zig | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e6bebe521e..6d910d0551 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -964,19 +964,19 @@ pub const Object = struct { else => {}, } } - const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; @@ -4529,13 +4529,13 @@ pub const FuncGen = struct { else => {}, } } - const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = self.builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -8169,7 +8169,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -9249,8 +9249,9 @@ pub const FuncGen = struct { switch (target.cpu.arch) { .x86_64 => { + const array_llvm_ty = usize_llvm_ty.arrayType(6); const array_ptr = fg.valgrind_client_request_array orelse a: { - const array_ptr = fg.buildAlloca(usize_llvm_ty.arrayType(6)); + const array_ptr = fg.buildAlloca(array_llvm_ty); array_ptr.setAlignment(usize_alignment); fg.valgrind_client_request_array = array_ptr; break :a array_ptr; @@ -9261,7 +9262,7 @@ pub const FuncGen = struct { const indexes = [_]*const llvm.Value{ zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = fg.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); const store_inst = fg.builder.buildStore(elem, elem_ptr); store_inst.setAlignment(usize_alignment); } @@ -9291,6 +9292,7 @@ pub const FuncGen = struct { ); const call = fg.builder.buildCall( + fn_llvm_ty, asm_fn, &args, args.len, -- cgit v1.2.3 From bf28765a975355c27558eaa86cf00ccb29b663a7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 29 Aug 2022 18:19:39 -0700 Subject: LLVM: upgrade byval attr code to LLVM 15 opaque pointers Follow-up from 74673b7f69b27dc39a653f92eb58bba71e289f39. --- src/codegen/llvm.zig | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6d910d0551..e8e895e1fc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -797,6 +797,7 @@ pub const Object = struct { const param_ty = fn_info.param_types[it.zig_index - 1]; const param = llvm_func.getParam(llvm_arg_i); try args.ensureUnusedCapacity(1); + assert(!it.byval_attr); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); @@ -840,11 +841,16 @@ pub const Object = struct { }, .byref => { const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); + const alignment = param_ty.abiAlignment(target); dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", param_ty.abiAlignment(target)); + dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", alignment); + if (it.byval_attr) { + llvm_func.addByValAttr(llvm_arg_i, param_llvm_ty); + } llvm_arg_i += 1; @@ -853,14 +859,13 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(param); } else { - const alignment = param_ty.abiAlignment(target); - const param_llvm_ty = try dg.lowerType(param_ty); const load_inst = builder.buildLoad(param_llvm_ty, param, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } }, .abi_sized_int => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; @@ -890,6 +895,7 @@ pub const Object = struct { } }, .slice => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const ptr_info = param_ty.ptrInfo().data; @@ -919,6 +925,7 @@ pub const Object = struct { try args.append(aggregate); }, .multiple_llvm_ints => { + assert(!it.byval_attr); const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -949,6 +956,7 @@ pub const Object = struct { try args.append(loaded); }, .multiple_llvm_float => { + assert(!it.byval_attr); const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -983,6 +991,7 @@ pub const Object = struct { try args.append(loaded); }, .as_u16 => { + assert(!it.byval_attr); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const casted = builder.buildBitCast(param, dg.context.halfType(), ""); @@ -2406,14 +2415,6 @@ pub const DeclGen = struct { dg.addFnAttr(llvm_fn, "noreturn"); } - var llvm_arg_i = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing); - var it = iterateParamTypes(dg, fn_info); - while (it.next()) |_| : (llvm_arg_i += 1) { - if (!it.byval_attr) continue; - const param = llvm_fn.getParam(llvm_arg_i); - llvm_fn.addByValAttr(llvm_arg_i, param.typeOf().getElementType()); - } - return llvm_fn; } -- cgit v1.2.3 From fb81ba87620467de11db6b904741b4aafc7cb756 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 30 Aug 2022 14:45:03 -0700 Subject: LLVM: fix extern functions missing attributes Extern functions were missing attributes such as "readonly" on non-optional pointers, and "byval" which is required to match C ABI. Follow-up from bf28765a975355c27558eaa86cf00ccb29b663a7. closes #12683 --- src/codegen/llvm.zig | 126 +++++++++++++++++++++++++++++++++++++-------------- test/standalone.zig | 2 +- 2 files changed, 92 insertions(+), 36 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b241c1cbcb..badf0721c7 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -910,10 +910,11 @@ pub const Object = struct { while (it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { - const param_ty = fn_info.param_types[it.zig_index - 1]; + assert(!it.byval_attr); + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; const param = llvm_func.getParam(llvm_arg_i); try args.ensureUnusedCapacity(1); - assert(!it.byval_attr); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); @@ -926,32 +927,7 @@ pub const Object = struct { } else { args.appendAssumeCapacity(param); - if (param_ty.isPtrAtRuntime()) { - const ptr_info = param_ty.ptrInfo().data; - if (math.cast(u5, it.zig_index - 1)) |i| { - if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { - dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); - } - } - if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - } - if (!ptr_info.mutable) { - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - } - if (ptr_info.@"align" != 0) { - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); - } else { - const elem_align = @maximum( - ptr_info.pointee_type.abiAlignment(target), - 1, - ); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); - } - } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { - .signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"), - .unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"), - }; + dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); } llvm_arg_i += 1; }, @@ -961,13 +937,7 @@ pub const Object = struct { const param = llvm_func.getParam(llvm_arg_i); const alignment = param_ty.abiAlignment(target); - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", alignment); - if (it.byval_attr) { - llvm_func.addByValAttr(llvm_arg_i, param_llvm_ty); - } - + dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); llvm_arg_i += 1; try args.ensureUnusedCapacity(1); @@ -2531,6 +2501,39 @@ pub const DeclGen = struct { dg.addFnAttr(llvm_fn, "noreturn"); } + // Add parameter attributes. We handle only the case of extern functions (no body) + // because functions with bodies are handled in `updateFunc`. + if (is_extern) { + var it = iterateParamTypes(dg, fn_info); + it.llvm_index += @boolToInt(sret); + it.llvm_index += @boolToInt(err_return_tracing); + while (it.next()) |lowering| switch (lowering) { + .byval => { + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; + if (!isByRef(param_ty)) { + dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); + } + }, + .byref => { + const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); + const alignment = param_ty.abiAlignment(target); + dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + }, + // No attributes needed for these. + .no_bits, + .abi_sized_int, + .multiple_llvm_ints, + .multiple_llvm_float, + .as_u16, + => continue, + + .slice => unreachable, // extern functions do not support slice types. + + }; + } + return llvm_fn; } @@ -4141,6 +4144,59 @@ pub const DeclGen = struct { return null; } } + + fn addByValParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + param_ty: Type, + param_index: u32, + fn_info: Type.Payload.Function.Data, + llvm_arg_i: u32, + ) void { + const target = dg.module.getTarget(); + if (param_ty.isPtrAtRuntime()) { + const ptr_info = param_ty.ptrInfo().data; + if (math.cast(u5, param_index)) |i| { + if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); + } + } + if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + } + if (!ptr_info.mutable) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + } + if (ptr_info.@"align" != 0) { + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); + } else { + const elem_align = @maximum( + ptr_info.pointee_type.abiAlignment(target), + 1, + ); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); + } + } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { + .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), + .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), + }; + } + + fn addByRefParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + llvm_arg_i: u32, + alignment: u32, + byval_attr: bool, + param_llvm_ty: *const llvm.Type, + ) void { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); + if (byval_attr) { + llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty); + } + } }; pub const FuncGen = struct { diff --git a/test/standalone.zig b/test/standalone.zig index bfd683ec4c..463b87556e 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -44,7 +44,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { } // C ABI compatibility issue: https://github.com/ziglang/zig/issues/1481 if (builtin.cpu.arch == .x86_64) { - if (builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) { // https://github.com/ziglang/zig/issues/12222 + if (builtin.zig_backend == .stage1 or builtin.zig_backend == .stage2_llvm) { cases.addBuildFile("test/c_abi/build.zig", .{}); } } -- cgit v1.2.3 From cdb40936bd528ee92dd11cf090ab75cf08bc0fc0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 13 Sep 2022 03:03:34 -0700 Subject: properly annotate nullability of ZigLLVMCreateDebugForwardDeclType This bug manifested as a segfault in stage1 when calling this function. The C++ code looks like this: ```c++ entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, ZigLLVMTag_DW_structure_type(), full_name, import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, import ? import->data.structure.root_struct->di_file : nullptr, line); ``` There is actually no problem here - what happened is that because cross-language LTO was enabled between zig and c++ code, and because Zig annotated the file parameter (3rd line) as being non-null, the C++ code assumed that parameter could not be null, and eagerly dereferenced `import->...`, causing a segfault, since it was null. I verified that this commit fixed the problem and I also verified this hypothesis by disabling LTO and noticing that it indeed avoided the problem. --- src/codegen/llvm/bindings.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index d1a386ac60..81e722bed8 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -1734,8 +1734,8 @@ pub const DIBuilder = opaque { dib: *DIBuilder, tag: c_uint, name: [*:0]const u8, - scope: *DIScope, - file: *DIFile, + scope: ?*DIScope, + file: ?*DIFile, line: c_uint, ) *DIType; -- cgit v1.2.3