| ... | @@ -21,6 +21,9 @@ | ... | @@ -21,6 +21,9 @@ |
| 21 | struct FnTableEntry { | 21 | struct FnTableEntry { |
| 22 | LLVMValueRef fn_value; | 22 | LLVMValueRef fn_value; |
| 23 | AstNode *proto_node; | 23 | AstNode *proto_node; |
| | 24 | AstNode *fn_def_node; |
| | 25 | bool is_extern; |
| | 26 | bool internal_linkage; |
| 24 | }; | 27 | }; |
| 25 | | 28 | |
| 26 | enum TypeId { | 29 | enum TypeId { |
| ... | @@ -48,7 +51,6 @@ struct TypeTableEntry { | ... | @@ -48,7 +51,6 @@ struct TypeTableEntry { |
| 48 | struct CodeGen { | 51 | struct CodeGen { |
| 49 | LLVMModuleRef mod; | 52 | LLVMModuleRef mod; |
| 50 | AstNode *root; | 53 | AstNode *root; |
| 51 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> fn_defs; | | |
| 52 | ZigList<ErrorMsg> errors; | 54 | ZigList<ErrorMsg> errors; |
| 53 | LLVMBuilderRef builder; | 55 | LLVMBuilderRef builder; |
| 54 | llvm::DIBuilder *dbuilder; | 56 | llvm::DIBuilder *dbuilder; |
| ... | @@ -68,6 +70,7 @@ struct CodeGen { | ... | @@ -68,6 +70,7 @@ struct CodeGen { |
| 68 | Buf in_dir; | 70 | Buf in_dir; |
| 69 | ZigList<llvm::DIScope *> block_scopes; | 71 | ZigList<llvm::DIScope *> block_scopes; |
| 70 | llvm::DIFile *di_file; | 72 | llvm::DIFile *di_file; |
| | 73 | ZigList<FnTableEntry *> fn_defs; |
| 71 | }; | 74 | }; |
| 72 | | 75 | |
| 73 | struct TypeNode { | 76 | struct TypeNode { |
| ... | @@ -83,7 +86,6 @@ struct CodeGenNode { | ... | @@ -83,7 +86,6 @@ struct CodeGenNode { |
| 83 | CodeGen *create_codegen(AstNode *root, Buf *in_full_path) { | 86 | CodeGen *create_codegen(AstNode *root, Buf *in_full_path) { |
| 84 | CodeGen *g = allocate<CodeGen>(1); | 87 | CodeGen *g = allocate<CodeGen>(1); |
| 85 | g->root = root; | 88 | g->root = root; |
| 86 | g->fn_defs.init(32); | | |
| 87 | g->fn_table.init(32); | 89 | g->fn_table.init(32); |
| 88 | g->str_table.init(32); | 90 | g->str_table.init(32); |
| 89 | g->type_table.init(32); | 91 | g->type_table.init(32); |
| ... | @@ -137,11 +139,12 @@ static llvm::DIType *to_llvm_debug_type(AstNode *type_node) { | ... | @@ -137,11 +139,12 @@ static llvm::DIType *to_llvm_debug_type(AstNode *type_node) { |
| 137 | | 139 | |
| 138 | static bool type_is_unreachable(AstNode *type_node) { | 140 | static bool type_is_unreachable(AstNode *type_node) { |
| 139 | assert(type_node->type == NodeTypeType); | 141 | assert(type_node->type == NodeTypeType); |
| 140 | return type_node->data.type.type == AstNodeTypeTypePrimitive && | 142 | assert(type_node->codegen_node); |
| 141 | buf_eql_str(&type_node->data.type.primitive_name, "unreachable"); | 143 | assert(type_node->codegen_node->data.type_node.entry); |
| | 144 | return type_node->codegen_node->data.type_node.entry->id == TypeIdUnreachable; |
| 142 | } | 145 | } |
| 143 | | 146 | |
| 144 | static void analyze_node(CodeGen *g, AstNode *node); | 147 | static void find_declarations(CodeGen *g, AstNode *node); |
| 145 | | 148 | |
| 146 | static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { | 149 | static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { |
| 147 | assert(!node->codegen_node); | 150 | assert(!node->codegen_node); |
| ... | @@ -163,7 +166,7 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { | ... | @@ -163,7 +166,7 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { |
| 163 | } | 166 | } |
| 164 | case AstNodeTypeTypePointer: | 167 | case AstNodeTypeTypePointer: |
| 165 | { | 168 | { |
| 166 | analyze_node(g, node->data.type.child_type); | 169 | find_declarations(g, node->data.type.child_type); |
| 167 | TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node; | 170 | TypeNode *child_type_node = &node->data.type.child_type->codegen_node->data.type_node; |
| 168 | if (child_type_node->entry->id == TypeIdUnreachable) { | 171 | if (child_type_node->entry->id == TypeIdUnreachable) { |
| 169 | add_node_error(g, node, | 172 | add_node_error(g, node, |
| ... | @@ -192,14 +195,8 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { | ... | @@ -192,14 +195,8 @@ static void resolve_type_and_recurse(CodeGen *g, AstNode *node) { |
| 192 | } | 195 | } |
| 193 | } | 196 | } |
| 194 | | 197 | |
| 195 | static void analyze_node(CodeGen *g, AstNode *node) { | 198 | static void find_declarations(CodeGen *g, AstNode *node) { |
| 196 | switch (node->type) { | 199 | switch (node->type) { |
| 197 | case NodeTypeRoot: | | |
| 198 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { | | |
| 199 | AstNode *child = node->data.root.top_level_decls.at(i); | | |
| 200 | analyze_node(g, child); | | |
| 201 | } | | |
| 202 | break; | | |
| 203 | case NodeTypeExternBlock: | 200 | case NodeTypeExternBlock: |
| 204 | for (int i = 0; i < node->data.extern_block.directives->length; i += 1) { | 201 | for (int i = 0; i < node->data.extern_block.directives->length; i += 1) { |
| 205 | AstNode *directive_node = node->data.extern_block.directives->at(i); | 202 | AstNode *directive_node = node->data.extern_block.directives->at(i); |
| ... | @@ -215,34 +212,14 @@ static void analyze_node(CodeGen *g, AstNode *node) { | ... | @@ -215,34 +212,14 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 215 | | 212 | |
| 216 | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { | 213 | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { |
| 217 | AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); | 214 | AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); |
| 218 | analyze_node(g, fn_decl); | 215 | assert(fn_decl->type == NodeTypeFnDecl); |
| 219 | | | |
| 220 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; | 216 | AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto; |
| | 217 | find_declarations(g, fn_proto); |
| 221 | Buf *name = &fn_proto->data.fn_proto.name; | 218 | Buf *name = &fn_proto->data.fn_proto.name; |
| 222 | ZigList<AstNode *> *params = &fn_proto->data.fn_proto.params; | | |
| 223 | | | |
| 224 | LLVMTypeRef *fn_param_values = allocate<LLVMTypeRef>(params->length); | | |
| 225 | for (int param_i = 0; param_i < params->length; param_i += 1) { | | |
| 226 | AstNode *param_node = params->at(param_i); | | |
| 227 | assert(param_node->type == NodeTypeParamDecl); | | |
| 228 | AstNode *param_type = param_node->data.param_decl.type; | | |
| 229 | fn_param_values[param_i] = to_llvm_type(param_type); | | |
| 230 | } | | |
| 231 | AstNode *return_type_node = fn_proto->data.fn_proto.return_type; | | |
| 232 | LLVMTypeRef return_type = to_llvm_type(return_type_node); | | |
| 233 | | | |
| 234 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, fn_param_values, params->length, 0); | | |
| 235 | LLVMValueRef fn_val = LLVMAddFunction(g->mod, buf_ptr(name), fn_type); | | |
| 236 | LLVMSetLinkage(fn_val, LLVMExternalLinkage); | | |
| 237 | LLVMSetFunctionCallConv(fn_val, LLVMCCallConv); | | |
| 238 | | | |
| 239 | if (type_is_unreachable(return_type_node)) { | | |
| 240 | LLVMAddFunctionAttr(fn_val, LLVMNoReturnAttribute); | | |
| 241 | } | | |
| 242 | | 219 | |
| 243 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); | 220 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 244 | fn_table_entry->fn_value = fn_val; | | |
| 245 | fn_table_entry->proto_node = fn_proto; | 221 | fn_table_entry->proto_node = fn_proto; |
| | 222 | fn_table_entry->is_extern = true; |
| 246 | g->fn_table.put(name, fn_table_entry); | 223 | g->fn_table.put(name, fn_table_entry); |
| 247 | } | 224 | } |
| 248 | break; | 225 | break; |
| ... | @@ -251,14 +228,74 @@ static void analyze_node(CodeGen *g, AstNode *node) { | ... | @@ -251,14 +228,74 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 251 | AstNode *proto_node = node->data.fn_def.fn_proto; | 228 | AstNode *proto_node = node->data.fn_def.fn_proto; |
| 252 | assert(proto_node->type == NodeTypeFnProto); | 229 | assert(proto_node->type == NodeTypeFnProto); |
| 253 | Buf *proto_name = &proto_node->data.fn_proto.name; | 230 | Buf *proto_name = &proto_node->data.fn_proto.name; |
| 254 | auto entry = g->fn_defs.maybe_get(proto_name); | 231 | auto entry = g->fn_table.maybe_get(proto_name); |
| 255 | if (entry) { | 232 | if (entry) { |
| 256 | add_node_error(g, node, | 233 | add_node_error(g, node, |
| 257 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); | 234 | buf_sprintf("redefinition of '%s'", buf_ptr(proto_name))); |
| 258 | } else { | 235 | } else { |
| 259 | g->fn_defs.put(proto_name, node); | 236 | FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1); |
| 260 | analyze_node(g, proto_node); | 237 | fn_table_entry->proto_node = proto_node; |
| | 238 | fn_table_entry->fn_def_node = node; |
| | 239 | g->fn_table.put(proto_name, fn_table_entry); |
| | 240 | g->fn_defs.append(fn_table_entry); |
| | 241 | |
| | 242 | find_declarations(g, proto_node); |
| | 243 | } |
| | 244 | break; |
| | 245 | } |
| | 246 | case NodeTypeFnProto: |
| | 247 | { |
| | 248 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| | 249 | AstNode *child = node->data.fn_proto.params.at(i); |
| | 250 | find_declarations(g, child); |
| 261 | } | 251 | } |
| | 252 | find_declarations(g, node->data.fn_proto.return_type); |
| | 253 | break; |
| | 254 | } |
| | 255 | break; |
| | 256 | case NodeTypeParamDecl: |
| | 257 | find_declarations(g, node->data.param_decl.type); |
| | 258 | break; |
| | 259 | case NodeTypeType: |
| | 260 | resolve_type_and_recurse(g, node); |
| | 261 | break; |
| | 262 | case NodeTypeDirective: |
| | 263 | // we handled directives in the parent function |
| | 264 | break; |
| | 265 | case NodeTypeFnDecl: |
| | 266 | case NodeTypeStatementReturn: |
| | 267 | case NodeTypeRoot: |
| | 268 | case NodeTypeBlock: |
| | 269 | case NodeTypeExpression: |
| | 270 | case NodeTypeFnCall: |
| | 271 | zig_unreachable(); |
| | 272 | } |
| | 273 | } |
| | 274 | |
| | 275 | static void analyze_node(CodeGen *g, AstNode *node) { |
| | 276 | switch (node->type) { |
| | 277 | case NodeTypeRoot: |
| | 278 | // Iterate once over the top level declarations to build the function table |
| | 279 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { |
| | 280 | AstNode *child = node->data.root.top_level_decls.at(i); |
| | 281 | find_declarations(g, child); |
| | 282 | } |
| | 283 | for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) { |
| | 284 | AstNode *child = node->data.root.top_level_decls.at(i); |
| | 285 | analyze_node(g, child); |
| | 286 | } |
| | 287 | break; |
| | 288 | case NodeTypeExternBlock: |
| | 289 | for (int fn_decl_i = 0; fn_decl_i < node->data.extern_block.fn_decls.length; fn_decl_i += 1) { |
| | 290 | AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i); |
| | 291 | analyze_node(g, fn_decl); |
| | 292 | } |
| | 293 | break; |
| | 294 | case NodeTypeFnDef: |
| | 295 | { |
| | 296 | AstNode *proto_node = node->data.fn_def.fn_proto; |
| | 297 | assert(proto_node->type == NodeTypeFnProto); |
| | 298 | analyze_node(g, proto_node); |
| 262 | break; | 299 | break; |
| 263 | } | 300 | } |
| 264 | case NodeTypeFnDecl: | 301 | case NodeTypeFnDecl: |
| ... | @@ -282,10 +319,8 @@ static void analyze_node(CodeGen *g, AstNode *node) { | ... | @@ -282,10 +319,8 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 282 | break; | 319 | break; |
| 283 | | 320 | |
| 284 | case NodeTypeType: | 321 | case NodeTypeType: |
| 285 | { | 322 | // ignore; we handled types with find_declarations |
| 286 | resolve_type_and_recurse(g, node); | 323 | break; |
| 287 | break; | | |
| 288 | } | | |
| 289 | case NodeTypeBlock: | 324 | case NodeTypeBlock: |
| 290 | for (int i = 0; i < node->data.block.statements.length; i += 1) { | 325 | for (int i = 0; i < node->data.block.statements.length; i += 1) { |
| 291 | AstNode *child = node->data.block.statements.at(i); | 326 | AstNode *child = node->data.block.statements.at(i); |
| ... | @@ -309,12 +344,33 @@ static void analyze_node(CodeGen *g, AstNode *node) { | ... | @@ -309,12 +344,33 @@ static void analyze_node(CodeGen *g, AstNode *node) { |
| 309 | } | 344 | } |
| 310 | break; | 345 | break; |
| 311 | case NodeTypeFnCall: | 346 | case NodeTypeFnCall: |
| 312 | for (int i = 0; i < node->data.fn_call.params.length; i += 1) { | 347 | { |
| 313 | AstNode *child = node->data.fn_call.params.at(i); | 348 | Buf *name = &node->data.fn_call.name; |
| 314 | analyze_node(g, child); | 349 | |
| | 350 | auto entry = g->fn_table.maybe_get(name); |
| | 351 | if (!entry) { |
| | 352 | add_node_error(g, node, |
| | 353 | buf_sprintf("undefined function: '%s'", buf_ptr(name))); |
| | 354 | } else { |
| | 355 | FnTableEntry *fn_table_entry = entry->value; |
| | 356 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); |
| | 357 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; |
| | 358 | int actual_param_count = node->data.fn_call.params.length; |
| | 359 | if (expected_param_count != actual_param_count) { |
| | 360 | add_node_error(g, node, |
| | 361 | buf_sprintf("wrong number of arguments. Expected %d, got %d.", |
| | 362 | expected_param_count, actual_param_count)); |
| | 363 | } |
| | 364 | } |
| | 365 | |
| | 366 | for (int i = 0; i < node->data.fn_call.params.length; i += 1) { |
| | 367 | AstNode *child = node->data.fn_call.params.at(i); |
| | 368 | analyze_node(g, child); |
| | 369 | } |
| | 370 | break; |
| 315 | } | 371 | } |
| 316 | break; | | |
| 317 | case NodeTypeDirective: | 372 | case NodeTypeDirective: |
| | 373 | // we looked at directives in the parent node |
| 318 | break; | 374 | break; |
| 319 | } | 375 | } |
| 320 | } | 376 | } |
| ... | @@ -399,7 +455,6 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -399,7 +455,6 @@ void semantic_analyze(CodeGen *g) { |
| 399 | | 455 | |
| 400 | add_types(g); | 456 | add_types(g); |
| 401 | | 457 | |
| 402 | // Pass 1. | | |
| 403 | analyze_node(g, g->root); | 458 | analyze_node(g, g->root); |
| 404 | } | 459 | } |
| 405 | | 460 | |
| ... | @@ -415,23 +470,11 @@ static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { | ... | @@ -415,23 +470,11 @@ static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { |
| 415 | assert(fn_call_node->type == NodeTypeFnCall); | 470 | assert(fn_call_node->type == NodeTypeFnCall); |
| 416 | | 471 | |
| 417 | Buf *name = &fn_call_node->data.fn_call.name; | 472 | Buf *name = &fn_call_node->data.fn_call.name; |
| 418 | | 473 | FnTableEntry *fn_table_entry = g->fn_table.get(name); |
| 419 | auto entry = g->fn_table.maybe_get(name); | | |
| 420 | if (!entry) { | | |
| 421 | add_node_error(g, fn_call_node, | | |
| 422 | buf_sprintf("undefined function: '%s'", buf_ptr(name))); | | |
| 423 | return LLVMConstNull(LLVMInt32Type()); | | |
| 424 | } | | |
| 425 | FnTableEntry *fn_table_entry = entry->value; | | |
| 426 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); | 474 | assert(fn_table_entry->proto_node->type == NodeTypeFnProto); |
| 427 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; | 475 | int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length; |
| 428 | int actual_param_count = fn_call_node->data.fn_call.params.length; | 476 | int actual_param_count = fn_call_node->data.fn_call.params.length; |
| 429 | if (expected_param_count != actual_param_count) { | 477 | assert(expected_param_count == actual_param_count); |
| 430 | add_node_error(g, fn_call_node, | | |
| 431 | buf_sprintf("wrong number of arguments. Expected %d, got %d.", | | |
| 432 | expected_param_count, actual_param_count)); | | |
| 433 | return LLVMConstNull(LLVMInt32Type()); | | |
| 434 | } | | |
| 435 | | 478 | |
| 436 | LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); | 479 | LLVMValueRef *param_values = allocate<LLVMValueRef>(actual_param_count); |
| 437 | for (int i = 0; i < actual_param_count; i += 1) { | 480 | for (int i = 0; i < actual_param_count; i += 1) { |
| ... | @@ -557,6 +600,8 @@ static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProt | ... | @@ -557,6 +600,8 @@ static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProt |
| 557 | } | 600 | } |
| 558 | | 601 | |
| 559 | void code_gen(CodeGen *g) { | 602 | void code_gen(CodeGen *g) { |
| | 603 | assert(!g->errors.length); |
| | 604 | |
| 560 | Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING); | 605 | Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING); |
| 561 | bool is_optimized = g->build_type == CodeGenBuildTypeRelease; | 606 | bool is_optimized = g->build_type == CodeGenBuildTypeRelease; |
| 562 | const char *flags = ""; | 607 | const char *flags = ""; |
| ... | @@ -570,16 +615,19 @@ void code_gen(CodeGen *g) { | ... | @@ -570,16 +615,19 @@ void code_gen(CodeGen *g) { |
| 570 | | 615 | |
| 571 | g->di_file = g->dbuilder->createFile(g->compile_unit->getFilename(), g->compile_unit->getDirectory()); | 616 | g->di_file = g->dbuilder->createFile(g->compile_unit->getFilename(), g->compile_unit->getDirectory()); |
| 572 | | 617 | |
| 573 | auto it = g->fn_defs.entry_iterator(); | 618 | |
| | 619 | // Generate function prototypes |
| | 620 | auto it = g->fn_table.entry_iterator(); |
| 574 | for (;;) { | 621 | for (;;) { |
| 575 | auto *entry = it.next(); | 622 | auto *entry = it.next(); |
| 576 | if (!entry) | 623 | if (!entry) |
| 577 | break; | 624 | break; |
| 578 | | 625 | |
| 579 | AstNode *fn_def_node = entry->value; | 626 | FnTableEntry *fn_table_entry = entry->value; |
| 580 | AstNodeFnDef *fn_def = &fn_def_node->data.fn_def; | 627 | |
| 581 | assert(fn_def->fn_proto->type == NodeTypeFnProto); | 628 | AstNode *proto_node = fn_table_entry->proto_node; |
| 582 | AstNodeFnProto *fn_proto = &fn_def->fn_proto->data.fn_proto; | 629 | assert(proto_node->type == NodeTypeFnProto); |
| | 630 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 583 | | 631 | |
| 584 | LLVMTypeRef ret_type = to_llvm_type(fn_proto->return_type); | 632 | LLVMTypeRef ret_type = to_llvm_type(fn_proto->return_type); |
| 585 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(fn_proto->params.length); | 633 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(fn_proto->params.length); |
| ... | @@ -592,13 +640,29 @@ void code_gen(CodeGen *g) { | ... | @@ -592,13 +640,29 @@ void code_gen(CodeGen *g) { |
| 592 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, fn_proto->params.length, 0); | 640 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, fn_proto->params.length, 0); |
| 593 | LLVMValueRef fn = LLVMAddFunction(g->mod, buf_ptr(&fn_proto->name), function_type); | 641 | LLVMValueRef fn = LLVMAddFunction(g->mod, buf_ptr(&fn_proto->name), function_type); |
| 594 | | 642 | |
| 595 | bool internal_linkage = false; | 643 | LLVMSetLinkage(fn, fn_table_entry->internal_linkage ? LLVMPrivateLinkage : LLVMExternalLinkage); |
| 596 | LLVMSetLinkage(fn, internal_linkage ? LLVMPrivateLinkage : LLVMExternalLinkage); | | |
| 597 | | 644 | |
| 598 | if (type_is_unreachable(fn_proto->return_type)) { | 645 | if (type_is_unreachable(fn_proto->return_type)) { |
| 599 | LLVMAddFunctionAttr(fn, LLVMNoReturnAttribute); | 646 | LLVMAddFunctionAttr(fn, LLVMNoReturnAttribute); |
| 600 | } | 647 | } |
| 601 | LLVMAddFunctionAttr(fn, LLVMNoUnwindAttribute); | 648 | if (fn_table_entry->is_extern) { |
| | 649 | LLVMSetFunctionCallConv(fn, LLVMCCallConv); |
| | 650 | } else { |
| | 651 | LLVMAddFunctionAttr(fn, LLVMNoUnwindAttribute); |
| | 652 | } |
| | 653 | |
| | 654 | fn_table_entry->fn_value = fn; |
| | 655 | } |
| | 656 | |
| | 657 | // Generate function definitions. |
| | 658 | for (int i = 0; i < g->fn_defs.length; i += 1) { |
| | 659 | FnTableEntry *fn_table_entry = g->fn_defs.at(i); |
| | 660 | AstNode *fn_def_node = fn_table_entry->fn_def_node; |
| | 661 | LLVMValueRef fn = fn_table_entry->fn_value; |
| | 662 | |
| | 663 | AstNode *proto_node = fn_table_entry->proto_node; |
| | 664 | assert(proto_node->type == NodeTypeFnProto); |
| | 665 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 602 | | 666 | |
| 603 | // Add debug info. | 667 | // Add debug info. |
| 604 | llvm::DIScope *fn_scope = g->di_file; | 668 | llvm::DIScope *fn_scope = g->di_file; |
| ... | @@ -609,17 +673,19 @@ void code_gen(CodeGen *g) { | ... | @@ -609,17 +673,19 @@ void code_gen(CodeGen *g) { |
| 609 | llvm::Function *unwrapped_function = reinterpret_cast<llvm::Function*>(llvm::unwrap(fn)); | 673 | llvm::Function *unwrapped_function = reinterpret_cast<llvm::Function*>(llvm::unwrap(fn)); |
| 610 | llvm::DISubprogram *subprogram = g->dbuilder->createFunction( | 674 | llvm::DISubprogram *subprogram = g->dbuilder->createFunction( |
| 611 | fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number, | 675 | fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number, |
| 612 | create_di_function_type(g, fn_proto, g->di_file), internal_linkage, | 676 | create_di_function_type(g, fn_proto, g->di_file), fn_table_entry->internal_linkage, |
| 613 | is_definition, scope_line, flags, is_optimized, unwrapped_function); | 677 | is_definition, scope_line, flags, is_optimized, unwrapped_function); |
| 614 | | 678 | |
| 615 | g->block_scopes.append(subprogram); | 679 | g->block_scopes.append(subprogram); |
| 616 | | 680 | |
| 617 | | | |
| 618 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); | 681 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); |
| 619 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | 682 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 620 | | 683 | |
| 621 | gen_block(g, fn_def->body); | 684 | gen_block(g, fn_def_node->data.fn_def.body); |
| | 685 | |
| | 686 | g->block_scopes.pop(); |
| 622 | } | 687 | } |
| | 688 | assert(!g->errors.length); |
| 623 | | 689 | |
| 624 | g->dbuilder->finalize(); | 690 | g->dbuilder->finalize(); |
| 625 | | 691 | |