diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c3194ccda1..f92b025e7c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1126,6 +1126,7 @@ pub const Object = struct { } else { _ = self.llvm_module.addAlias( llvm_global.typeOf(), + 0, llvm_global, exp_name_z, ); @@ -2291,7 +2292,7 @@ pub const DeclGen = struct { dg.addArgAttr(llvm_fn, 0, "noalias"); const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type); - llvm_fn.addSretAttr(0, raw_llvm_ret_ty); + llvm_fn.addSretAttr(raw_llvm_ret_ty); } const err_return_tracing = fn_info.return_type.isError() and diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 90f3c84b7e..13e0b05064 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -206,7 +206,7 @@ pub const Value = opaque { extern fn LLVMDeleteFunction(Fn: *const Value) void; pub const addSretAttr = ZigLLVMAddSretAttr; - extern fn ZigLLVMAddSretAttr(fn_ref: *const Value, ArgNo: c_uint, type_val: *const Type) void; + extern fn ZigLLVMAddSretAttr(fn_ref: *const Value, type_val: *const Type) void; pub const setCallSret = ZigLLVMSetCallSret; extern fn ZigLLVMSetCallSret(Call: *const Value, return_type: *const Type) void; @@ -520,8 +520,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 = LLVMBuildLoad2; - extern fn LLVMBuildLoad2(*const Builder, Ty: *const Type, PointerVal: *const Value, Name: [*:0]const u8) *const Value; + pub const buildLoad = LLVMBuildLoad; + extern fn LLVMBuildLoad(*const Builder, 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; diff --git a/src/main.zig b/src/main.zig index 241a495a2e..849aa93d13 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4488,11 +4488,11 @@ pub fn lldMain( const llvm = @import("codegen/llvm/bindings.zig"); const argc = @intCast(c_int, argv.len); if (mem.eql(u8, args[1], "ld.lld")) { - break :rc llvm.LinkELF(argc, argv.ptr, can_exit_early); + break :rc llvm.LinkELF(argc, argv.ptr, can_exit_early, false); } else if (mem.eql(u8, args[1], "lld-link")) { - break :rc llvm.LinkCOFF(argc, argv.ptr, can_exit_early); + break :rc llvm.LinkCOFF(argc, argv.ptr, can_exit_early, false); } else if (mem.eql(u8, args[1], "wasm-ld")) { - break :rc llvm.LinkWasm(argc, argv.ptr, can_exit_early); + break :rc llvm.LinkWasm(argc, argv.ptr, can_exit_early, false); } else { unreachable; } diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 672de7cae3..700fc2af06 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -638,7 +638,7 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) { // Sret pointers must not be address 0 addLLVMArgAttr(llvm_fn, 0, "nonnull"); - ZigLLVMAddSretAttr(llvm_fn, 0, get_llvm_type(g, return_type)); + ZigLLVMAddSretAttr(llvm_fn, get_llvm_type(g, return_type)); if (cc_want_sret_attr(cc)) { addLLVMArgAttr(llvm_fn, 0, "noalias"); } @@ -912,10 +912,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, LLVMTypeRef elem_type, LLVMValueRef ptr, - uint32_t alignment, bool is_volatile, const char *name) +static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile, + const char *name) { - LLVMValueRef result = LLVMBuildLoad2(g->builder, elem_type, ptr, name); + LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, name); if (is_volatile) LLVMSetVolatile(result, true); if (alignment == 0) { LLVMSetAlignment(result, LLVMABIAlignmentOfType(g->target_data_ref, LLVMGetElementType(LLVMTypeOf(ptr)))); @@ -927,10 +927,8 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMTypeRef elem_type, LLVMValu static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) { assert(ptr_type->id == ZigTypeIdPointer); - ZigType *elem_type = ptr_type->data.pointer.child_type; uint32_t alignment = get_ptr_align(g, ptr_type); - return gen_load_untyped(g, get_llvm_type(g, elem_type), ptr, alignment, - ptr_type->data.pointer.is_volatile, name); + return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name); } static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) { @@ -1278,16 +1276,15 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { 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, usize_type_ref, len_field_ptr, 0, false, ""); - LLVMValueRef index_val = gen_load_untyped(g, usize_type_ref, index_field_ptr, 0, false, ""); + 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_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, }; - LLVMTypeRef ptr_to_usize = LLVMPointerType(usize_type_ref, 0); - LLVMValueRef ptr_value = gen_load_untyped(g, ptr_to_usize, ptr_field_ptr, 0, false, ""); + LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); gen_store_untyped(g, address_value, address_slot, 0, false); @@ -5562,6 +5559,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A size_t param_index = 0; LLVMTypeRef *param_types = heap::c_allocator.allocate(input_and_output_count); LLVMValueRef *param_values = heap::c_allocator.allocate(input_and_output_count); + bool *param_needs_attr = heap::c_allocator.allocate(input_and_output_count); for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); bool is_return = (asm_output->return_type != nullptr); @@ -5619,6 +5617,8 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A param_types[param_index] = type_ref; param_values[param_index] = value_ref; + // In the case of indirect inputs, LLVM requires the callsite to have an elementtype() attribute. + param_needs_attr[param_index] = buf_ptr(asm_input->constraint)[0] == '*'; } for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { Buf *clobber_buf = asm_expr->clobber_list.at(i); @@ -5658,14 +5658,25 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A ret_type = get_llvm_type(g, instruction->base.value->type); } LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); - heap::c_allocator.deallocate(param_types, input_and_output_count); bool is_volatile = instruction->has_side_effects || (asm_expr->output_list.length == 0); 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, ""); + + for (size_t i = 0; i < input_and_output_count; i += 1) { + if (param_needs_attr[i]) { + LLVMTypeRef elem_ty = LLVMGetElementType(param_types[i]); + ZigLLVMSetCallElemTypeAttr(built_call, i, elem_ty); + } + } + + + + heap::c_allocator.deallocate(param_types, input_and_output_count); heap::c_allocator.deallocate(param_values, input_and_output_count); + heap::c_allocator.deallocate(param_needs_attr, input_and_output_count); return built_call; } diff --git a/src/stage1/target.cpp b/src/stage1/target.cpp index b66bc36f8b..7c4587cdaa 100644 --- a/src/stage1/target.cpp +++ b/src/stage1/target.cpp @@ -531,6 +531,7 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { case ZigLLVM_renderscript32: case ZigLLVM_aarch64_32: case ZigLLVM_csky: + case ZigLLVM_spirv32: return 32; case ZigLLVM_aarch64: @@ -554,6 +555,7 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { case ZigLLVM_wasm64: case ZigLLVM_renderscript64: case ZigLLVM_ve: + case ZigLLVM_spirv64: return 64; } zig_unreachable(); @@ -598,6 +600,7 @@ uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { case ZigLLVM_wasm32: case ZigLLVM_renderscript32: case ZigLLVM_csky: + case ZigLLVM_spirv32: return 32; case ZigLLVM_aarch64: @@ -621,6 +624,7 @@ uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { case ZigLLVM_wasm64: case ZigLLVM_renderscript64: case ZigLLVM_ve: + case ZigLLVM_spirv64: return 64; case ZigLLVM_x86_64: @@ -818,6 +822,8 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { case ZigLLVM_wasm32: case ZigLLVM_wasm64: + case ZigLLVM_spirv32: + case ZigLLVM_spirv64: return nullptr; // known to be not available case ZigLLVM_amdgcn: @@ -919,6 +925,8 @@ bool target_is_arm(const ZigTarget *target) { case ZigLLVM_ppcle: case ZigLLVM_ppc64: case ZigLLVM_ve: + case ZigLLVM_spirv32: + case ZigLLVM_spirv64: return false; } zig_unreachable(); diff --git a/src/translate_c.zig b/src/translate_c.zig index 306f5d3ea1..880daa6213 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -4810,7 +4810,7 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan .rhs = try transQualType(c, scope, element_qt, source_loc), }); }, - .ExtInt, .ExtVector => { + .BitInt, .ExtVector => { const type_name = c.str(ty.getTypeClassName()); return fail(c, error.UnsupportedType, source_loc, "TODO implement translation of type: '{s}'", .{type_name}); }, diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 2a80129778..7cef3d01f7 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -1064,12 +1064,20 @@ void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_v func->addParamAttrs(ArgNo + 1, attr_builder); } -void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) { +void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val) { Function *func = unwrap(fn_ref); AttrBuilder attr_builder(func->getContext()); Type *llvm_type = unwrap(type_val); attr_builder.addStructRetAttr(llvm_type); - func->addParamAttrs(ArgNo + 1, attr_builder); + func->addParamAttrs(AttributeList::ReturnIndex, attr_builder); +} + +void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty) { + Function *func = unwrap(fn_ref); + AttrBuilder attr_builder(func->getContext()); + Type *llvm_type = unwrap(elem_ty); + attr_builder.addTypeAttr(Attribute::ElementType, llvm_type); + func->addParamAttrs(AttributeList::FirstArgIndex + arg_index, attr_builder); } void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) { @@ -1174,7 +1182,15 @@ void ZigLLVMSetTailCall(LLVMValueRef Call) { void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type) { CallInst *call_inst = unwrap(Call); Type *llvm_type = unwrap(return_type); - call_inst->addParamAttr(1, Attribute::getWithStructRetType(call_inst->getContext(), llvm_type)); + call_inst->addParamAttr(AttributeList::ReturnIndex, + Attribute::getWithStructRetType(call_inst->getContext(), llvm_type)); +} + +void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type) { + CallInst *call_inst = unwrap(Call); + Type *llvm_type = unwrap(return_type); + call_inst->addParamAttr(arg_index, + Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); } void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 5aff15db5f..ba8c31d668 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -311,12 +311,14 @@ ZIG_EXTERN_C LLVMValueRef ZigLLVMInsertDbgValueIntrinsicAtEnd(struct ZigLLVMDIBu ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call); ZIG_EXTERN_C void ZigLLVMSetCallSret(LLVMValueRef Call, LLVMTypeRef return_type); +ZIG_EXTERN_C void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef return_type); ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data); ZIG_EXTERN_C void ZigLLVMFunctionSetCallingConv(LLVMValueRef function, enum ZigLLVM_CallingConv cc); ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val); -ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val); +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 void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv);