authorgravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-30 22:12:21-07:00
committergravatar for thejoshwolfe@gmail.comJosh Wolfe <thejoshwolfe@gmail.com> 2015-11-30 22:12:21-07:00
log00f4c05784c05552e1e379b98c09161c936cfb31
tree5b2234cae585c5ac3a2cb23503908b0a6e2a27e3
parentabbc3957019c3a12dacd54869ff18b91c3f07699
parent55b8472374eede496b59396dbe253b05b16063e1

merge conflicts


26 files changed, 562 insertions(+), 306 deletions(-)

CMakeLists.txt+4-4
...@@ -22,16 +22,16 @@ include_directories(...@@ -22,16 +22,16 @@ include_directories(
22)22)
2323
24set(ZIG_SOURCES24set(ZIG_SOURCES
25 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
26 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
25 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"27 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
28 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
26 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"29 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
27 "${CMAKE_SOURCE_DIR}/src/error.cpp"30 "${CMAKE_SOURCE_DIR}/src/error.cpp"
28 "${CMAKE_SOURCE_DIR}/src/main.cpp"31 "${CMAKE_SOURCE_DIR}/src/main.cpp"
29 "${CMAKE_SOURCE_DIR}/src/parser.cpp"32 "${CMAKE_SOURCE_DIR}/src/os.cpp"
30 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
31 "${CMAKE_SOURCE_DIR}/src/util.cpp"33 "${CMAKE_SOURCE_DIR}/src/util.cpp"
32 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
33 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"34 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
34 "${CMAKE_SOURCE_DIR}/src/os.cpp"
35)35)
3636
37set(TEST_SOURCES37set(TEST_SOURCES
README.md+3-1
...@@ -79,7 +79,9 @@ zig | C equivalent | Description...@@ -79,7 +79,9 @@ zig | C equivalent | Description
79```79```
80Root : many(TopLevelDecl) token(EOF)80Root : many(TopLevelDecl) token(EOF)
8181
82TopLevelDecl : FnDef | ExternBlock | RootExportDecl82TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use
83
84Use : many(Directive) token(Use) token(String) token(Semicolon)
8385
84RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token(Semicolon)86RootExportDecl : 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")...@@ -7,7 +7,7 @@ if exists("b:current_syntax")
7 finish7 finish
8endif8endif
99
10syn keyword zigKeyword fn return mut const extern unreachable export pub as10syn keyword zigKeyword fn return mut const extern unreachable export pub as use
11syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void11syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 void
1212
13syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell13syn region zigCommentLine start="//" end="$" contains=zigTodo,@Spell
...@@ -19,6 +19,15 @@ syn region zigCommentBlockDocNest matchgroup=zigCommentBlockDoc start="/\*" end=...@@ -19,6 +19,15 @@ syn region zigCommentBlockDocNest matchgroup=zigCommentBlockDoc start="/\*" end=
1919
20syn keyword zigTodo contained TODO XXX20syn 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
22let b:current_syntax = "zig"31let b:current_syntax = "zig"
2332
24hi def link zigKeyword Keyword33hi def link zigKeyword Keyword
...@@ -28,4 +37,8 @@ hi def link zigCommentLineDoc SpecialComment...@@ -28,4 +37,8 @@ hi def link zigCommentLineDoc SpecialComment
28hi def link zigCommentBlock zigCommentLine37hi def link zigCommentBlock zigCommentLine
29hi def link zigCommentBlockDoc zigCommentLineDoc38hi def link zigCommentBlockDoc zigCommentLineDoc
30hi def link zigTodo Todo39hi def link zigTodo Todo
3140hi 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+84-93
...@@ -119,7 +119,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {...@@ -119,7 +119,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {
119 resolve_type(g, node->data.fn_proto.return_type);119 resolve_type(g, node->data.fn_proto.return_type);
120}120}
121121
122static void preview_function_declarations(CodeGen *g, AstNode *node) {122static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *node) {
123 switch (node->type) {123 switch (node->type) {
124 case NodeTypeExternBlock:124 case NodeTypeExternBlock:
125 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {125 for (int i = 0; i < node->data.extern_block.directives->length; i += 1) {
...@@ -145,6 +145,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {...@@ -145,6 +145,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
145 fn_table_entry->proto_node = fn_proto;145 fn_table_entry->proto_node = fn_proto;
146 fn_table_entry->is_extern = true;146 fn_table_entry->is_extern = true;
147 fn_table_entry->calling_convention = LLVMCCallConv;147 fn_table_entry->calling_convention = LLVMCCallConv;
148 fn_table_entry->import_entry = import;
148 g->fn_table.put(name, fn_table_entry);149 g->fn_table.put(name, fn_table_entry);
149 }150 }
150 break;151 break;
...@@ -162,6 +163,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {...@@ -162,6 +163,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
162 node->codegen_node->data.fn_def_node.skip = true;163 node->codegen_node->data.fn_def_node.skip = true;
163 } else {164 } else {
164 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);165 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
166 fn_table_entry->import_entry = import;
165 fn_table_entry->proto_node = proto_node;167 fn_table_entry->proto_node = proto_node;
166 fn_table_entry->fn_def_node = node;168 fn_table_entry->fn_def_node = node;
167 fn_table_entry->internal_linkage = proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport;169 fn_table_entry->internal_linkage = proto_node->data.fn_proto.visib_mod != FnProtoVisibModExport;
...@@ -196,8 +198,8 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {...@@ -196,8 +198,8 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
196 } else {198 } else {
197 g->root_export_decl = node;199 g->root_export_decl = node;
198200
199 if (!g->out_name)201 if (!g->root_out_name)
200 g->out_name = &node->data.root_export_decl.name;202 g->root_out_name = &node->data.root_export_decl.name;
201203
202 Buf *out_type = &node->data.root_export_decl.type;204 Buf *out_type = &node->data.root_export_decl.type;
203 OutType export_out_type;205 OutType export_out_type;
...@@ -215,6 +217,9 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {...@@ -215,6 +217,9 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
215 g->out_type = export_out_type;217 g->out_type = export_out_type;
216 }218 }
217 break;219 break;
220 case NodeTypeUse:
221 zig_panic("TODO use");
222 break;
218 case NodeTypeDirective:223 case NodeTypeDirective:
219 case NodeTypeParamDecl:224 case NodeTypeParamDecl:
220 case NodeTypeFnProto:225 case NodeTypeFnProto:
...@@ -379,6 +384,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, BlockContext *context, Ty...@@ -379,6 +384,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, BlockContext *context, Ty
379 case NodeTypeRootExportDecl:384 case NodeTypeRootExportDecl:
380 case NodeTypeExternBlock:385 case NodeTypeExternBlock:
381 case NodeTypeFnDef:386 case NodeTypeFnDef:
387 case NodeTypeUse:
382 zig_unreachable();388 zig_unreachable();
383 }389 }
384 zig_unreachable();390 zig_unreachable();
...@@ -437,6 +443,75 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {...@@ -437,6 +443,75 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
437 }443 }
438}444}
439445
446static void analyze_expression(CodeGen *g, AstNode *node) {
447 switch (node->type) {
448 case NodeTypeBlock:
449 for (int i = 0; i < node->data.block.statements.length; i += 1) {
450 AstNode *child = node->data.block.statements.at(i);
451 analyze_expression(g, child);
452 }
453 break;
454 case NodeTypeReturnExpr:
455 if (node->data.return_expr.expr) {
456 analyze_expression(g, node->data.return_expr.expr);
457 }
458 break;
459 case NodeTypeBinOpExpr:
460 analyze_expression(g, node->data.bin_op_expr.op1);
461 analyze_expression(g, node->data.bin_op_expr.op2);
462 break;
463 case NodeTypeFnCallExpr:
464 {
465 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
466
467 auto entry = g->fn_table.maybe_get(name);
468 if (!entry) {
469 add_node_error(g, node,
470 buf_sprintf("undefined function: '%s'", buf_ptr(name)));
471 } else {
472 FnTableEntry *fn_table_entry = entry->value;
473 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
474 int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
475 int actual_param_count = node->data.fn_call_expr.params.length;
476 if (expected_param_count != actual_param_count) {
477 add_node_error(g, node,
478 buf_sprintf("wrong number of arguments. Expected %d, got %d.",
479 expected_param_count, actual_param_count));
480 }
481 }
482
483 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
484 AstNode *child = node->data.fn_call_expr.params.at(i);
485 analyze_expression(g, child);
486 }
487 break;
488 }
489 case NodeTypeCastExpr:
490 zig_panic("TODO");
491 break;
492 case NodeTypePrefixOpExpr:
493 zig_panic("TODO");
494 break;
495 case NodeTypeNumberLiteral:
496 case NodeTypeStringLiteral:
497 case NodeTypeUnreachable:
498 case NodeTypeSymbol:
499 // nothing to do
500 break;
501 case NodeTypeDirective:
502 case NodeTypeFnDecl:
503 case NodeTypeFnProto:
504 case NodeTypeParamDecl:
505 case NodeTypeType:
506 case NodeTypeRoot:
507 case NodeTypeRootExportDecl:
508 case NodeTypeExternBlock:
509 case NodeTypeFnDef:
510 case NodeTypeUse:
511 zig_unreachable();
512 }
513}
514
440static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {515static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
441 switch (node->type) {516 switch (node->type) {
442 case NodeTypeFnDef:517 case NodeTypeFnDef:
...@@ -470,9 +545,9 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {...@@ -470,9 +545,9 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
470545
471 case NodeTypeRootExportDecl:546 case NodeTypeRootExportDecl:
472 case NodeTypeExternBlock:547 case NodeTypeExternBlock:
548 case NodeTypeUse:
473 // already looked at these in the preview pass549 // already looked at these in the preview pass
474 break;550 break;
475
476 case NodeTypeDirective:551 case NodeTypeDirective:
477 case NodeTypeParamDecl:552 case NodeTypeParamDecl:
478 case NodeTypeFnProto:553 case NodeTypeFnProto:
...@@ -493,13 +568,13 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {...@@ -493,13 +568,13 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
493 }568 }
494}569}
495570
496static void analyze_root(CodeGen *g, AstNode *node) {571static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
497 assert(node->type == NodeTypeRoot);572 assert(node->type == NodeTypeRoot);
498573
499 // find function declarations574 // find function declarations
500 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {575 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
501 AstNode *child = node->data.root.top_level_decls.at(i);576 AstNode *child = node->data.root.top_level_decls.at(i);
502 preview_function_declarations(g, child);577 preview_function_declarations(g, import, child);
503 }578 }
504579
505 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {580 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
...@@ -507,7 +582,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {...@@ -507,7 +582,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {
507 analyze_top_level_declaration(g, child);582 analyze_top_level_declaration(g, child);
508 }583 }
509584
510 if (!g->out_name) {585 if (!g->root_out_name) {
511 add_node_error(g, node,586 add_node_error(g, node,
512 buf_sprintf("missing export declaration and output name not provided"));587 buf_sprintf("missing export declaration and output name not provided"));
513 } else if (g->out_type == OutTypeUnknown) {588 } else if (g->out_type == OutTypeUnknown) {
...@@ -516,91 +591,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {...@@ -516,91 +591,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {
516 }591 }
517}592}
518593
519static void define_primitive_types(CodeGen *g) {594void semantic_analyze(CodeGen *g, ImportTableEntry *import_table_entry) {
520 {595 analyze_root(g, import_table_entry, import_table_entry->root);
521 // if this type is anywhere in the AST, we should never hit codegen.
522 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
523 buf_init_from_str(&entry->name, "(invalid)");
524 g->builtin_types.entry_invalid = entry;
525 }
526 {
527 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
528 entry->type_ref = LLVMInt8Type();
529 buf_init_from_str(&entry->name, "u8");
530 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
531 LLVMZigEncoding_DW_ATE_unsigned());
532 g->type_table.put(&entry->name, entry);
533 g->builtin_types.entry_u8 = entry;
534 }
535 {
536 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
537 entry->type_ref = LLVMInt32Type();
538 buf_init_from_str(&entry->name, "i32");
539 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
540 LLVMZigEncoding_DW_ATE_signed());
541 g->type_table.put(&entry->name, entry);
542 g->builtin_types.entry_i32 = entry;
543 }
544 {
545 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
546 entry->type_ref = LLVMVoidType();
547 buf_init_from_str(&entry->name, "void");
548 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
549 LLVMZigEncoding_DW_ATE_unsigned());
550 g->type_table.put(&entry->name, entry);
551 g->builtin_types.entry_void = entry;
552 }
553 {
554 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
555 entry->type_ref = LLVMVoidType();
556 buf_init_from_str(&entry->name, "unreachable");
557 entry->di_type = g->builtin_types.entry_void->di_type;
558 g->type_table.put(&entry->name, entry);
559 g->builtin_types.entry_unreachable = entry;
560 }
561}
562
563
564void semantic_analyze(CodeGen *g) {
565 LLVMInitializeAllTargets();
566 LLVMInitializeAllTargetMCs();
567 LLVMInitializeAllAsmPrinters();
568 LLVMInitializeAllAsmParsers();
569 LLVMInitializeNativeTarget();
570
571 g->is_native_target = true;
572 char *native_triple = LLVMGetDefaultTargetTriple();
573
574 LLVMTargetRef target_ref;
575 char *err_msg = nullptr;
576 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
577 zig_panic("unable to get target from triple: %s", err_msg);
578 }
579
580 char *native_cpu = LLVMZigGetHostCPUName();
581 char *native_features = LLVMZigGetNativeFeatures();
582
583 LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
584 LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
585
586 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
587
588 g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
589 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
590
591 g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
592
593
594 g->module = LLVMModuleCreateWithName("ZigModule");
595
596 g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
597
598 g->builder = LLVMCreateBuilder();
599 g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
600
601
602 define_primitive_types(g);
603
604 analyze_root(g, g->root);
605}596}
606597
src/analyze.hpp+2-1
...@@ -9,7 +9,8 @@...@@ -9,7 +9,8 @@
9#define ZIG_ANALYZE_HPP9#define ZIG_ANALYZE_HPP
1010
11struct CodeGen;11struct CodeGen;
12struct ImportTableEntry;
1213
13void semantic_analyze(CodeGen *g);14void semantic_analyze(CodeGen *g, ImportTableEntry *entry);
1415
15#endif16#endif
src/codegen.cpp+216-42
...@@ -11,26 +11,21 @@...@@ -11,26 +11,21 @@
11#include "os.hpp"11#include "os.hpp"
12#include "config.h"12#include "config.h"
13#include "error.hpp"13#include "error.hpp"
14
15#include "semantic_info.hpp"14#include "semantic_info.hpp"
15#include "analyze.hpp"
1616
17#include <stdio.h>17#include <stdio.h>
18#include <errno.h>18#include <errno.h>
1919
20CodeGen *create_codegen(AstNode *root, Buf *in_full_path) {20CodeGen *codegen_create(Buf *root_source_dir) {
21 CodeGen *g = allocate<CodeGen>(1);21 CodeGen *g = allocate<CodeGen>(1);
22 g->root = root;
23 g->fn_table.init(32);22 g->fn_table.init(32);
24 g->str_table.init(32);23 g->str_table.init(32);
25 g->type_table.init(32);24 g->type_table.init(32);
26 g->link_table.init(32);25 g->link_table.init(32);
27 g->is_static = false;26 g->import_table.init(32);
28 g->build_type = CodeGenBuildTypeDebug;27 g->build_type = CodeGenBuildTypeDebug;
29 g->strip_debug_symbols = false;28 g->root_source_dir = root_source_dir;
30 g->out_name = nullptr;
31 g->out_type = OutTypeUnknown;
32
33 os_path_split(in_full_path, &g->in_dir, &g->in_file);
34 return g;29 return g;
35}30}
3631
...@@ -42,6 +37,10 @@ void codegen_set_is_static(CodeGen *g, bool is_static) {...@@ -42,6 +37,10 @@ void codegen_set_is_static(CodeGen *g, bool is_static) {
42 g->is_static = is_static;37 g->is_static = is_static;
43}38}
4439
40void codegen_set_verbose(CodeGen *g, bool verbose) {
41 g->verbose = verbose;
42}
43
45void codegen_set_strip(CodeGen *g, bool strip) {44void codegen_set_strip(CodeGen *g, bool strip) {
46 g->strip_debug_symbols = strip;45 g->strip_debug_symbols = strip;
47}46}
...@@ -51,7 +50,7 @@ void codegen_set_out_type(CodeGen *g, OutType out_type) {...@@ -51,7 +50,7 @@ void codegen_set_out_type(CodeGen *g, OutType out_type) {
51}50}
5251
53void codegen_set_out_name(CodeGen *g, Buf *out_name) {52void codegen_set_out_name(CodeGen *g, Buf *out_name) {
54 g->out_name = out_name;53 g->root_out_name = out_name;
55}54}
5655
57static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);56static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
...@@ -425,16 +424,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -425,16 +424,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
425 case NodeTypeBlock:424 case NodeTypeBlock:
426 case NodeTypeExternBlock:425 case NodeTypeExternBlock:
427 case NodeTypeDirective:426 case NodeTypeDirective:
427 case NodeTypeUse:
428 zig_unreachable();428 zig_unreachable();
429 }429 }
430 zig_unreachable();430 zig_unreachable();
431}431}
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) {
434 assert(block_node->type == NodeTypeBlock);434 assert(block_node->type == NodeTypeBlock);
435435
436 LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, g->block_scopes.last(),436 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);
438 g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block));438 g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block));
439439
440 add_debug_source_node(g, block_node);440 add_debug_source_node(g, block_node);
...@@ -466,22 +466,11 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro...@@ -466,22 +466,11 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro
466 return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0);466 return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0);
467}467}
468468
469void code_gen(CodeGen *g) {469static void do_code_gen(CodeGen *g) {
470 assert(!g->errors.length);470 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
481 g->block_scopes.append(LLVMZigCompileUnitToScope(g->compile_unit));472 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
486 // Generate function prototypes475 // Generate function prototypes
487 auto it = g->fn_table.entry_iterator();476 auto it = g->fn_table.entry_iterator();
...@@ -523,6 +512,7 @@ void code_gen(CodeGen *g) {...@@ -523,6 +512,7 @@ void code_gen(CodeGen *g) {
523 // Generate function definitions.512 // Generate function definitions.
524 for (int i = 0; i < g->fn_defs.length; i += 1) {513 for (int i = 0; i < g->fn_defs.length; i += 1) {
525 FnTableEntry *fn_table_entry = g->fn_defs.at(i);514 FnTableEntry *fn_table_entry = g->fn_defs.at(i);
515 ImportTableEntry *import = fn_table_entry->import_entry;
526 AstNode *fn_def_node = fn_table_entry->fn_def_node;516 AstNode *fn_def_node = fn_table_entry->fn_def_node;
527 LLVMValueRef fn = fn_table_entry->fn_value;517 LLVMValueRef fn = fn_table_entry->fn_value;
528 g->cur_fn = fn_table_entry;518 g->cur_fn = fn_table_entry;
...@@ -532,14 +522,15 @@ void code_gen(CodeGen *g) {...@@ -532,14 +522,15 @@ void code_gen(CodeGen *g) {
532 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;522 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
533523
534 // Add debug info.524 // Add debug info.
535 LLVMZigDIScope *fn_scope = LLVMZigFileToScope(g->di_file);525 LLVMZigDIScope *fn_scope = LLVMZigFileToScope(import->di_file);
536 unsigned line_number = fn_def_node->line + 1;526 unsigned line_number = fn_def_node->line + 1;
537 unsigned scope_line = line_number;527 unsigned scope_line = line_number;
538 bool is_definition = true;528 bool is_definition = true;
539 unsigned flags = 0;529 unsigned flags = 0;
530 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
540 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,531 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
541 fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number,532 fn_scope, buf_ptr(&fn_proto->name), "", import->di_file, line_number,
542 create_di_function_type(g, fn_proto, g->di_file), fn_table_entry->internal_linkage, 533 create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage,
543 is_definition, scope_line, flags, is_optimized, fn);534 is_definition, scope_line, flags, is_optimized, fn);
544535
545 g->block_scopes.append(LLVMZigSubprogramToScope(subprogram));536 g->block_scopes.append(LLVMZigSubprogramToScope(subprogram));
...@@ -555,7 +546,7 @@ void code_gen(CodeGen *g) {...@@ -555,7 +546,7 @@ void code_gen(CodeGen *g) {
555 LLVMGetParams(fn, codegen_fn_def->params);546 LLVMGetParams(fn, codegen_fn_def->params);
556547
557 bool add_implicit_return = codegen_fn_def->add_implicit_return;548 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
560 g->block_scopes.pop();551 g->block_scopes.pop();
561 }552 }
...@@ -563,7 +554,9 @@ void code_gen(CodeGen *g) {...@@ -563,7 +554,9 @@ void code_gen(CodeGen *g) {
563554
564 LLVMZigDIBuilderFinalize(g->dbuilder);555 LLVMZigDIBuilderFinalize(g->dbuilder);
565556
566 LLVMDumpModule(g->module);557 if (g->verbose) {
558 LLVMDumpModule(g->module);
559 }
567560
568 // in release mode, we're sooooo confident that we've generated correct ir,561 // in release mode, we're sooooo confident that we've generated correct ir,
569 // that we skip the verify module step in order to get better performance.562 // that we skip the verify module step in order to get better performance.
...@@ -573,13 +566,171 @@ void code_gen(CodeGen *g) {...@@ -573,13 +566,171 @@ void code_gen(CodeGen *g) {
573#endif566#endif
574}567}
575568
576void code_gen_optimize(CodeGen *g) {569static void define_primitive_types(CodeGen *g) {
577 LLVMZigOptimizeModule(g->target_machine, g->module);570 {
578 LLVMDumpModule(g->module);571 // if this type is anywhere in the AST, we should never hit codegen.
572 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
573 buf_init_from_str(&entry->name, "(invalid)");
574 g->builtin_types.entry_invalid = entry;
575 }
576 {
577 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
578 entry->type_ref = LLVMInt8Type();
579 buf_init_from_str(&entry->name, "u8");
580 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
581 LLVMZigEncoding_DW_ATE_unsigned());
582 g->type_table.put(&entry->name, entry);
583 g->builtin_types.entry_u8 = entry;
584 }
585 {
586 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
587 entry->type_ref = LLVMInt32Type();
588 buf_init_from_str(&entry->name, "i32");
589 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
590 LLVMZigEncoding_DW_ATE_signed());
591 g->type_table.put(&entry->name, entry);
592 g->builtin_types.entry_i32 = entry;
593 }
594 {
595 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
596 entry->type_ref = LLVMVoidType();
597 buf_init_from_str(&entry->name, "void");
598 entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
599 LLVMZigEncoding_DW_ATE_unsigned());
600 g->type_table.put(&entry->name, entry);
601 g->builtin_types.entry_void = entry;
602 }
603 {
604 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
605 entry->type_ref = LLVMVoidType();
606 buf_init_from_str(&entry->name, "unreachable");
607 entry->di_type = g->builtin_types.entry_void->di_type;
608 g->type_table.put(&entry->name, entry);
609 g->builtin_types.entry_unreachable = entry;
610 }
579}611}
580612
581ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {613
582 return &g->errors;614
615static void init(CodeGen *g, Buf *source_path) {
616 LLVMInitializeAllTargets();
617 LLVMInitializeAllTargetMCs();
618 LLVMInitializeAllAsmPrinters();
619 LLVMInitializeAllAsmParsers();
620 LLVMInitializeNativeTarget();
621
622 g->is_native_target = true;
623 char *native_triple = LLVMGetDefaultTargetTriple();
624
625 LLVMTargetRef target_ref;
626 char *err_msg = nullptr;
627 if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
628 zig_panic("unable to get target from triple: %s", err_msg);
629 }
630
631 char *native_cpu = LLVMZigGetHostCPUName();
632 char *native_features = LLVMZigGetNativeFeatures();
633
634 LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
635 LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
636
637 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
638
639 g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
640 native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
641
642 g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
643
644
645 g->module = LLVMModuleCreateWithName("ZigModule");
646
647 g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
648
649 g->builder = LLVMCreateBuilder();
650 g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
651
652
653 define_primitive_types(g);
654
655 Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
656 bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
657 const char *flags = "";
658 unsigned runtime_version = 0;
659 g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
660 buf_ptr(source_path), buf_ptr(g->root_source_dir),
661 buf_ptr(producer), is_optimized, flags, runtime_version,
662 "", 0, !g->strip_debug_symbols);
663
664
665}
666
667void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) {
668 if (!g->initialized) {
669 g->initialized = true;
670 init(g, source_path);
671 }
672
673 Buf full_path = BUF_INIT;
674 os_path_join(g->root_source_dir, source_path, &full_path);
675
676 Buf dirname = BUF_INIT;
677 Buf basename = BUF_INIT;
678 os_path_split(&full_path, &dirname, &basename);
679
680 if (g->verbose) {
681 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(source_path));
682 fprintf(stderr, "----------------\n");
683 fprintf(stderr, "%s\n", buf_ptr(source_code));
684
685 fprintf(stderr, "\nTokens:\n");
686 fprintf(stderr, "---------\n");
687 }
688
689 ZigList<Token> *tokens = tokenize(source_code);
690
691 if (g->verbose) {
692 print_tokens(source_code, tokens);
693
694 fprintf(stderr, "\nAST:\n");
695 fprintf(stderr, "------\n");
696 }
697
698 ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
699 import_entry->root = ast_parse(source_code, tokens);
700 assert(import_entry->root);
701 if (g->verbose) {
702 ast_print(import_entry->root, 0);
703
704 fprintf(stderr, "\nSemantic Analysis:\n");
705 fprintf(stderr, "--------------------\n");
706 }
707
708 import_entry->path = source_path;
709 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname));
710 g->import_table.put(source_path, import_entry);
711
712 semantic_analyze(g, import_entry);
713
714 if (g->errors.length == 0) {
715 if (g->verbose) {
716 fprintf(stderr, "OK\n");
717 }
718 } else {
719 for (int i = 0; i < g->errors.length; i += 1) {
720 ErrorMsg *err = &g->errors.at(i);
721 fprintf(stderr, "Error: Line %d, column %d: %s\n",
722 err->line_start + 1, err->column_start + 1,
723 buf_ptr(err->msg));
724 }
725 exit(1);
726 }
727
728 if (g->verbose) {
729 fprintf(stderr, "\nCode Generation:\n");
730 fprintf(stderr, "------------------\n");
731 }
732
733 do_code_gen(g);
583}734}
584735
585static Buf *to_c_type(CodeGen *g, AstNode *type_node) {736static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
...@@ -601,15 +752,15 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {...@@ -601,15 +752,15 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
601}752}
602753
603static void generate_h_file(CodeGen *g) {754static void generate_h_file(CodeGen *g) {
604 Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->out_name));755 Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
605 FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");756 FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");
606 if (!out_h)757 if (!out_h)
607 zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));758 zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));
608759
609 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->out_name));760 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));
610 buf_upcase(export_macro);761 buf_upcase(export_macro);
611762
612 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->out_name));763 Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
613 buf_upcase(extern_c_macro);764 buf_upcase(extern_c_macro);
614765
615 Buf h_buf = BUF_INIT;766 Buf h_buf = BUF_INIT;
...@@ -644,7 +795,8 @@ static void generate_h_file(CodeGen *g) {...@@ -644,7 +795,8 @@ static void generate_h_file(CodeGen *g) {
644 }795 }
645 }796 }
646797
647 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H", buf_ptr(g->out_name), buf_ptr(g->out_name));798 Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
799 buf_ptr(g->root_out_name), buf_ptr(g->root_out_name));
648 buf_upcase(ifdef_dance_name);800 buf_upcase(ifdef_dance_name);
649801
650 fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));802 fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
...@@ -677,9 +829,27 @@ static void generate_h_file(CodeGen *g) {...@@ -677,9 +829,27 @@ static void generate_h_file(CodeGen *g) {
677 zig_panic("unable to close h file: %s", strerror(errno));829 zig_panic("unable to close h file: %s", strerror(errno));
678}830}
679831
680void code_gen_link(CodeGen *g, const char *out_file) {832void codegen_link(CodeGen *g, const char *out_file) {
833 bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
834 if (is_optimized) {
835 if (g->verbose) {
836 fprintf(stderr, "\nOptimization:\n");
837 fprintf(stderr, "---------------\n");
838 }
839
840 LLVMZigOptimizeModule(g->target_machine, g->module);
841
842 if (g->verbose) {
843 LLVMDumpModule(g->module);
844 }
845 }
846 if (g->verbose) {
847 fprintf(stderr, "\nLink:\n");
848 fprintf(stderr, "-------\n");
849 }
850
681 if (!out_file) {851 if (!out_file) {
682 out_file = buf_ptr(g->out_name);852 out_file = buf_ptr(g->root_out_name);
683 }853 }
684854
685 Buf out_file_o = BUF_INIT;855 Buf out_file_o = BUF_INIT;
...@@ -728,8 +898,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {...@@ -728,8 +898,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
728898
729 if (g->out_type == OutTypeLib) {899 if (g->out_type == OutTypeLib) {
730 Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d",900 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);901 buf_ptr(g->root_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);902 Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
733 args.append("-shared");903 args.append("-shared");
734 args.append("-soname");904 args.append("-soname");
735 args.append(buf_ptr(soname));905 args.append(buf_ptr(soname));
...@@ -756,4 +926,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {...@@ -756,4 +926,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
756 if (g->out_type == OutTypeLib) {926 if (g->out_type == OutTypeLib) {
757 generate_h_file(g);927 generate_h_file(g);
758 }928 }
929
930 if (g->verbose) {
931 fprintf(stderr, "OK\n");
932 }
759}933}
src/codegen.hpp+4-7
...@@ -29,7 +29,7 @@ struct ErrorMsg {...@@ -29,7 +29,7 @@ struct ErrorMsg {
29};29};
3030
3131
32CodeGen *create_codegen(AstNode *root, Buf *in_file);32CodeGen *codegen_create(Buf *root_source_dir);
3333
34enum CodeGenBuildType {34enum CodeGenBuildType {
35 CodeGenBuildTypeDebug,35 CodeGenBuildTypeDebug,
...@@ -38,15 +38,12 @@ enum CodeGenBuildType {...@@ -38,15 +38,12 @@ enum CodeGenBuildType {
38void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);38void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);
39void codegen_set_is_static(CodeGen *codegen, bool is_static);39void codegen_set_is_static(CodeGen *codegen, bool is_static);
40void codegen_set_strip(CodeGen *codegen, bool strip);40void codegen_set_strip(CodeGen *codegen, bool strip);
41void codegen_set_verbose(CodeGen *codegen, bool verbose);
41void codegen_set_out_type(CodeGen *codegen, OutType out_type);42void codegen_set_out_type(CodeGen *codegen, OutType out_type);
42void codegen_set_out_name(CodeGen *codegen, Buf *out_name);43void 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);47void codegen_link(CodeGen *g, const char *out_file);
47
48void code_gen_link(CodeGen *g, const char *out_file);
49
50ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g);
5148
52#endif49#endif
src/error.cpp+1
...@@ -5,6 +5,7 @@ const char *err_str(int err) {...@@ -5,6 +5,7 @@ const char *err_str(int err) {
5 case ErrorNone: return "(no error)";5 case ErrorNone: return "(no error)";
6 case ErrorNoMem: return "out of memory";6 case ErrorNoMem: return "out of memory";
7 case ErrorInvalidFormat: return "invalid format";7 case ErrorInvalidFormat: return "invalid format";
8 case ErrorSemanticAnalyzeFail: return "semantic analyze failed";
8 }9 }
9 return "(invalid error)";10 return "(invalid error)";
10}11}
src/error.hpp+1
...@@ -12,6 +12,7 @@ enum Error {...@@ -12,6 +12,7 @@ enum Error {
12 ErrorNone,12 ErrorNone,
13 ErrorNoMem,13 ErrorNoMem,
14 ErrorInvalidFormat,14 ErrorInvalidFormat,
15 ErrorSemanticAnalyzeFail,
15};16};
1617
17const char *err_str(int err);18const char *err_str(int err);
src/main.cpp+51-119
...@@ -6,25 +6,11 @@...@@ -6,25 +6,11 @@
6 */6 */
77
8#include "config.h"8#include "config.h"
9#include "util.hpp"
10#include "list.hpp"
11#include "buffer.hpp"9#include "buffer.hpp"
12#include "parser.hpp"
13#include "tokenizer.hpp"
14#include "error.hpp"
15#include "codegen.hpp"10#include "codegen.hpp"
16#include "analyze.hpp"11#include "os.hpp"
1712
18#include <stdio.h>13#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
29static int usage(const char *arg0) {15static int usage(const char *arg0) {
30 fprintf(stderr, "Usage: %s [command] [options] target\n"16 fprintf(stderr, "Usage: %s [command] [options] target\n"
...@@ -38,6 +24,7 @@ static int usage(const char *arg0) {...@@ -38,6 +24,7 @@ static int usage(const char *arg0) {
38 " --export [exe|lib|obj] override output type\n"24 " --export [exe|lib|obj] override output type\n"
39 " --name [name] override output name\n"25 " --name [name] override output name\n"
40 " --output [file] override destination path\n"26 " --output [file] override destination path\n"
27 " --verbose turn on compiler debug output\n"
41 , arg0);28 , arg0);
42 return EXIT_FAILURE;29 return EXIT_FAILURE;
43}30}
...@@ -47,98 +34,47 @@ static int version(void) {...@@ -47,98 +34,47 @@ static int version(void) {
47 return EXIT_SUCCESS;34 return EXIT_SUCCESS;
48}35}
4936
50static Buf *fetch_file(FILE *f) {37struct Build {
51 int fd = fileno(f);38 const char *in_file;
52 struct stat st;39 const char *out_file;
53 if (fstat(fd, &st))40 bool release;
54 zig_panic("unable to stat file: %s", strerror(errno));41 bool strip;
55 off_t big_size = st.st_size;42 bool is_static;
56 if (big_size > INT_MAX)43 OutType out_type;
57 zig_panic("file too big");44 const char *out_name;
58 int size = (int)big_size;45 bool verbose;
5946};
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];
7247
73 if (!in_file)48static int build(const char *arg0, Build *b) {
49 if (!b->in_file)
74 return usage(arg0);50 return usage(arg0);
7551
76 FILE *in_f;52 Buf in_file_buf = BUF_INIT;
77 if (strcmp(in_file, "-") == 0) {53 buf_init_from_str(&in_file_buf, b->in_file);
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 }
8754
88 fprintf(stderr, "Original source:\n");55 Buf root_source_dir = BUF_INIT;
89 fprintf(stderr, "----------------\n");56 Buf root_source_code = BUF_INIT;
90 Buf *in_data = fetch_file(in_f);57 Buf root_source_name = BUF_INIT;
91 fprintf(stderr, "%s\n", buf_ptr(in_data));58 if (buf_eql_str(&in_file_buf, "-")) {
9259 os_get_cwd(&root_source_dir);
93 fprintf(stderr, "\nTokens:\n");60 os_fetch_file(stdin, &root_source_code);
94 fprintf(stderr, "---------\n");61 buf_init_from_str(&root_source_name, "");
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");
118 } else {62 } else {
119 for (int i = 0; i < errors->length; i += 1) {63 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
120 ErrorMsg *err = &errors->at(i);64 os_fetch_file_path(buf_create_from_str(b->in_file), &root_source_code);
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;
126 }65 }
12766
128 fprintf(stderr, "\nCode Generation:\n");67 CodeGen *g = codegen_create(&root_source_dir);
129 fprintf(stderr, "------------------\n");68 codegen_set_build_type(g, b->release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
130 code_gen(codegen);69 codegen_set_strip(g, b->strip);
13170 codegen_set_is_static(g, b->is_static);
132 if (release) {71 if (b->out_type != OutTypeUnknown)
133 fprintf(stderr, "\nOptimization:\n");72 codegen_set_out_type(g, b->out_type);
134 fprintf(stderr, "---------------\n");73 if (b->out_name)
135 code_gen_optimize(codegen);74 codegen_set_out_name(g, buf_create_from_str(b->out_name));
136 }75 codegen_set_verbose(g, b->verbose);
13776 codegen_add_code(g, &root_source_name, &root_source_code);
138 fprintf(stderr, "\nLink:\n");77 codegen_link(g, b->out_file);
139 fprintf(stderr, "-------\n");
140 code_gen_link(codegen, out_file);
141 fprintf(stderr, "OK\n");
14278
143 return 0;79 return 0;
144}80}
...@@ -151,43 +87,39 @@ enum Cmd {...@@ -151,43 +87,39 @@ enum Cmd {
15187
152int main(int argc, char **argv) {88int main(int argc, char **argv) {
153 char *arg0 = argv[0];89 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};
163 Cmd cmd = CmdNone;92 Cmd cmd = CmdNone;
93
164 for (int i = 1; i < argc; i += 1) {94 for (int i = 1; i < argc; i += 1) {
165 char *arg = argv[i];95 char *arg = argv[i];
166 if (arg[0] == '-' && arg[1] == '-') {96 if (arg[0] == '-' && arg[1] == '-') {
167 if (strcmp(arg, "--release") == 0) {97 if (strcmp(arg, "--release") == 0) {
168 release = true;98 b.release = true;
169 } else if (strcmp(arg, "--strip") == 0) {99 } else if (strcmp(arg, "--strip") == 0) {
170 strip = true;100 b.strip = true;
171 } else if (strcmp(arg, "--static") == 0) {101 } 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;
173 } else if (i + 1 >= argc) {105 } else if (i + 1 >= argc) {
174 return usage(arg0);106 return usage(arg0);
175 } else {107 } else {
176 i += 1;108 i += 1;
177 if (strcmp(arg, "--output") == 0) {109 if (strcmp(arg, "--output") == 0) {
178 out_file = argv[i];110 b.out_file = argv[i];
179 } else if (strcmp(arg, "--export") == 0) {111 } else if (strcmp(arg, "--export") == 0) {
180 if (strcmp(argv[i], "exe") == 0) {112 if (strcmp(argv[i], "exe") == 0) {
181 out_type = OutTypeExe;113 b.out_type = OutTypeExe;
182 } else if (strcmp(argv[i], "lib") == 0) {114 } else if (strcmp(argv[i], "lib") == 0) {
183 out_type = OutTypeLib;115 b.out_type = OutTypeLib;
184 } else if (strcmp(argv[i], "obj") == 0) {116 } else if (strcmp(argv[i], "obj") == 0) {
185 out_type = OutTypeObj;117 b.out_type = OutTypeObj;
186 } else {118 } else {
187 return usage(arg0);119 return usage(arg0);
188 }120 }
189 } else if (strcmp(arg, "--name") == 0) {121 } else if (strcmp(arg, "--name") == 0) {
190 out_name = argv[i];122 b.out_name = argv[i];
191 } else {123 } else {
192 return usage(arg0);124 return usage(arg0);
193 }125 }
...@@ -206,8 +138,8 @@ int main(int argc, char **argv) {...@@ -206,8 +138,8 @@ int main(int argc, char **argv) {
206 case CmdNone:138 case CmdNone:
207 zig_unreachable();139 zig_unreachable();
208 case CmdBuild:140 case CmdBuild:
209 if (!in_file) {141 if (!b.in_file) {
210 in_file = arg;142 b.in_file = arg;
211 } else {143 } else {
212 return usage(arg0);144 return usage(arg0);
213 }145 }
...@@ -222,7 +154,7 @@ int main(int argc, char **argv) {...@@ -222,7 +154,7 @@ int main(int argc, char **argv) {
222 case CmdNone:154 case CmdNone:
223 return usage(arg0);155 return usage(arg0);
224 case CmdBuild:156 case CmdBuild:
225 return build(arg0, in_file, out_file, release, strip, is_static, out_type, out_name);157 return build(arg0, &b);
226 case CmdVersion:158 case CmdVersion:
227 return version();159 return version();
228 }160 }
src/os.cpp+51-4
...@@ -13,8 +13,8 @@...@@ -13,8 +13,8 @@
13#include <sys/types.h>13#include <sys/types.h>
14#include <sys/stat.h>14#include <sys/stat.h>
15#include <sys/wait.h>15#include <sys/wait.h>
16#include <stdio.h>
17#include <fcntl.h>16#include <fcntl.h>
17#include <limits.h>
1818
19void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached) {19void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached) {
20 pid_t pid = fork();20 pid_t pid = fork();
...@@ -37,7 +37,7 @@ void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detache...@@ -37,7 +37,7 @@ void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detache
37 zig_panic("execvp failed: %s", strerror(errno));37 zig_panic("execvp failed: %s", strerror(errno));
38}38}
3939
40static void read_all_fd(int fd, Buf *out_buf) {40static void read_all_fd_stream(int fd, Buf *out_buf) {
41 static const ssize_t buf_size = 0x2000;41 static const ssize_t buf_size = 0x2000;
42 buf_resize(out_buf, buf_size);42 buf_resize(out_buf, buf_size);
43 ssize_t actual_buf_len = 0;43 ssize_t actual_buf_len = 0;
...@@ -72,6 +72,12 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {...@@ -72,6 +72,12 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
72 buf_init_from_buf(out_basename, full_path);72 buf_init_from_buf(out_basename, full_path);
73}73}
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
75void os_exec_process(const char *exe, ZigList<const char *> &args,81void os_exec_process(const char *exe, ZigList<const char *> &args,
76 int *return_code, Buf *out_stderr, Buf *out_stdout)82 int *return_code, Buf *out_stderr, Buf *out_stdout)
77{83{
...@@ -117,8 +123,8 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,...@@ -117,8 +123,8 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,
117123
118 waitpid(pid, return_code, 0);124 waitpid(pid, return_code, 0);
119125
120 read_all_fd(stdout_pipe[0], out_stdout);126 read_all_fd_stream(stdout_pipe[0], out_stdout);
121 read_all_fd(stderr_pipe[0], out_stderr);127 read_all_fd_stream(stderr_pipe[0], out_stderr);
122128
123 }129 }
124}130}
...@@ -133,3 +139,44 @@ void os_write_file(Buf *full_path, Buf *contents) {...@@ -133,3 +139,44 @@ void os_write_file(Buf *full_path, Buf *contents) {
133 if (close(fd) == -1)139 if (close(fd) == -1)
134 zig_panic("close failed");140 zig_panic("close failed");
135}141}
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 @@...@@ -11,13 +11,22 @@
11#include "list.hpp"11#include "list.hpp"
12#include "buffer.hpp"12#include "buffer.hpp"
1313
14#include <stdio.h>
15
14void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached);16void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached);
15void os_exec_process(const char *exe, ZigList<const char *> &args,17void os_exec_process(const char *exe, ZigList<const char *> &args,
16 int *return_code, Buf *out_stderr, Buf *out_stdout);18 int *return_code, Buf *out_stderr, Buf *out_stdout);
1719
18void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);20void 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
20void os_write_file(Buf *full_path, Buf *contents);23void 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
23#endif32#endif
src/parser.cpp+41-1
...@@ -100,6 +100,8 @@ const char *node_type_str(NodeType node_type) {...@@ -100,6 +100,8 @@ const char *node_type_str(NodeType node_type) {
100 return "Symbol";100 return "Symbol";
101 case NodeTypePrefixOpExpr:101 case NodeTypePrefixOpExpr:
102 return "PrefixOpExpr";102 return "PrefixOpExpr";
103 case NodeTypeUse:
104 return "Use";
103 }105 }
104 zig_unreachable();106 zig_unreachable();
105}107}
...@@ -241,6 +243,9 @@ void ast_print(AstNode *node, int indent) {...@@ -241,6 +243,9 @@ void ast_print(AstNode *node, int indent) {
241 fprintf(stderr, "PrimaryExpr Symbol %s\n",243 fprintf(stderr, "PrimaryExpr Symbol %s\n",
242 buf_ptr(&node->data.symbol));244 buf_ptr(&node->data.symbol));
243 break;245 break;
246 case NodeTypeUse:
247 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
248 break;
244 }249 }
245}250}
246251
...@@ -1231,7 +1236,36 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b...@@ -1231,7 +1236,36 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
1231}1236}
12321237
1233/*1238/*
1234TopLevelDecl : FnDef | ExternBlock | RootExportDecl1239Use : 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
1235*/1269*/
1236static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {1270static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
1237 for (;;) {1271 for (;;) {
...@@ -1258,6 +1292,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis...@@ -1258,6 +1292,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
1258 continue;1292 continue;
1259 }1293 }
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
1261 if (pc->directive_list->length > 0) {1301 if (pc->directive_list->length > 0) {
1262 ast_error(directive_token, "invalid directive");1302 ast_error(directive_token, "invalid directive");
1263 }1303 }
src/parser.hpp+7
...@@ -35,6 +35,7 @@ enum NodeType {...@@ -35,6 +35,7 @@ enum NodeType {
35 NodeTypeSymbol,35 NodeTypeSymbol,
36 NodeTypePrefixOpExpr,36 NodeTypePrefixOpExpr,
37 NodeTypeFnCallExpr,37 NodeTypeFnCallExpr,
38 NodeTypeUse,
38};39};
3940
40struct AstNodeRoot {41struct AstNodeRoot {
...@@ -158,6 +159,11 @@ struct AstNodePrefixOpExpr {...@@ -158,6 +159,11 @@ struct AstNodePrefixOpExpr {
158 AstNode *primary_expr;159 AstNode *primary_expr;
159};160};
160161
162struct AstNodeUse {
163 Buf path;
164 ZigList<AstNode *> *directives;
165};
166
161struct AstNode {167struct AstNode {
162 enum NodeType type;168 enum NodeType type;
163 AstNode *parent;169 AstNode *parent;
...@@ -180,6 +186,7 @@ struct AstNode {...@@ -180,6 +186,7 @@ struct AstNode {
180 AstNodeCastExpr cast_expr;186 AstNodeCastExpr cast_expr;
181 AstNodePrefixOpExpr prefix_op_expr;187 AstNodePrefixOpExpr prefix_op_expr;
182 AstNodeFnCallExpr fn_call_expr;188 AstNodeFnCallExpr fn_call_expr;
189 AstNodeUse use;
183 Buf number;190 Buf number;
184 Buf string;191 Buf string;
185 Buf symbol;192 Buf symbol;
src/semantic_info.hpp+23-14
...@@ -12,15 +12,6 @@...@@ -12,15 +12,6 @@
12#include "hash_map.hpp"12#include "hash_map.hpp"
13#include "zig_llvm.hpp"13#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
24struct TypeTableEntry {15struct TypeTableEntry {
25 LLVMTypeRef type_ref;16 LLVMTypeRef type_ref;
26 LLVMZigDIType *di_type;17 LLVMZigDIType *di_type;
...@@ -33,17 +24,35 @@ struct TypeTableEntry {...@@ -33,17 +24,35 @@ struct TypeTableEntry {
33 TypeTableEntry *pointer_mut_parent;24 TypeTableEntry *pointer_mut_parent;
34};25};
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
36struct CodeGen {43struct CodeGen {
37 LLVMModuleRef module;44 LLVMModuleRef module;
38 AstNode *root;
39 ZigList<ErrorMsg> errors;45 ZigList<ErrorMsg> errors;
40 LLVMBuilderRef builder;46 LLVMBuilderRef builder;
41 LLVMZigDIBuilder *dbuilder;47 LLVMZigDIBuilder *dbuilder;
42 LLVMZigDICompileUnit *compile_unit;48 LLVMZigDICompileUnit *compile_unit;
49
50 // reminder: hash tables must be initialized before use
43 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;51 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
44 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;52 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
45 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;53 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
46 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;54 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
55 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
4756
48 struct {57 struct {
49 TypeTableEntry *entry_u8;58 TypeTableEntry *entry_u8;
...@@ -60,12 +69,10 @@ struct CodeGen {...@@ -60,12 +69,10 @@ struct CodeGen {
60 CodeGenBuildType build_type;69 CodeGenBuildType build_type;
61 LLVMTargetMachineRef target_machine;70 LLVMTargetMachineRef target_machine;
62 bool is_native_target;71 bool is_native_target;
63 Buf in_file;72 Buf *root_source_dir;
64 Buf in_dir;73 Buf *root_out_name;
65 ZigList<LLVMZigDIScope *> block_scopes;74 ZigList<LLVMZigDIScope *> block_scopes;
66 LLVMZigDIFile *di_file;
67 ZigList<FnTableEntry *> fn_defs;75 ZigList<FnTableEntry *> fn_defs;
68 Buf *out_name;
69 OutType out_type;76 OutType out_type;
70 FnTableEntry *cur_fn;77 FnTableEntry *cur_fn;
71 bool c_stdint_used;78 bool c_stdint_used;
...@@ -73,6 +80,8 @@ struct CodeGen {...@@ -73,6 +80,8 @@ struct CodeGen {
73 int version_major;80 int version_major;
74 int version_minor;81 int version_minor;
75 int version_patch;82 int version_patch;
83 bool verbose;
84 bool initialized;
76};85};
7786
78struct TypeNode {87struct TypeNode {
src/tokenizer.cpp+3
...@@ -180,6 +180,8 @@ static void end_token(Tokenize *t) {...@@ -180,6 +180,8 @@ static void end_token(Tokenize *t) {
180 t->cur_tok->id = TokenIdKeywordExport;180 t->cur_tok->id = TokenIdKeywordExport;
181 } else if (mem_eql_str(token_mem, token_len, "as")) {181 } else if (mem_eql_str(token_mem, token_len, "as")) {
182 t->cur_tok->id = TokenIdKeywordAs;182 t->cur_tok->id = TokenIdKeywordAs;
183 } else if (mem_eql_str(token_mem, token_len, "use")) {
184 t->cur_tok->id = TokenIdKeywordUse;
183 }185 }
184186
185 t->cur_tok = nullptr;187 t->cur_tok = nullptr;
...@@ -562,6 +564,7 @@ static const char * token_name(Token *token) {...@@ -562,6 +564,7 @@ static const char * token_name(Token *token) {
562 case TokenIdKeywordPub: return "Pub";564 case TokenIdKeywordPub: return "Pub";
563 case TokenIdKeywordExport: return "Export";565 case TokenIdKeywordExport: return "Export";
564 case TokenIdKeywordAs: return "As";566 case TokenIdKeywordAs: return "As";
567 case TokenIdKeywordUse: return "Use";
565 case TokenIdLParen: return "LParen";568 case TokenIdLParen: return "LParen";
566 case TokenIdRParen: return "RParen";569 case TokenIdRParen: return "RParen";
567 case TokenIdComma: return "Comma";570 case TokenIdComma: return "Comma";
src/tokenizer.hpp+1
...@@ -22,6 +22,7 @@ enum TokenId {...@@ -22,6 +22,7 @@ enum TokenId {
22 TokenIdKeywordPub,22 TokenIdKeywordPub,
23 TokenIdKeywordExport,23 TokenIdKeywordExport,
24 TokenIdKeywordAs,24 TokenIdKeywordAs,
25 TokenIdKeywordUse,
25 TokenIdLParen,26 TokenIdLParen,
26 TokenIdRParen,27 TokenIdRParen,
27 TokenIdComma,28 TokenIdComma,
test/run_tests.cpp+2
...@@ -47,6 +47,7 @@ static void add_simple_case(const char *case_name, const char *source, const cha...@@ -47,6 +47,7 @@ static void add_simple_case(const char *case_name, const char *source, const cha
47 test_case->compiler_args.append(tmp_exe_path);47 test_case->compiler_args.append(tmp_exe_path);
48 test_case->compiler_args.append("--release");48 test_case->compiler_args.append("--release");
49 test_case->compiler_args.append("--strip");49 test_case->compiler_args.append("--strip");
50 test_case->compiler_args.append("--verbose");
5051
51 test_cases.append(test_case);52 test_cases.append(test_case);
52}53}
...@@ -70,6 +71,7 @@ static void add_compile_fail_case(const char *case_name, const char *source, int...@@ -70,6 +71,7 @@ static void add_compile_fail_case(const char *case_name, const char *source, int
70 test_case->compiler_args.append(tmp_exe_path);71 test_case->compiler_args.append(tmp_exe_path);
71 test_case->compiler_args.append("--release");72 test_case->compiler_args.append("--release");
72 test_case->compiler_args.append("--strip");73 test_case->compiler_args.append("--strip");
74 test_case->compiler_args.append("--verbose");
7375
74 test_cases.append(test_case);76 test_cases.append(test_case);
7577