authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-30 19:58:53-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-30 20:00:39-07:00
log55b8472374eede496b59396dbe253b05b16063e1
treec2d9be8780e272d4fc6fc1a59b20e9a8c1dab755
parentef482ece7c047e898fdc2ea15ba4216c15309d0c

refactor code to prepare for multiple files

verbose compiler output is now behind --verbose flag

26 files changed, 490 insertions(+), 303 deletions(-)

CMakeLists.txt+4-4
......@@ -22,16 +22,16 @@ include_directories(
2222)
2323
2424set(ZIG_SOURCES
25 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
26 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
2527 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
28 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
2629 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
2730 "${CMAKE_SOURCE_DIR}/src/error.cpp"
2831 "${CMAKE_SOURCE_DIR}/src/main.cpp"
29 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
30 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
32 "${CMAKE_SOURCE_DIR}/src/os.cpp"
3133 "${CMAKE_SOURCE_DIR}/src/util.cpp"
32 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
3334 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
34 "${CMAKE_SOURCE_DIR}/src/os.cpp"
3535)
3636
3737set(TEST_SOURCES
README.md+3-1
......@@ -79,7 +79,9 @@ zig | C equivalent | Description
7979```
8080Root : many(TopLevelDecl) token(EOF)
8181
82TopLevelDecl : FnDef | ExternBlock | RootExportDecl
82TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use
83
84Use : many(Directive) token(Use) token(String) token(Semicolon)
8385
8486RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon)
8587
doc/vim/syntax/zig.vim+15-2
......@@ -7,7 +7,7 @@ if exists("b:current_syntax")
77 finish
88endif
99
10syn keyword zigKeyword fn return mut const extern unreachable export pub as
10syn keyword zigKeyword fn return mut const extern unreachable export pub as use
1111syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void
1212
1313syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell
......@@ -19,6 +19,15 @@ syn region zigCommentBlockDocNest matchgroup=zigCommentBlockDoc start="/\*" end=
1919
2020syn keyword zigTodo contained TODO XXX
2121
22syn match zigEscapeError display contained /\\./
23syn match zigEscape display contained /\\\([nrt0\\'"]\|x\x\{2}\)/
24syn match zigEscapeUnicode display contained /\\\(u\x\{4}\|U\x\{8}\)/
25syn match zigEscapeUnicode display contained /\\u{\x\{1,6}}/
26syn match zigStringContinuation display contained /\\\n\s*/
27syn region zigString start=+b"+ skip=+\\\\\|\\"+ end=+"+ contains=zigEscape,zigEscapeError,zigStringContinuation
28syn region zigString start=+"+ skip=+\\\\\|\\"+ end=+"+ contains=zigEscape,zigEscapeUnicode,zigEscapeError,zigStringContinuation,@Spell
29syn region zigString start='b\?r\z(#*\)"' end='"\z1' contains=@Spell
30
2231let b:current_syntax = "zig"
2332
2433hi def link zigKeyword Keyword
......@@ -28,4 +37,8 @@ hi def link zigCommentLineDoc SpecialComment
2837hi def link zigCommentBlock zigCommentLine
2938hi def link zigCommentBlockDoc zigCommentLineDoc
3039hi def link zigTodo Todo
31
40hi def link zigStringContinuation Special
41hi def link zigString String
42hi def link zigEscape Special
43hi def link zigEscapeUnicode zigEscape
44hi def link zigEscapeError Error
example/hello.zig deleted-12
......@@ -1,12 +0,0 @@
1export executable "hello";
2
3#link("c")
4extern {
5 fn puts(s: *mut u8) -> i32;
6 fn exit(code: i32) -> unreachable;
7}
8
9export fn _start() -> unreachable {
10 puts("Hello, world!");
11 exit(0);
12}
example/hello_world/hello.zig created+12
......@@ -0,0 +1,12 @@
1export executable "hello";
2
3#link("c")
4extern {
5 fn puts(s: *mut u8) -> i32;
6 fn exit(code: i32) -> unreachable;
7}
8
9export fn _start() -> unreachable {
10 puts("Hello, world!");
11 exit(0);
12}
example/mathtest.zig deleted-6
......@@ -1,6 +0,0 @@
1#version("2.0.0")
2export library "mathtest";
3
4export fn add(a: i32, b: i32) -> i32 {
5 return a + b;
6}
example/multiple_files/foo.zig created+5
......@@ -0,0 +1,5 @@
1use "libc.zig";
2
3fn print_text() {
4 puts("it works!");
5}
example/multiple_files/libc.zig created+5
......@@ -0,0 +1,5 @@
1#link("c")
2extern {
3 fn puts(s: *mut u8) -> i32;
4 fn exit(code: i32) -> unreachable;
5}
example/multiple_files/main.zig created+9
......@@ -0,0 +1,9 @@
1export executable "test";
2
3use "libc.zig";
4use "foo.zig";
5
6fn _start() -> unreachable {
7 print_text();
8 exit(0);
9}
example/shared_library/mathtest.zig created+6
......@@ -0,0 +1,6 @@
1#version("2.0.0")
2export library "mathtest";
3
4export fn add(a: i32, b: i32) -> i32 {
5 return a + b;
6}
example/shared_library/test.c created+7
......@@ -0,0 +1,7 @@
1#include "mathtest.h"
2#include <stdio.h>
3
4int main(int argc, char **argv) {
5 printf("%d\n", add(42, 1137));
6 return 0;
7}
src/analyze.cpp+15-90
......@@ -113,7 +113,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {
113113 resolve_type(g, node->data.fn_proto.return_type);
114114}
115115
116static void preview_function_declarations(CodeGen *g, AstNode *node) {
116static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *node) {
117117 switch (node->type) {
118118 case NodeTypeExternBlock:
119119 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {
......@@ -139,6 +139,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
139139 fn_table_entry->proto_node = fn_proto;
140140 fn_table_entry->is_extern = true;
141141 fn_table_entry->calling_convention = LLVMCCallConv;
142 fn_table_entry->import_entry = import;
142143 g->fn_table.put(name, fn_table_entry);
143144 }
144145 break;
......@@ -156,6 +157,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
156157 node->codegen_node->data.fn_def_node.skip = true;
157158 } else {
158159 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
160 fn_table_entry->import_entry = import;
159161 fn_table_entry->proto_node = proto_node;
160162 fn_table_entry->fn_def_node = node;
161163 fn_table_entry->internal_linkage = proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport;
......@@ -190,8 +192,8 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
190192 } else {
191193 g->root_export_decl = node;
192194
193 if (!g->out_name)
194 g->out_name = &node->data.root_export_decl.name;
195 if (!g->root_out_name)
196 g->root_out_name = &node->data.root_export_decl.name;
195197
196198 Buf *out_type = &node->data.root_export_decl.type;
197199 OutType export_out_type;
......@@ -209,6 +211,9 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
209211 g->out_type = export_out_type;
210212 }
211213 break;
214 case NodeTypeUse:
215 zig_panic("TODO use");
216 break;
212217 case NodeTypeDirective:
213218 case NodeTypeParamDecl:
214219 case NodeTypeFnProto:
......@@ -346,6 +351,7 @@ static void analyze_expression(CodeGen *g, AstNode *node) {
346351 case NodeTypeRootExportDecl:
347352 case NodeTypeExternBlock:
348353 case NodeTypeFnDef:
354 case NodeTypeUse:
349355 zig_unreachable();
350356 }
351357}
......@@ -377,9 +383,9 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
377383
378384 case NodeTypeRootExportDecl:
379385 case NodeTypeExternBlock:
386 case NodeTypeUse:
380387 // already looked at these in the preview pass
381388 break;
382
383389 case NodeTypeDirective:
384390 case NodeTypeParamDecl:
385391 case NodeTypeFnProto:
......@@ -400,13 +406,13 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
400406 }
401407}
402408
403static void analyze_root(CodeGen *g, AstNode *node) {
409static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
404410 assert(node->type == NodeTypeRoot);
405411
406412 // find function declarations
407413 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
408414 AstNode *child = node->data.root.top_level_decls.at(i);
409 preview_function_declarations(g, child);
415 preview_function_declarations(g, import, child);
410416 }
411417
412418 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
......@@ -414,7 +420,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {
414420 analyze_top_level_declaration(g, child);
415421 }
416422
417 if (!g->out_name) {
423 if (!g->root_out_name) {
418424 add_node_error(g, node,
419425 buf_sprintf("missing export declaration and output name not provided"));
420426 } else if (g->out_type == OutTypeUnknown) {
......@@ -423,88 +429,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {
423429 }
424430}
425431
426static void define_primitive_types(CodeGen *g) {
427 {
428 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
429 entry->type_ref = LLVMInt8Type();
430 buf_init_from_str(&entry->name, "u8");
431 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
432 LLVMZigEncoding_DW_ATE_unsigned());
433 g->type_table.put(&entry->name, entry);
434 g->builtin_types.entry_u8 = entry;
435 }
436 {
437 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
438 entry->type_ref = LLVMInt32Type();
439 buf_init_from_str(&entry->name, "i32");
440 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
441 LLVMZigEncoding_DW_ATE_signed());
442 g->type_table.put(&entry->name, entry);
443 g->builtin_types.entry_i32 = entry;
444 }
445 {
446 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
447 entry->type_ref = LLVMVoidType();
448 buf_init_from_str(&entry->name, "void");
449 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
450 LLVMZigEncoding_DW_ATE_unsigned());
451 g->type_table.put(&entry->name, entry);
452 g->builtin_types.entry_void = entry;
453
454 // invalid types are void
455 g->builtin_types.entry_invalid = entry;
456 }
457 {
458 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
459 entry->type_ref = LLVMVoidType();
460 buf_init_from_str(&entry->name, "unreachable");
461 entry->di_type = g->builtin_types.entry_invalid->di_type;
462 g->type_table.put(&entry->name, entry);
463 g->builtin_types.entry_unreachable = entry;
464 }
465}
466
467
468void semantic_analyze(CodeGen *g) {
469 LLVMInitializeAllTargets();
470 LLVMInitializeAllTargetMCs();
471 LLVMInitializeAllAsmPrinters();
472 LLVMInitializeAllAsmParsers();
473 LLVMInitializeNativeTarget();
474
475 g->is_native_target = true;
476 char *native_triple = LLVMGetDefaultTargetTriple();
477
478 LLVMTargetRef target_ref;
479 char *err_msg = nullptr;
480 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
481 zig_panic("unable to get target from triple: %s", err_msg);
482 }
483
484 char *native_cpu = LLVMZigGetHostCPUName();
485 char *native_features = LLVMZigGetNativeFeatures();
486
487 LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
488 LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
489
490 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
491
492 g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
493 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
494
495 g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
496
497
498 g->module = LLVMModuleCreateWithName("ZigModule");
499
500 g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
501
502 g->builder = LLVMCreateBuilder();
503 g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
504
505
506 define_primitive_types(g);
507
508 analyze_root(g, g->root);
432void semantic_analyze(CodeGen *g, ImportTableEntry *import_table_entry) {
433 analyze_root(g, import_table_entry, import_table_entry->root);
509434}
510435
src/analyze.hpp+2-1
......@@ -9,7 +9,8 @@
99#define ZIG_ANALYZE_HPP
1010
1111struct CodeGen;
12struct ImportTableEntry;
1213
13void semantic_analyze(CodeGen *g);
14void semantic_analyze(CodeGen *g, ImportTableEntry *entry);
1415
1516#endif
src/codegen.cpp+213-42
......@@ -11,26 +11,21 @@
1111#include "os.hpp"
1212#include "config.h"
1313#include "error.hpp"
14
1514#include "semantic_info.hpp"
15#include "analyze.hpp"
1616
1717#include <stdio.h>
1818#include <errno.h>
1919
20CodeGen *create_codegen(AstNode *root, Buf *in_full_path) {
20CodeGen *codegen_create(Buf *root_source_dir) {
2121 CodeGen *g = allocate<CodeGen>(1);
22 g->root = root;
2322 g->fn_table.init(32);
2423 g->str_table.init(32);
2524 g->type_table.init(32);
2625 g->link_table.init(32);
27 g->is_static = false;
26 g->import_table.init(32);
2827 g->build_type = CodeGenBuildTypeDebug;
29 g->strip_debug_symbols = false;
30 g->out_name = nullptr;
31 g->out_type = OutTypeUnknown;
32
33 os_path_split(in_full_path, &g->in_dir, &g->in_file);
28 g->root_source_dir = root_source_dir;
3429 return g;
3530}
3631
......@@ -42,6 +37,10 @@ void codegen_set_is_static(CodeGen *g, bool is_static) {
4237 g->is_static = is_static;
4338}
4439
40void codegen_set_verbose(CodeGen *g, bool verbose) {
41 g->verbose = verbose;
42}
43
4544void codegen_set_strip(CodeGen *g, bool strip) {
4645 g->strip_debug_symbols = strip;
4746}
......@@ -51,7 +50,7 @@ void codegen_set_out_type(CodeGen *g, OutType out_type) {
5150}
5251
5352void codegen_set_out_name(CodeGen *g, Buf *out_name) {
54 g->out_name = out_name;
53 g->root_out_name = out_name;
5554}
5655
5756static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
......@@ -425,16 +424,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
425424 case NodeTypeBlock:
426425 case NodeTypeExternBlock:
427426 case NodeTypeDirective:
427 case NodeTypeUse:
428428 zig_unreachable();
429429 }
430430 zig_unreachable();
431431}
432432
433static void gen_block(CodeGen *g, AstNode *block_node, bool add_implicit_return) {
433static void gen_block(CodeGen *g, ImportTableEntry *import, AstNode *block_node, bool add_implicit_return) {
434434 assert(block_node->type == NodeTypeBlock);
435435
436436 LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, g->block_scopes.last(),
437 g->di_file, block_node->line + 1, block_node->column + 1);
437 import->di_file, block_node->line + 1, block_node->column + 1);
438438 g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block));
439439
440440 add_debug_source_node(g, block_node);
......@@ -466,22 +466,11 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro
466466 return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0);
467467}
468468
469void code_gen(CodeGen *g) {
469static void do_code_gen(CodeGen *g) {
470470 assert(!g->errors.length);
471471
472 Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
473 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
474 const char *flags = "";
475 unsigned runtime_version = 0;
476 g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
477 buf_ptr(&g->in_file), buf_ptr(&g->in_dir),
478 buf_ptr(producer), is_optimized, flags, runtime_version,
479 "", 0, !g->strip_debug_symbols);
480
481472 g->block_scopes.append(LLVMZigCompileUnitToScope(g->compile_unit));
482473
483 g->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&g->in_file), buf_ptr(&g->in_dir));
484
485474
486475 // Generate function prototypes
487476 auto it = g->fn_table.entry_iterator();
......@@ -523,6 +512,7 @@ void code_gen(CodeGen *g) {
523512 // Generate function definitions.
524513 for (int i = 0; i < g->fn_defs.length; i += 1) {
525514 FnTableEntry *fn_table_entry = g->fn_defs.at(i);
515 ImportTableEntry *import = fn_table_entry->import_entry;
526516 AstNode *fn_def_node = fn_table_entry->fn_def_node;
527517 LLVMValueRef fn = fn_table_entry->fn_value;
528518 g->cur_fn = fn_table_entry;
......@@ -532,14 +522,15 @@ void code_gen(CodeGen *g) {
532522 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
533523
534524 // Add debug info.
535 LLVMZigDIScope *fn_scope = LLVMZigFileToScope(g->di_file);
525 LLVMZigDIScope *fn_scope = LLVMZigFileToScope(import->di_file);
536526 unsigned line_number = fn_def_node->line + 1;
537527 unsigned scope_line = line_number;
538528 bool is_definition = true;
539529 unsigned flags = 0;
530 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
540531 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
541 fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number,
542 create_di_function_type(g, fn_proto, g->di_file), fn_table_entry->internal_linkage,
532 fn_scope, buf_ptr(&fn_proto->name), "", import->di_file, line_number,
533 create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage,
543534 is_definition, scope_line, flags, is_optimized, fn);
544535
545536 g->block_scopes.append(LLVMZigSubprogramToScope(subprogram));
......@@ -555,7 +546,7 @@ void code_gen(CodeGen *g) {
555546 LLVMGetParams(fn, codegen_fn_def->params);
556547
557548 bool add_implicit_return = codegen_fn_def->add_implicit_return;
558 gen_block(g, fn_def_node->data.fn_def.body, add_implicit_return);
549 gen_block(g, import, fn_def_node->data.fn_def.body, add_implicit_return);
559550
560551 g->block_scopes.pop();
561552 }
......@@ -563,7 +554,9 @@ void code_gen(CodeGen *g) {
563554
564555 LLVMZigDIBuilderFinalize(g->dbuilder);
565556
566 LLVMDumpModule(g->module);
557 if (g->verbose) {
558 LLVMDumpModule(g->module);
559 }
567560
568561 // in release mode, we're sooooo confident that we've generated correct ir,
569562 // that we skip the verify module step in order to get better performance.
......@@ -573,13 +566,168 @@ void code_gen(CodeGen *g) {
573566#endif
574567}
575568
576void code_gen_optimize(CodeGen *g) {
577 LLVMZigOptimizeModule(g->target_machine, g->module);
578 LLVMDumpModule(g->module);
569static void define_primitive_types(CodeGen *g) {
570 {
571 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
572 entry->type_ref = LLVMInt8Type();
573 buf_init_from_str(&entry->name, "u8");
574 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
575 LLVMZigEncoding_DW_ATE_unsigned());
576 g->type_table.put(&entry->name, entry);
577 g->builtin_types.entry_u8 = entry;
578 }
579 {
580 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
581 entry->type_ref = LLVMInt32Type();
582 buf_init_from_str(&entry->name, "i32");
583 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
584 LLVMZigEncoding_DW_ATE_signed());
585 g->type_table.put(&entry->name, entry);
586 g->builtin_types.entry_i32 = entry;
587 }
588 {
589 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
590 entry->type_ref = LLVMVoidType();
591 buf_init_from_str(&entry->name, "void");
592 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
593 LLVMZigEncoding_DW_ATE_unsigned());
594 g->type_table.put(&entry->name, entry);
595 g->builtin_types.entry_void = entry;
596
597 // invalid types are void
598 g->builtin_types.entry_invalid = entry;
599 }
600 {
601 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
602 entry->type_ref = LLVMVoidType();
603 buf_init_from_str(&entry->name, "unreachable");
604 entry->di_type = g->builtin_types.entry_invalid->di_type;
605 g->type_table.put(&entry->name, entry);
606 g->builtin_types.entry_unreachable = entry;
607 }
579608}
580609
581ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
582 return &g->errors;
610
611
612static void init(CodeGen *g, Buf *source_path) {
613 LLVMInitializeAllTargets();
614 LLVMInitializeAllTargetMCs();
615 LLVMInitializeAllAsmPrinters();
616 LLVMInitializeAllAsmParsers();
617 LLVMInitializeNativeTarget();
618
619 g->is_native_target = true;
620 char *native_triple = LLVMGetDefaultTargetTriple();
621
622 LLVMTargetRef target_ref;
623 char *err_msg = nullptr;
624 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
625 zig_panic("unable to get target from triple: %s", err_msg);
626 }
627
628 char *native_cpu = LLVMZigGetHostCPUName();
629 char *native_features = LLVMZigGetNativeFeatures();
630
631 LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
632 LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
633
634 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
635
636 g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
637 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
638
639 g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
640
641
642 g->module = LLVMModuleCreateWithName("ZigModule");
643
644 g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
645
646 g->builder = LLVMCreateBuilder();
647 g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
648
649
650 define_primitive_types(g);
651
652 Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
653 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
654 const char *flags = "";
655 unsigned runtime_version = 0;
656 g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
657 buf_ptr(source_path), buf_ptr(g->root_source_dir),
658 buf_ptr(producer), is_optimized, flags, runtime_version,
659 "", 0, !g->strip_debug_symbols);
660
661
662}
663
664void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) {
665 if (!g->initialized) {
666 g->initialized = true;
667 init(g, source_path);
668 }
669
670 Buf full_path = BUF_INIT;
671 os_path_join(g->root_source_dir, source_path, &full_path);
672
673 Buf dirname = BUF_INIT;
674 Buf basename = BUF_INIT;
675 os_path_split(&full_path, &dirname, &basename);
676
677 if (g->verbose) {
678 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(source_path));
679 fprintf(stderr, "----------------\n");
680 fprintf(stderr, "%s\n", buf_ptr(source_code));
681
682 fprintf(stderr, "\nTokens:\n");
683 fprintf(stderr, "---------\n");
684 }
685
686 ZigList<Token> *tokens = tokenize(source_code);
687
688 if (g->verbose) {
689 print_tokens(source_code, tokens);
690
691 fprintf(stderr, "\nAST:\n");
692 fprintf(stderr, "------\n");
693 }
694
695 ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
696 import_entry->root = ast_parse(source_code, tokens);
697 assert(import_entry->root);
698 if (g->verbose) {
699 ast_print(import_entry->root, 0);
700
701 fprintf(stderr, "\nSemantic Analysis:\n");
702 fprintf(stderr, "--------------------\n");
703 }
704
705 import_entry->path = source_path;
706 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname));
707 g->import_table.put(source_path, import_entry);
708
709 semantic_analyze(g, import_entry);
710
711 if (g->errors.length == 0) {
712 if (g->verbose) {
713 fprintf(stderr, "OK\n");
714 }
715 } else {
716 for (int i = 0; i < g->errors.length; i += 1) {
717 ErrorMsg *err = &g->errors.at(i);
718 fprintf(stderr, "Error: Line %d, column %d: %s\n",
719 err->line_start + 1, err->column_start + 1,
720 buf_ptr(err->msg));
721 }
722 exit(1);
723 }
724
725 if (g->verbose) {
726 fprintf(stderr, "\nCode Generation:\n");
727 fprintf(stderr, "------------------\n");
728 }
729
730 do_code_gen(g);
583731}
584732
585733static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
......@@ -601,15 +749,15 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
601749}
602750
603751static void generate_h_file(CodeGen *g) {
604 Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->out_name));
752 Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
605753 FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");
606754 if (!out_h)
607755 zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));
608756
609 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->out_name));
757 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));
610758 buf_upcase(export_macro);
611759
612 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->out_name));
760 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
613761 buf_upcase(extern_c_macro);
614762
615763 Buf h_buf = BUF_INIT;
......@@ -644,7 +792,8 @@ static void generate_h_file(CodeGen *g) {
644792 }
645793 }
646794
647 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H", buf_ptr(g->out_name), buf_ptr(g->out_name));
795 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
796 buf_ptr(g->root_out_name), buf_ptr(g->root_out_name));
648797 buf_upcase(ifdef_dance_name);
649798
650799 fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
......@@ -677,9 +826,27 @@ static void generate_h_file(CodeGen *g) {
677826 zig_panic("unable to close h file: %s", strerror(errno));
678827}
679828
680void code_gen_link(CodeGen *g, const char *out_file) {
829void codegen_link(CodeGen *g, const char *out_file) {
830 bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
831 if (is_optimized) {
832 if (g->verbose) {
833 fprintf(stderr, "\nOptimization:\n");
834 fprintf(stderr, "---------------\n");
835 }
836
837 LLVMZigOptimizeModule(g->target_machine, g->module);
838
839 if (g->verbose) {
840 LLVMDumpModule(g->module);
841 }
842 }
843 if (g->verbose) {
844 fprintf(stderr, "\nLink:\n");
845 fprintf(stderr, "-------\n");
846 }
847
681848 if (!out_file) {
682 out_file = buf_ptr(g->out_name);
849 out_file = buf_ptr(g->root_out_name);
683850 }
684851
685852 Buf out_file_o = BUF_INIT;
......@@ -728,8 +895,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
728895
729896 if (g->out_type == OutTypeLib) {
730897 Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d",
731 buf_ptr(g->out_name), g->version_major, g->version_minor, g->version_patch);
732 Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->out_name), g->version_major);
898 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
899 Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
733900 args.append("-shared");
734901 args.append("-soname");
735902 args.append(buf_ptr(soname));
......@@ -756,4 +923,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
756923 if (g->out_type == OutTypeLib) {
757924 generate_h_file(g);
758925 }
926
927 if (g->verbose) {
928 fprintf(stderr, "OK\n");
929 }
759930}
src/codegen.hpp+4-7
......@@ -29,7 +29,7 @@ struct ErrorMsg {
2929};
3030
3131
32CodeGen *create_codegen(AstNode *root, Buf *in_file);
32CodeGen *codegen_create(Buf *root_source_dir);
3333
3434enum CodeGenBuildType {
3535 CodeGenBuildTypeDebug,
......@@ -38,15 +38,12 @@ enum CodeGenBuildType {
3838void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);
3939void codegen_set_is_static(CodeGen *codegen, bool is_static);
4040void codegen_set_strip(CodeGen *codegen, bool strip);
41void codegen_set_verbose(CodeGen *codegen, bool verbose);
4142void codegen_set_out_type(CodeGen *codegen, OutType out_type);
4243void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
4344
44void code_gen_optimize(CodeGen *g);
45void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code);
4546
46void code_gen(CodeGen *g);
47
48void code_gen_link(CodeGen *g, const char *out_file);
49
50ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g);
47void codegen_link(CodeGen *g, const char *out_file);
5148
5249#endif
src/error.cpp+1
......@@ -5,6 +5,7 @@ const char *err_str(int err) {
55 case ErrorNone: return "(no error)";
66 case ErrorNoMem: return "out of memory";
77 case ErrorInvalidFormat: return "invalid format";
8 case ErrorSemanticAnalyzeFail: return "semantic analyze failed";
89 }
910 return "(invalid error)";
1011}
src/error.hpp+1
......@@ -12,6 +12,7 @@ enum Error {
1212 ErrorNone,
1313 ErrorNoMem,
1414 ErrorInvalidFormat,
15 ErrorSemanticAnalyzeFail,
1516};
1617
1718const char *err_str(int err);
src/main.cpp+51-119
......@@ -6,25 +6,11 @@
66 */
77
88#include "config.h"
9#include "util.hpp"
10#include "list.hpp"
119#include "buffer.hpp"
12#include "parser.hpp"
13#include "tokenizer.hpp"
14#include "error.hpp"
1510#include "codegen.hpp"
16#include "analyze.hpp"
11#include "os.hpp"
1712
1813#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21#include <limits.h>
22#include <stdint.h>
23#include <errno.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include <inttypes.h>
2814
2915static int usage(const char *arg0) {
3016 fprintf(stderr, "Usage: %s [command] [options] target\n"
......@@ -38,6 +24,7 @@ static int usage(const char *arg0) {
3824 " --export [exe|lib|obj] override output type\n"
3925 " --name [name] override output name\n"
4026 " --output [file] override destination path\n"
27 " --verbose turn on compiler debug output\n"
4128 , arg0);
4229 return EXIT_FAILURE;
4330}
......@@ -47,98 +34,47 @@ static int version(void) {
4734 return EXIT_SUCCESS;
4835}
4936
50static Buf *fetch_file(FILE *f) {
51 int fd = fileno(f);
52 struct stat st;
53 if (fstat(fd, &st))
54 zig_panic("unable to stat file: %s", strerror(errno));
55 off_t big_size = st.st_size;
56 if (big_size > INT_MAX)
57 zig_panic("file too big");
58 int size = (int)big_size;
59
60 Buf *buf = buf_alloc_fixed(size);
61 size_t amt_read = fread(buf_ptr(buf), 1, buf_len(buf), f);
62 if (amt_read != (size_t)buf_len(buf))
63 zig_panic("error reading: %s", strerror(errno));
64
65 return buf;
66}
67
68static int build(const char *arg0, const char *in_file, const char *out_file, bool release,
69 bool strip, bool is_static, OutType out_type, char *out_name)
70{
71 static char cur_dir[1024];
37struct Build {
38 const char *in_file;
39 const char *out_file;
40 bool release;
41 bool strip;
42 bool is_static;
43 OutType out_type;
44 const char *out_name;
45 bool verbose;
46};
7247
73 if (!in_file)
48static int build(const char *arg0, Build *b) {
49 if (!b->in_file)
7450 return usage(arg0);
7551
76 FILE *in_f;
77 if (strcmp(in_file, "-") == 0) {
78 in_f = stdin;
79 char *result = getcwd(cur_dir, sizeof(cur_dir));
80 if (!result)
81 zig_panic("unable to get current working directory: %s", strerror(errno));
82 } else {
83 in_f = fopen(in_file, "rb");
84 if (!in_f)
85 zig_panic("unable to open %s for reading: %s\n", in_file, strerror(errno));
86 }
52 Buf in_file_buf = BUF_INIT;
53 buf_init_from_str(&in_file_buf, b->in_file);
8754
88 fprintf(stderr, "Original source:\n");
89 fprintf(stderr, "----------------\n");
90 Buf *in_data = fetch_file(in_f);
91 fprintf(stderr, "%s\n", buf_ptr(in_data));
92
93 fprintf(stderr, "\nTokens:\n");
94 fprintf(stderr, "---------\n");
95 ZigList<Token> *tokens = tokenize(in_data);
96 print_tokens(in_data, tokens);
97
98 fprintf(stderr, "\nAST:\n");
99 fprintf(stderr, "------\n");
100 AstNode *root = ast_parse(in_data, tokens);
101 assert(root);
102 ast_print(root, 0);
103
104 fprintf(stderr, "\nSemantic Analysis:\n");
105 fprintf(stderr, "--------------------\n");
106 CodeGen *codegen = create_codegen(root, buf_create_from_str(in_file));
107 codegen_set_build_type(codegen, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
108 codegen_set_strip(codegen, strip);
109 codegen_set_is_static(codegen, is_static);
110 if (out_type != OutTypeUnknown)
111 codegen_set_out_type(codegen, out_type);
112 if (out_name)
113 codegen_set_out_name(codegen, buf_create_from_str(out_name));
114 semantic_analyze(codegen);
115 ZigList<ErrorMsg> *errors = codegen_error_messages(codegen);
116 if (errors->length == 0) {
117 fprintf(stderr, "OK\n");
55 Buf root_source_dir = BUF_INIT;
56 Buf root_source_code = BUF_INIT;
57 Buf root_source_name = BUF_INIT;
58 if (buf_eql_str(&in_file_buf, "-")) {
59 os_get_cwd(&root_source_dir);
60 os_fetch_file(stdin, &root_source_code);
61 buf_init_from_str(&root_source_name, "");
11862 } else {
119 for (int i = 0; i < errors->length; i += 1) {
120 ErrorMsg *err = &errors->at(i);
121 fprintf(stderr, "Error: Line %d, column %d: %s\n",
122 err->line_start + 1, err->column_start + 1,
123 buf_ptr(err->msg));
124 }
125 return 1;
63 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
64 os_fetch_file_path(buf_create_from_str(b->in_file), &root_source_code);
12665 }
12766
128 fprintf(stderr, "\nCode Generation:\n");
129 fprintf(stderr, "------------------\n");
130 code_gen(codegen);
131
132 if (release) {
133 fprintf(stderr, "\nOptimization:\n");
134 fprintf(stderr, "---------------\n");
135 code_gen_optimize(codegen);
136 }
137
138 fprintf(stderr, "\nLink:\n");
139 fprintf(stderr, "-------\n");
140 code_gen_link(codegen, out_file);
141 fprintf(stderr, "OK\n");
67 CodeGen *g = codegen_create(&root_source_dir);
68 codegen_set_build_type(g, b->release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
69 codegen_set_strip(g, b->strip);
70 codegen_set_is_static(g, b->is_static);
71 if (b->out_type != OutTypeUnknown)
72 codegen_set_out_type(g, b->out_type);
73 if (b->out_name)
74 codegen_set_out_name(g, buf_create_from_str(b->out_name));
75 codegen_set_verbose(g, b->verbose);
76 codegen_add_code(g, &root_source_name, &root_source_code);
77 codegen_link(g, b->out_file);
14278
14379 return 0;
14480}
......@@ -151,43 +87,39 @@ enum Cmd {
15187
15288int main(int argc, char **argv) {
15389 char *arg0 = argv[0];
154 char *in_file = NULL;
155 char *out_file = NULL;
156 bool release = false;
157 bool strip = false;
158 bool is_static = false;
159
160 OutType out_type = OutTypeUnknown;
161 char *out_name = NULL;
16290
91 Build b = {0};
16392 Cmd cmd = CmdNone;
93
16494 for (int i = 1; i < argc; i += 1) {
16595 char *arg = argv[i];
16696 if (arg[0] == '-' && arg[1] == '-') {
16797 if (strcmp(arg, "--release") == 0) {
168 release = true;
98 b.release = true;
16999 } else if (strcmp(arg, "--strip") == 0) {
170 strip = true;
100 b.strip = true;
171101 } else if (strcmp(arg, "--static") == 0) {
172 is_static = true;
102 b.is_static = true;
103 } else if (strcmp(arg, "--verbose") == 0) {
104 b.verbose = true;
173105 } else if (i + 1 >= argc) {
174106 return usage(arg0);
175107 } else {
176108 i += 1;
177109 if (strcmp(arg, "--output") == 0) {
178 out_file = argv[i];
110 b.out_file = argv[i];
179111 } else if (strcmp(arg, "--export") == 0) {
180112 if (strcmp(argv[i], "exe") == 0) {
181 out_type = OutTypeExe;
113 b.out_type = OutTypeExe;
182114 } else if (strcmp(argv[i], "lib") == 0) {
183 out_type = OutTypeLib;
115 b.out_type = OutTypeLib;
184116 } else if (strcmp(argv[i], "obj") == 0) {
185 out_type = OutTypeObj;
117 b.out_type = OutTypeObj;
186118 } else {
187119 return usage(arg0);
188120 }
189121 } else if (strcmp(arg, "--name") == 0) {
190 out_name = argv[i];
122 b.out_name = argv[i];
191123 } else {
192124 return usage(arg0);
193125 }
......@@ -206,8 +138,8 @@ int main(int argc, char **argv) {
206138 case CmdNone:
207139 zig_unreachable();
208140 case CmdBuild:
209 if (!in_file) {
210 in_file = arg;
141 if (!b.in_file) {
142 b.in_file = arg;
211143 } else {
212144 return usage(arg0);
213145 }
......@@ -222,7 +154,7 @@ int main(int argc, char **argv) {
222154 case CmdNone:
223155 return usage(arg0);
224156 case CmdBuild:
225 return build(arg0, in_file, out_file, release, strip, is_static, out_type, out_name);
157 return build(arg0, &b);
226158 case CmdVersion:
227159 return version();
228160 }
src/os.cpp+51-4
......@@ -13,8 +13,8 @@
1313#include <sys/types.h>
1414#include <sys/stat.h>
1515#include <sys/wait.h>
16#include <stdio.h>
1716#include <fcntl.h>
17#include <limits.h>
1818
1919void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached) {
2020 pid_t pid = fork();
......@@ -37,7 +37,7 @@ void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detache
3737 zig_panic("execvp failed: %s", strerror(errno));
3838}
3939
40static void read_all_fd(int fd, Buf *out_buf) {
40static void read_all_fd_stream(int fd, Buf *out_buf) {
4141 static const ssize_t buf_size = 0x2000;
4242 buf_resize(out_buf, buf_size);
4343 ssize_t actual_buf_len = 0;
......@@ -72,6 +72,12 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
7272 buf_init_from_buf(out_basename, full_path);
7373}
7474
75void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
76 buf_init_from_buf(out_full_path, dirname);
77 buf_append_char(out_full_path, '/');
78 buf_append_buf(out_full_path, basename);
79}
80
7581void os_exec_process(const char *exe, ZigList<const char *> &args,
7682 int *return_code, Buf *out_stderr, Buf *out_stdout)
7783{
......@@ -117,8 +123,8 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,
117123
118124 waitpid(pid, return_code, 0);
119125
120 read_all_fd(stdout_pipe[0], out_stdout);
121 read_all_fd(stderr_pipe[0], out_stderr);
126 read_all_fd_stream(stdout_pipe[0], out_stdout);
127 read_all_fd_stream(stderr_pipe[0], out_stderr);
122128
123129 }
124130}
......@@ -133,3 +139,44 @@ void os_write_file(Buf *full_path, Buf *contents) {
133139 if (close(fd) == -1)
134140 zig_panic("close failed");
135141}
142
143int os_fetch_file(FILE *f, Buf *out_contents) {
144 int fd = fileno(f);
145 struct stat st;
146 if (fstat(fd, &st))
147 zig_panic("unable to stat file: %s", strerror(errno));
148 off_t big_size = st.st_size;
149 if (big_size > INT_MAX)
150 zig_panic("file too big");
151 int size = (int)big_size;
152
153 buf_resize(out_contents, size);
154 ssize_t ret = read(fd, buf_ptr(out_contents), size);
155
156 if (ret != size)
157 zig_panic("unable to read file: %s", strerror(errno));
158
159 return 0;
160}
161
162int os_fetch_file_path(Buf *full_path, Buf *out_contents) {
163 FILE *f = fopen(buf_ptr(full_path), "rb");
164 if (!f)
165 zig_panic("unable to open %s: %s\n", buf_ptr(full_path), strerror(errno));
166 int result = os_fetch_file(f, out_contents);
167 fclose(f);
168 return result;
169}
170
171int os_get_cwd(Buf *out_cwd) {
172 int err = ERANGE;
173 buf_resize(out_cwd, 512);
174 while (err == ERANGE) {
175 buf_resize(out_cwd, buf_len(out_cwd) * 2);
176 err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno;
177 }
178 if (err)
179 zig_panic("unable to get cwd: %s", strerror(err));
180
181 return 0;
182}
src/os.hpp+9
......@@ -11,13 +11,22 @@
1111#include "list.hpp"
1212#include "buffer.hpp"
1313
14#include <stdio.h>
15
1416void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached);
1517void os_exec_process(const char *exe, ZigList<const char *> &args,
1618 int *return_code, Buf *out_stderr, Buf *out_stdout);
1719
1820void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
21void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
1922
2023void os_write_file(Buf *full_path, Buf *contents);
2124
2225
26int os_fetch_file(FILE *file, Buf *out_contents);
27int os_fetch_file_path(Buf *full_path, Buf *out_contents);
28
29int os_get_cwd(Buf *out_cwd);
30
31
2332#endif
src/parser.cpp+41-1
......@@ -100,6 +100,8 @@ const char *node_type_str(NodeType node_type) {
100100 return "Symbol";
101101 case NodeTypePrefixOpExpr:
102102 return "PrefixOpExpr";
103 case NodeTypeUse:
104 return "Use";
103105 }
104106 zig_unreachable();
105107}
......@@ -241,6 +243,9 @@ void ast_print(AstNode *node, int indent) {
241243 fprintf(stderr, "PrimaryExpr Symbol %s\n",
242244 buf_ptr(&node->data.symbol));
243245 break;
246 case NodeTypeUse:
247 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
248 break;
244249 }
245250}
246251
......@@ -1231,7 +1236,36 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
12311236}
12321237
12331238/*
1234TopLevelDecl : FnDef | ExternBlock | RootExportDecl
1239Use : many(Directive) token(Use) token(String) token(Semicolon)
1240*/
1241static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory) {
1242 assert(mandatory == false);
1243
1244 Token *use_kw = &pc->tokens->at(*token_index);
1245 if (use_kw->id != TokenIdKeywordUse)
1246 return nullptr;
1247 *token_index += 1;
1248
1249 Token *use_name = &pc->tokens->at(*token_index);
1250 *token_index += 1;
1251 ast_expect_token(pc, use_name, TokenIdStringLiteral);
1252
1253 Token *semicolon = &pc->tokens->at(*token_index);
1254 *token_index += 1;
1255 ast_expect_token(pc, semicolon, TokenIdSemicolon);
1256
1257 AstNode *node = ast_create_node(NodeTypeUse, use_kw);
1258
1259 parse_string_literal(pc, use_name, &node->data.use.path);
1260
1261 node->data.use.directives = pc->directive_list;
1262 pc->directive_list = nullptr;
1263
1264 return node;
1265}
1266
1267/*
1268TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use
12351269*/
12361270static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
12371271 for (;;) {
......@@ -1258,6 +1292,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
12581292 continue;
12591293 }
12601294
1295 AstNode *use_node = ast_parse_use(pc, token_index, false);
1296 if (use_node) {
1297 top_level_decls->append(use_node);
1298 continue;
1299 }
1300
12611301 if (pc->directive_list->length > 0) {
12621302 ast_error(directive_token, "invalid directive");
12631303 }
src/parser.hpp+7
......@@ -35,6 +35,7 @@ enum NodeType {
3535 NodeTypeSymbol,
3636 NodeTypePrefixOpExpr,
3737 NodeTypeFnCallExpr,
38 NodeTypeUse,
3839};
3940
4041struct AstNodeRoot {
......@@ -158,6 +159,11 @@ struct AstNodePrefixOpExpr {
158159 AstNode *primary_expr;
159160};
160161
162struct AstNodeUse {
163 Buf path;
164 ZigList<AstNode *> *directives;
165};
166
161167struct AstNode {
162168 enum NodeType type;
163169 AstNode *parent;
......@@ -180,6 +186,7 @@ struct AstNode {
180186 AstNodeCastExpr cast_expr;
181187 AstNodePrefixOpExpr prefix_op_expr;
182188 AstNodeFnCallExpr fn_call_expr;
189 AstNodeUse use;
183190 Buf number;
184191 Buf string;
185192 Buf symbol;
src/semantic_info.hpp+23-14
......@@ -12,15 +12,6 @@
1212#include "hash_map.hpp"
1313#include "zig_llvm.hpp"
1414
15struct FnTableEntry {
16 LLVMValueRef fn_value;
17 AstNode *proto_node;
18 AstNode *fn_def_node;
19 bool is_extern;
20 bool internal_linkage;
21 unsigned calling_convention;
22};
23
2415struct TypeTableEntry {
2516 LLVMTypeRef type_ref;
2617 LLVMZigDIType *di_type;
......@@ -33,17 +24,35 @@ struct TypeTableEntry {
3324 TypeTableEntry *pointer_mut_parent;
3425};
3526
27struct ImportTableEntry {
28 AstNode *root;
29 Buf *path; // relative to root_source_dir
30 LLVMZigDIFile *di_file;
31};
32
33struct FnTableEntry {
34 LLVMValueRef fn_value;
35 AstNode *proto_node;
36 AstNode *fn_def_node;
37 bool is_extern;
38 bool internal_linkage;
39 unsigned calling_convention;
40 ImportTableEntry *import_entry;
41};
42
3643struct CodeGen {
3744 LLVMModuleRef module;
38 AstNode *root;
3945 ZigList<ErrorMsg> errors;
4046 LLVMBuilderRef builder;
4147 LLVMZigDIBuilder *dbuilder;
4248 LLVMZigDICompileUnit *compile_unit;
49
50 // reminder: hash tables must be initialized before use
4351 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
4452 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
4553 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
4654 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
55 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
4756
4857 struct {
4958 TypeTableEntry *entry_u8;
......@@ -60,12 +69,10 @@ struct CodeGen {
6069 CodeGenBuildType build_type;
6170 LLVMTargetMachineRef target_machine;
6271 bool is_native_target;
63 Buf in_file;
64 Buf in_dir;
72 Buf *root_source_dir;
73 Buf *root_out_name;
6574 ZigList<LLVMZigDIScope *> block_scopes;
66 LLVMZigDIFile *di_file;
6775 ZigList<FnTableEntry *> fn_defs;
68 Buf *out_name;
6976 OutType out_type;
7077 FnTableEntry *cur_fn;
7178 bool c_stdint_used;
......@@ -73,6 +80,8 @@ struct CodeGen {
7380 int version_major;
7481 int version_minor;
7582 int version_patch;
83 bool verbose;
84 bool initialized;
7685};
7786
7887struct TypeNode {
src/tokenizer.cpp+3
......@@ -180,6 +180,8 @@ static void end_token(Tokenize *t) {
180180 t->cur_tok->id = TokenIdKeywordExport;
181181 } else if (mem_eql_str(token_mem, token_len, "as")) {
182182 t->cur_tok->id = TokenIdKeywordAs;
183 } else if (mem_eql_str(token_mem, token_len, "use")) {
184 t->cur_tok->id = TokenIdKeywordUse;
183185 }
184186
185187 t->cur_tok = nullptr;
......@@ -562,6 +564,7 @@ static const char * token_name(Token *token) {
562564 case TokenIdKeywordPub: return "Pub";
563565 case TokenIdKeywordExport: return "Export";
564566 case TokenIdKeywordAs: return "As";
567 case TokenIdKeywordUse: return "Use";
565568 case TokenIdLParen: return "LParen";
566569 case TokenIdRParen: return "RParen";
567570 case TokenIdComma: return "Comma";
src/tokenizer.hpp+1
......@@ -22,6 +22,7 @@ enum TokenId {
2222 TokenIdKeywordPub,
2323 TokenIdKeywordExport,
2424 TokenIdKeywordAs,
25 TokenIdKeywordUse,
2526 TokenIdLParen,
2627 TokenIdRParen,
2728 TokenIdComma,
test/run_tests.cpp+2
......@@ -47,6 +47,7 @@ static void add_simple_case(const char *case_name, const char *source, const cha
4747 test_case->compiler_args.append(tmp_exe_path);
4848 test_case->compiler_args.append("--release");
4949 test_case->compiler_args.append("--strip");
50 test_case->compiler_args.append("--verbose");
5051
5152 test_cases.append(test_case);
5253}
......@@ -70,6 +71,7 @@ static void add_compile_fail_case(const char *case_name, const char *source, int
7071 test_case->compiler_args.append(tmp_exe_path);
7172 test_case->compiler_args.append("--release");
7273 test_case->compiler_args.append("--strip");
74 test_case->compiler_args.append("--verbose");
7375
7476 test_cases.append(test_case);
7577