From d5968086fe357aa5cf678327295677dba5102fc8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 2 Sep 2018 21:08:59 -0400 Subject: use the sret attribute at the callsite when appropriate Thanks to Shawn Landden for the original pull request. closes #1450 --- src/codegen.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index f25ecd8e08..388a1a371f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3101,6 +3101,12 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { LLVMBuildCall(g->builder, write_register_fn_val, params, 2, ""); } +static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { + unsigned attr_kind_id = LLVMGetEnumAttributeKindForName("sret", 4); + LLVMAttributeRef sret_attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), attr_kind_id, 1); + LLVMAddCallSiteAttribute(call_instr, 1, sret_attr); +} + static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) { LLVMValueRef fn_val; TypeTableEntry *fn_type; @@ -3196,6 +3202,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr } else if (!ret_has_bits) { return nullptr; } else if (first_arg_ret) { + set_call_instr_sret(g, result); return instruction->tmp_ptr; } else if (handle_is_ptr(src_return_type)) { auto store_instr = LLVMBuildStore(g->builder, result, instruction->tmp_ptr); @@ -4662,8 +4669,9 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f args.append(allocator_val); args.append(coro_size); args.append(alignment_val); - ZigLLVMBuildCall(g->builder, alloc_fn_val, args.items, args.length, + LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, alloc_fn_val, args.items, args.length, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); + set_call_instr_sret(g, call_instruction); LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, sret_ptr, err_union_err_index, ""); LLVMValueRef err_val = LLVMBuildLoad(g->builder, err_val_ptr, ""); LLVMBuildStore(g->builder, err_val, err_code_ptr); -- cgit v1.2.3 From 95636c7e5ff6ad0eeb768a2a0a1d7533b5872e20 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 3 Sep 2018 00:04:12 -0400 Subject: ability to @ptrCast to *void fixes #960 --- src/codegen.cpp | 3 +++ src/ir.cpp | 10 ++++++++-- test/cases/cast.zig | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 388a1a371f..298e89579f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2655,6 +2655,9 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, IrInstructionPtrCast *instruction) { TypeTableEntry *wanted_type = instruction->base.value.type; + if (!type_has_bits(wanted_type)) { + return nullptr; + } LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); } diff --git a/src/ir.cpp b/src/ir.cpp index 4e64b3e002..2c3fadfc2d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -19757,6 +19757,8 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3 } static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtrCast *instruction) { + Error err; + IrInstruction *dest_type_value = instruction->dest_type->other; TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value); if (type_is_invalid(dest_type)) @@ -19810,9 +19812,13 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc instruction->base.source_node, nullptr, ptr); casted_ptr->value.type = dest_type; - // keep the bigger alignment, it can only help + // Keep the bigger alignment, it can only help- + // unless the target is zero bits. + if ((err = type_ensure_zero_bits_known(ira->codegen, dest_type))) + return ira->codegen->builtin_types.entry_invalid; + IrInstruction *result; - if (src_align_bytes > dest_align_bytes) { + if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); if (type_is_invalid(result->value.type)) return ira->codegen->builtin_types.entry_invalid; diff --git a/test/cases/cast.zig b/test/cases/cast.zig index cc5e4b4394..2b455ccc43 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -519,3 +519,9 @@ fn incrementVoidPtrArray(array: ?*c_void, len: usize) void { @ptrCast([*]u8, array.?)[n] += 1; } } + +test "*usize to *void" { + var i = usize(0); + var v = @ptrCast(*void, &i); + v.* = {}; +} -- cgit v1.2.3