From 7b3686861f87d006da817db98f7d3b13fada9815 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 25 Jul 2019 22:24:01 -0400 Subject: [PATCH] `@frameSize` works via PrefixData --- BRANCH_TODO | 9 +++++++++ src/all_types.hpp | 1 - src/codegen.cpp | 21 +++++++++++++-------- src/ir.cpp | 12 ++---------- src/ir_print.cpp | 2 -- src/zig_llvm.cpp | 6 +++++- src/zig_llvm.h | 1 + 7 files changed, 30 insertions(+), 22 deletions(-) diff --git a/BRANCH_TODO b/BRANCH_TODO index 6ea57d2173..d10bc704d8 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,5 +1,14 @@ + * reimplement @frameSize with Prefix Data + * reimplement with function splitting rather than switch + * add the `anyframe` type and `anyframe->T` * await * await of a non async function + * await in single-threaded mode * async call on a non async function + * @asyncCall with an async function pointer + * cancel + * defer and errdefer * safety for resuming when it is awaiting * implicit cast of normal function to async function should be allowed when it is inferred to be async + * go over the commented out tests + * revive std.event.Loop diff --git a/src/all_types.hpp b/src/all_types.hpp index d30b3b8a80..6ee3a6b937 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -3063,7 +3063,6 @@ struct IrInstructionFrameSizeGen { IrInstruction base; IrInstruction *fn; - IrInstruction *frame_ptr; }; enum IrOverflowOp { diff --git a/src/codegen.cpp b/src/codegen.cpp index 6fc152ad3e..4343006b17 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4914,13 +4914,16 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, return nullptr; } -static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable, IrInstructionFrameSizeGen *instruction) { +static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable, + IrInstructionFrameSizeGen *instruction) +{ + LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type; + LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0); LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn); - LLVMValueRef frame_ptr = ir_llvm_value(g, instruction->frame_ptr); - LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_ptr, coro_resume_index_index, ""); - LLVMValueRef one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false); - LLVMBuildStore(g->builder, one, resume_index_ptr); - return ZigLLVMBuildCall(g->builder, fn_val, &frame_ptr, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, ""); + 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, ""); + return LLVMBuildLoad(g->builder, prefix_ptr, ""); } static void set_debug_location(CodeGen *g, IrInstruction *instruction) { @@ -6409,13 +6412,16 @@ static void do_code_gen(CodeGen *g) { } if (is_async) { + 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); + ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); + if (!g->strip_debug_symbols) { AstNode *source_node = fn_table_entry->proto_node; ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope)); } IrExecutable *executable = &fn_table_entry->analyzed_executable; - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume"); LLVMPositionBuilderAtEnd(g->builder, bad_resume_block); gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope); @@ -6424,7 +6430,6 @@ static void do_code_gen(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, get_size_block); assert(fn_table_entry->frame_type->abi_size != 0); assert(fn_table_entry->frame_type->abi_size != SIZE_MAX); - LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); LLVMBuildRet(g->builder, size_val); LLVMPositionBuilderAtEnd(g->builder, fn_table_entry->preamble_llvm_block); diff --git a/src/ir.cpp b/src/ir.cpp index 1a62af8ce4..7a5af347b7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2396,15 +2396,12 @@ static IrInstruction *ir_build_frame_size_src(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_frame_size_gen(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn, - IrInstruction *frame_ptr) +static IrInstruction *ir_build_frame_size_gen(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) { IrInstructionFrameSizeGen *instruction = ir_build_instruction(irb, scope, source_node); instruction->fn = fn; - instruction->frame_ptr = frame_ptr; ir_ref_instruction(fn, irb->current_basic_block); - ir_ref_instruction(frame_ptr, irb->current_basic_block); return &instruction->base; } @@ -21808,13 +21805,8 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru return ira->codegen->invalid_instruction; } - IrInstruction *frame_ptr = ir_resolve_result(ira, &instruction->base, no_result_loc(), - ira->codegen->builtin_types.entry_frame_header, nullptr, true, false); - if (frame_ptr != nullptr && (type_is_invalid(frame_ptr->value.type) || instr_is_unreachable(frame_ptr))) - return frame_ptr; - IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope, - instruction->base.source_node, fn, frame_ptr); + instruction->base.source_node, fn); result->value.type = ira->codegen->builtin_types.entry_usize; return result; } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 7e903ed662..ae467bdc8c 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -925,8 +925,6 @@ static void ir_print_frame_size_src(IrPrint *irp, IrInstructionFrameSizeSrc *ins static void ir_print_frame_size_gen(IrPrint *irp, IrInstructionFrameSizeGen *instruction) { fprintf(irp->f, "@frameSize("); ir_print_other_instruction(irp, instruction->fn); - fprintf(irp->f, ","); - ir_print_other_instruction(irp, instruction->frame_ptr); fprintf(irp->f, ")"); } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index b52edabe65..906b278b21 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -899,9 +899,13 @@ LLVMValueRef ZigLLVMBuildAShrExact(LLVMBuilderRef builder, LLVMValueRef LHS, LLV } void ZigLLVMSetTailCall(LLVMValueRef Call) { - unwrap(Call)->setTailCallKind(CallInst::TCK_MustTail); + unwrap(Call)->setTailCallKind(CallInst::TCK_MustTail); } +void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { + unwrap(function)->setPrefixData(unwrap(data)); +} + class MyOStream: public raw_ostream { public: diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 2a2ab567a6..2be119ba0c 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -212,6 +212,7 @@ ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigne ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); ZIG_EXTERN_C void ZigLLVMSetTailCall(LLVMValueRef Call); +ZIG_EXTERN_C void ZigLLVMFunctionSetPrefixData(LLVMValueRef fn, LLVMValueRef data); ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn);