| ... | ... | @@ -331,12 +331,45 @@ static LLVMValueRef get_handle_value(CodeGen *g, AstNode *source_node, LLVMValue |
| 331 | 331 | } |
| 332 | 332 | |
| 333 | 333 | static LLVMValueRef gen_err_name(CodeGen *g, AstNode *node) { |
| 334 | | zig_panic("TODO"); |
| 335 | | //assert(node->type == NodeTypeFnCallExpr); |
| 336 | | //assert(g->generate_error_name_table); |
| 337 | | //AstNode *err_val_node = node->data.fn_call_expr.params.at(0); |
| 338 | | //LLVMValueRef err_val = gen_expr(g, err_val_node); |
| 339 | | //arg |
| 334 | assert(node->type == NodeTypeFnCallExpr); |
| 335 | assert(g->generate_error_name_table); |
| 336 | |
| 337 | if (g->error_decls.length == 1) { |
| 338 | LLVMBuildUnreachable(g->builder); |
| 339 | return nullptr; |
| 340 | } |
| 341 | |
| 342 | |
| 343 | AstNode *err_val_node = node->data.fn_call_expr.params.at(0); |
| 344 | LLVMValueRef err_val = gen_expr(g, err_val_node); |
| 345 | add_debug_source_node(g, node); |
| 346 | |
| 347 | if (!g->is_release_build) { |
| 348 | LLVMBasicBlockRef bounds_check_fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckFail"); |
| 349 | LLVMBasicBlockRef lower_ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "LowerBoundsCheckOk"); |
| 350 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoundsCheckOk"); |
| 351 | |
| 352 | LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(err_val)); |
| 353 | LLVMValueRef is_zero_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, ""); |
| 354 | LLVMBuildCondBr(g->builder, is_zero_val, bounds_check_fail_block, lower_ok_block); |
| 355 | |
| 356 | LLVMPositionBuilderAtEnd(g->builder, bounds_check_fail_block); |
| 357 | LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, ""); |
| 358 | LLVMBuildUnreachable(g->builder); |
| 359 | |
| 360 | LLVMPositionBuilderAtEnd(g->builder, lower_ok_block); |
| 361 | LLVMValueRef end_val = LLVMConstInt(LLVMTypeOf(err_val), g->error_decls.length, false); |
| 362 | LLVMValueRef is_too_big_val = LLVMBuildICmp(g->builder, LLVMIntUGE, err_val, end_val, ""); |
| 363 | LLVMBuildCondBr(g->builder, is_too_big_val, bounds_check_fail_block, ok_block); |
| 364 | |
| 365 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 366 | } |
| 367 | |
| 368 | LLVMValueRef indices[] = { |
| 369 | LLVMConstNull(g->builtin_types.entry_isize->type_ref), |
| 370 | err_val, |
| 371 | }; |
| 372 | return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); |
| 340 | 373 | } |
| 341 | 374 | |
| 342 | 375 | static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| ... | ... | @@ -3030,6 +3063,46 @@ static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) { |
| 3030 | 3063 | return LLVMConstStruct(fields, 2, false); |
| 3031 | 3064 | } |
| 3032 | 3065 | |
| 3066 | static void generate_error_name_table(CodeGen *g) { |
| 3067 | if (!g->generate_error_name_table || g->error_decls.length == 1) { |
| 3068 | return; |
| 3069 | } |
| 3070 | |
| 3071 | assert(g->error_decls.length > 0); |
| 3072 | |
| 3073 | TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); |
| 3074 | TypeTableEntry *u8_ptr_type = str_type->data.structure.fields[0].type_entry; |
| 3075 | |
| 3076 | LLVMValueRef *values = allocate<LLVMValueRef>(g->error_decls.length); |
| 3077 | values[0] = LLVMGetUndef(str_type->type_ref); |
| 3078 | for (int i = 1; i < g->error_decls.length; i += 1) { |
| 3079 | AstNode *error_decl_node = g->error_decls.at(i); |
| 3080 | assert(error_decl_node->type == NodeTypeErrorValueDecl); |
| 3081 | Buf *name = &error_decl_node->data.error_value_decl.name; |
| 3082 | |
| 3083 | LLVMValueRef str_init = LLVMConstString(buf_ptr(name), buf_len(name), true); |
| 3084 | LLVMValueRef str_global = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); |
| 3085 | LLVMSetInitializer(str_global, str_init); |
| 3086 | LLVMSetLinkage(str_global, LLVMPrivateLinkage); |
| 3087 | LLVMSetGlobalConstant(str_global, true); |
| 3088 | LLVMSetUnnamedAddr(str_global, true); |
| 3089 | |
| 3090 | LLVMValueRef fields[] = { |
| 3091 | LLVMConstBitCast(str_global, u8_ptr_type->type_ref), |
| 3092 | LLVMConstInt(g->builtin_types.entry_isize->type_ref, buf_len(name), false), |
| 3093 | }; |
| 3094 | values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); |
| 3095 | } |
| 3096 | |
| 3097 | LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, g->error_decls.length); |
| 3098 | |
| 3099 | g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), "err_name_table"); |
| 3100 | LLVMSetInitializer(g->err_name_table, err_name_table_init); |
| 3101 | LLVMSetLinkage(g->err_name_table, LLVMPrivateLinkage); |
| 3102 | LLVMSetGlobalConstant(g->err_name_table, true); |
| 3103 | LLVMSetUnnamedAddr(g->err_name_table, true); |
| 3104 | } |
| 3105 | |
| 3033 | 3106 | static void do_code_gen(CodeGen *g) { |
| 3034 | 3107 | assert(!g->errors.length); |
| 3035 | 3108 | |
| ... | ... | @@ -3037,6 +3110,7 @@ static void do_code_gen(CodeGen *g) { |
| 3037 | 3110 | |
| 3038 | 3111 | |
| 3039 | 3112 | gen_const_globals(g); |
| 3113 | generate_error_name_table(g); |
| 3040 | 3114 | |
| 3041 | 3115 | // Generate module level variables |
| 3042 | 3116 | for (int i = 0; i < g->global_vars.length; i += 1) { |