| ... | ... | @@ -59,30 +59,31 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| 62 | |
| 62 | 63 | |
| 63 | | static LLVMTypeRef to_llvm_type(AstNode *type_node) { |
| 64 | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| 64 | 65 | assert(type_node->type == NodeTypeType); |
| 65 | 66 | assert(type_node->codegen_node); |
| 66 | 67 | assert(type_node->codegen_node->data.type_node.entry); |
| 67 | | |
| 68 | | return type_node->codegen_node->data.type_node.entry->type_ref; |
| 68 | return type_node->codegen_node->data.type_node.entry; |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | | static LLVMZigDIType *to_llvm_debug_type(AstNode *type_node) { |
| 72 | | assert(type_node->type == NodeTypeType); |
| 73 | | assert(type_node->codegen_node); |
| 74 | | assert(type_node->codegen_node->data.type_node.entry); |
| 71 | static LLVMTypeRef fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) { |
| 72 | TypeTableEntry *type_entry = get_type_for_type_node(g, type_node); |
| 75 | 73 | |
| 76 | | return type_node->codegen_node->data.type_node.entry->di_type; |
| 74 | if (type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdArray) { |
| 75 | return get_pointer_to_type(g, type_entry, true)->type_ref; |
| 76 | } else { |
| 77 | return type_entry->type_ref; |
| 78 | } |
| 77 | 79 | } |
| 78 | 80 | |
| 79 | | static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) { |
| 80 | | assert(type_node->type == NodeTypeType); |
| 81 | | assert(type_node->codegen_node); |
| 82 | | assert(type_node->codegen_node->data.type_node.entry); |
| 83 | | return type_node->codegen_node->data.type_node.entry; |
| 81 | static LLVMZigDIType *to_llvm_debug_type(CodeGen *g, AstNode *type_node) { |
| 82 | TypeTableEntry *type_entry = get_type_for_type_node(g, type_node); |
| 83 | return type_entry->di_type; |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | |
| 86 | 87 | static bool type_is_unreachable(CodeGen *g, AstNode *type_node) { |
| 87 | 88 | return get_type_for_type_node(g, type_node) == g->builtin_types.entry_unreachable; |
| 88 | 89 | } |
| ... | ... | @@ -198,20 +199,6 @@ static LLVMValueRef gen_array_ptr(CodeGen *g, AstNode *node) { |
| 198 | 199 | return LLVMBuildInBoundsGEP(g->builder, array_ref_value, indices, 2, ""); |
| 199 | 200 | } |
| 200 | 201 | |
| 201 | | static LLVMValueRef gen_field_val(CodeGen *g, AstNode *node) { |
| 202 | | assert(node->type == NodeTypeFieldAccessExpr); |
| 203 | | |
| 204 | | LLVMValueRef struct_val = gen_expr(g, node->data.field_access_expr.struct_expr); |
| 205 | | assert(struct_val); |
| 206 | | |
| 207 | | FieldAccessNode *codegen_field_access = &node->codegen_node->data.field_access_node; |
| 208 | | assert(codegen_field_access->field_index >= 0); |
| 209 | | |
| 210 | | add_debug_source_node(g, node); |
| 211 | | return LLVMBuildExtractValue(g->builder, struct_val, codegen_field_access->field_index, ""); |
| 212 | | } |
| 213 | | |
| 214 | | /* |
| 215 | 202 | static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node) { |
| 216 | 203 | assert(node->type == NodeTypeFieldAccessExpr); |
| 217 | 204 | |
| ... | ... | @@ -223,9 +210,9 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node) { |
| 223 | 210 | |
| 224 | 211 | assert(codegen_field_access->field_index >= 0); |
| 225 | 212 | |
| 213 | add_debug_source_node(g, node); |
| 226 | 214 | return LLVMBuildStructGEP(g->builder, struct_ptr, codegen_field_access->field_index, ""); |
| 227 | 215 | } |
| 228 | | */ |
| 229 | 216 | |
| 230 | 217 | static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node) { |
| 231 | 218 | assert(node->type == NodeTypeArrayAccessExpr); |
| ... | ... | @@ -249,11 +236,8 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node) { |
| 249 | 236 | zig_panic("gen_field_access_expr bad array field"); |
| 250 | 237 | } |
| 251 | 238 | } else if (struct_type->id == TypeTableEntryIdStruct) { |
| 252 | | /* |
| 253 | 239 | LLVMValueRef ptr = gen_field_ptr(g, node); |
| 254 | 240 | return LLVMBuildLoad(g->builder, ptr, ""); |
| 255 | | */ |
| 256 | | return gen_field_val(g, node); |
| 257 | 241 | } else { |
| 258 | 242 | zig_panic("gen_field_access_expr bad struct type"); |
| 259 | 243 | } |
| ... | ... | @@ -311,14 +295,19 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { |
| 311 | 295 | } |
| 312 | 296 | case CastOpArrayToString: |
| 313 | 297 | { |
| 314 | | LLVMValueRef struct_vals[] = { |
| 315 | | expr_val, |
| 316 | | LLVMConstInt(g->builtin_types.entry_usize->type_ref, actual_type->data.array.len, false) |
| 317 | | }; |
| 318 | | unsigned field_count = g->builtin_types.entry_string->data.structure.field_count; |
| 319 | | assert(field_count == 2); |
| 320 | | return LLVMConstNamedStruct(g->builtin_types.entry_string->type_ref, |
| 321 | | struct_vals, field_count); |
| 298 | assert(cast_node->ptr); |
| 299 | |
| 300 | add_debug_source_node(g, node); |
| 301 | |
| 302 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 0, ""); |
| 303 | LLVMBuildStore(g->builder, expr_val, ptr_ptr); |
| 304 | |
| 305 | LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, cast_node->ptr, 1, ""); |
| 306 | LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, |
| 307 | actual_type->data.array.len, false); |
| 308 | LLVMBuildStore(g->builder, len_val, len_ptr); |
| 309 | |
| 310 | return cast_node->ptr; |
| 322 | 311 | } |
| 323 | 312 | } |
| 324 | 313 | zig_unreachable(); |
| ... | ... | @@ -580,6 +569,8 @@ static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 580 | 569 | assert(array_type->id == TypeTableEntryIdArray); |
| 581 | 570 | op1_type = array_type->data.array.child_type; |
| 582 | 571 | target_ref = gen_array_ptr(g, lhs_node); |
| 572 | } else if (lhs_node->type == NodeTypeFieldAccessExpr) { |
| 573 | target_ref = gen_field_ptr(g, lhs_node); |
| 583 | 574 | } else { |
| 584 | 575 | zig_panic("bad assign target"); |
| 585 | 576 | } |
| ... | ... | @@ -717,6 +708,7 @@ static LLVMValueRef gen_if_expr(CodeGen *g, AstNode *node) { |
| 717 | 708 | static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| 718 | 709 | assert(block_node->type == NodeTypeBlock); |
| 719 | 710 | |
| 711 | BlockContext *old_block_context = g->cur_block_context; |
| 720 | 712 | g->cur_block_context = block_node->codegen_node->data.block_node.block_context; |
| 721 | 713 | |
| 722 | 714 | LLVMValueRef return_value; |
| ... | ... | @@ -726,6 +718,7 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i |
| 726 | 718 | } |
| 727 | 719 | |
| 728 | 720 | if (implicit_return_type) { |
| 721 | add_debug_source_node(g, block_node); |
| 729 | 722 | if (implicit_return_type == g->builtin_types.entry_void) { |
| 730 | 723 | LLVMBuildRetVoid(g->builder); |
| 731 | 724 | } else if (implicit_return_type != g->builtin_types.entry_unreachable) { |
| ... | ... | @@ -733,6 +726,8 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i |
| 733 | 726 | } |
| 734 | 727 | } |
| 735 | 728 | |
| 729 | g->cur_block_context = old_block_context; |
| 730 | |
| 736 | 731 | return return_value; |
| 737 | 732 | } |
| 738 | 733 | |
| ... | ... | @@ -934,6 +929,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 934 | 929 | } else if (variable->is_ptr) { |
| 935 | 930 | if (variable->type->id == TypeTableEntryIdArray) { |
| 936 | 931 | return variable->value_ref; |
| 932 | } else if (variable->type->id == TypeTableEntryIdStruct) { |
| 933 | return variable->value_ref; |
| 937 | 934 | } else { |
| 938 | 935 | add_debug_source_node(g, node); |
| 939 | 936 | return LLVMBuildLoad(g->builder, variable->value_ref, ""); |
| ... | ... | @@ -994,12 +991,12 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro |
| 994 | 991 | LLVMZigDIFile *di_file) |
| 995 | 992 | { |
| 996 | 993 | LLVMZigDIType **types = allocate<LLVMZigDIType*>(1 + fn_proto->params.length); |
| 997 | | types[0] = to_llvm_debug_type(fn_proto->return_type); |
| 994 | types[0] = to_llvm_debug_type(g, fn_proto->return_type); |
| 998 | 995 | int types_len = fn_proto->params.length + 1; |
| 999 | 996 | for (int i = 0; i < fn_proto->params.length; i += 1) { |
| 1000 | 997 | AstNode *param_node = fn_proto->params.at(i); |
| 1001 | 998 | assert(param_node->type == NodeTypeParamDecl); |
| 1002 | | LLVMZigDIType *param_type = to_llvm_debug_type(param_node->data.param_decl.type); |
| 999 | LLVMZigDIType *param_type = to_llvm_debug_type(g, param_node->data.param_decl.type); |
| 1003 | 1000 | types[i + 1] = param_type; |
| 1004 | 1001 | } |
| 1005 | 1002 | return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0); |
| ... | ... | @@ -1026,7 +1023,7 @@ static void do_code_gen(CodeGen *g) { |
| 1026 | 1023 | assert(proto_node->type == NodeTypeFnProto); |
| 1027 | 1024 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1028 | 1025 | |
| 1029 | | LLVMTypeRef ret_type = to_llvm_type(fn_proto->return_type); |
| 1026 | LLVMTypeRef ret_type = fn_proto_type_from_type_node(g, fn_proto->return_type); |
| 1030 | 1027 | int param_count = count_non_void_params(g, &fn_proto->params); |
| 1031 | 1028 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count); |
| 1032 | 1029 | int gen_param_index = 0; |
| ... | ... | @@ -1036,7 +1033,7 @@ static void do_code_gen(CodeGen *g) { |
| 1036 | 1033 | if (is_param_decl_type_void(g, param_node)) |
| 1037 | 1034 | continue; |
| 1038 | 1035 | AstNode *type_node = param_node->data.param_decl.type; |
| 1039 | | param_types[gen_param_index] = to_llvm_type(type_node); |
| 1036 | param_types[gen_param_index] = fn_proto_type_from_type_node(g, type_node); |
| 1040 | 1037 | gen_param_index += 1; |
| 1041 | 1038 | } |
| 1042 | 1039 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, param_count, fn_proto->is_var_args); |
| ... | ... | @@ -1061,8 +1058,8 @@ static void do_code_gen(CodeGen *g) { |
| 1061 | 1058 | } |
| 1062 | 1059 | |
| 1063 | 1060 | // Generate function definitions. |
| 1064 | | for (int i = 0; i < g->fn_defs.length; i += 1) { |
| 1065 | | FnTableEntry *fn_table_entry = g->fn_defs.at(i); |
| 1061 | for (int fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { |
| 1062 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); |
| 1066 | 1063 | ImportTableEntry *import = fn_table_entry->import_entry; |
| 1067 | 1064 | AstNode *fn_def_node = fn_table_entry->fn_def_node; |
| 1068 | 1065 | LLVMValueRef fn = fn_table_entry->fn_value; |
| ... | ... | @@ -1101,8 +1098,8 @@ static void do_code_gen(CodeGen *g) { |
| 1101 | 1098 | LLVMGetParams(fn, params); |
| 1102 | 1099 | |
| 1103 | 1100 | int non_void_index = 0; |
| 1104 | | for (int i = 0; i < fn_proto->params.length; i += 1) { |
| 1105 | | AstNode *param_decl = fn_proto->params.at(i); |
| 1101 | for (int param_i = 0; param_i < fn_proto->params.length; param_i += 1) { |
| 1102 | AstNode *param_decl = fn_proto->params.at(param_i); |
| 1106 | 1103 | assert(param_decl->type == NodeTypeParamDecl); |
| 1107 | 1104 | if (is_param_decl_type_void(g, param_decl)) |
| 1108 | 1105 | continue; |
| ... | ... | @@ -1115,8 +1112,8 @@ static void do_code_gen(CodeGen *g) { |
| 1115 | 1112 | |
| 1116 | 1113 | // Set up debug info for blocks and variables and |
| 1117 | 1114 | // allocate all local variables |
| 1118 | | for (int i = 0; i < codegen_fn_def->all_block_contexts.length; i += 1) { |
| 1119 | | BlockContext *block_context = codegen_fn_def->all_block_contexts.at(i); |
| 1115 | for (int bc_i = 0; bc_i < codegen_fn_def->all_block_contexts.length; bc_i += 1) { |
| 1116 | BlockContext *block_context = codegen_fn_def->all_block_contexts.at(bc_i); |
| 1120 | 1117 | |
| 1121 | 1118 | if (block_context->parent) { |
| 1122 | 1119 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, |
| ... | ... | @@ -1157,6 +1154,16 @@ static void do_code_gen(CodeGen *g) { |
| 1157 | 1154 | import->di_file, var->decl_node->line + 1, |
| 1158 | 1155 | var->type->di_type, !g->strip_debug_symbols, 0, arg_no); |
| 1159 | 1156 | } |
| 1157 | |
| 1158 | // allocate structs which are the result of casts |
| 1159 | for (int cea_i = 0; cea_i < block_context->cast_expr_alloca_list.length; cea_i += 1) { |
| 1160 | AstNode *cast_expr_node = block_context->cast_expr_alloca_list.at(cea_i); |
| 1161 | assert(cast_expr_node->type == NodeTypeCastExpr); |
| 1162 | CastNode *cast_codegen = &cast_expr_node->codegen_node->data.cast_node; |
| 1163 | TypeTableEntry *type_entry = get_type_for_type_node(g, cast_expr_node->data.cast_expr.type); |
| 1164 | add_debug_source_node(g, cast_expr_node); |
| 1165 | cast_codegen->ptr = LLVMBuildAlloca(g->builder, type_entry->type_ref, ""); |
| 1166 | } |
| 1160 | 1167 | } |
| 1161 | 1168 | |
| 1162 | 1169 | TypeTableEntry *implicit_return_type = codegen_fn_def->implicit_return_type; |