From efa771af754281cd76a77ef22af107eb0a9aaf9a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 25 Apr 2017 14:20:15 -0400 Subject: [PATCH] compile time improvement - add __zig_panic_slice fn move some boilerplate code having to do with panicking to a function. Here's the timing difference. It's not much: Before: full test: 1m36.511s debug test: 20.862s hello.zig Name Start End Duration Percent Initialize 0.0000 0.0000 0.0000 0.0001 Semantic Analysis 0.0000 0.0421 0.0420 0.2109 Code Generation 0.0421 0.0620 0.0200 0.1003 LLVM Emit Object 0.0620 0.1852 0.1231 0.6180 Build Dependencies 0.1852 0.1974 0.0122 0.0615 LLVM Link 0.1974 0.1993 0.0018 0.0093 Generate .h 0.1993 0.1993 0.0000 0.0000 Total 0.0000 0.1993 0.1993 1.0000 After: full test: 1m33.588s debug test: 20.303s hello.zig Name Start End Duration Percent Initialize 0.0000 0.0000 0.0000 0.0002 Semantic Analysis 0.0000 0.0425 0.0425 0.2202 Code Generation 0.0425 0.0675 0.0250 0.1293 LLVM Emit Object 0.0675 0.1789 0.1114 0.5773 Build Dependencies 0.1789 0.1913 0.0124 0.0640 LLVM Link 0.1913 0.1931 0.0018 0.0091 Generate .h 0.1931 0.1931 0.0000 0.0000 Total 0.0000 0.1931 0.1931 1.0000 --- src/all_types.hpp | 1 + src/codegen.cpp | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 607efbdf68..a9bcf14d78 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1460,6 +1460,7 @@ struct CodeGen { LLVMValueRef err_name_table; size_t largest_err_name_len; LLVMValueRef safety_crash_err_fn; + LLVMValueRef panic_slice_fn; IrInstruction *invalid_instruction; ConstExprValue const_void_val; diff --git a/src/codegen.cpp b/src/codegen.cpp index 12cff60a17..efa9e26c05 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -647,8 +647,28 @@ static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len LLVMBuildUnreachable(g->builder); } -static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { +static LLVMValueRef get_panic_slice_fn(CodeGen *g) { + if (g->panic_slice_fn != nullptr) + return g->panic_slice_fn; + TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); + TypeTableEntry *ptr_to_str_type = get_pointer_to_type(g, str_type, true); + + Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_panic_slice"), false); + LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), &ptr_to_str_type->type_ref, 1, false); + LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); + addLLVMFnAttr(fn_val, "noreturn"); + addLLVMFnAttr(fn_val, "cold"); + LLVMSetLinkage(fn_val, LLVMInternalLinkage); + LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); + + LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); + LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); + LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); + LLVMPositionBuilderAtEnd(g->builder, entry_block); + + LLVMValueRef msg_arg = LLVMGetParam(fn_val, 0); + size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)ptr_index, ""); @@ -657,6 +677,17 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { LLVMValueRef msg_ptr = LLVMBuildLoad(g->builder, ptr_ptr, ""); LLVMValueRef msg_len = LLVMBuildLoad(g->builder, len_ptr, ""); gen_panic_raw(g, msg_ptr, msg_len); + + LLVMPositionBuilderAtEnd(g->builder, prev_block); + LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); + g->panic_slice_fn = fn_val; + return g->panic_slice_fn; +} + +static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { + LLVMValueRef fn_val = get_panic_slice_fn(g); + LLVMBuildCall(g->builder, fn_val, &msg_arg, 1, ""); + LLVMBuildUnreachable(g->builder); } static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {