Commit efa771af75

Andrew Kelley <superjoe30@gmail.com>
2017-04-25 20:20:15
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
1 parent e0050af
Changed files (2)
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;
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) {