aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJosh Wolfe <thejoshwolfe@gmail.com>2015-11-30 22:12:21 -0700
committerJosh Wolfe <thejoshwolfe@gmail.com>2015-11-30 22:12:21 -0700
commit00f4c05784c05552e1e379b98c09161c936cfb31 (patch)
tree5b2234cae585c5ac3a2cb23503908b0a6e2a27e3 /src
parentabbc3957019c3a12dacd54869ff18b91c3f07699 (diff)
parent55b8472374eede496b59396dbe253b05b16063e1 (diff)
downloadzig-00f4c05784c05552e1e379b98c09161c936cfb31.tar.gz
zig-00f4c05784c05552e1e379b98c09161c936cfb31.zip
merge conflicts
Diffstat (limited to 'src')
-rw-r--r--src/analyze.cpp177
-rw-r--r--src/analyze.hpp3
-rw-r--r--src/codegen.cpp258
-rw-r--r--src/codegen.hpp11
-rw-r--r--src/error.cpp1
-rw-r--r--src/error.hpp1
-rw-r--r--src/main.cpp170
-rw-r--r--src/os.cpp55
-rw-r--r--src/os.hpp9
-rw-r--r--src/parser.cpp42
-rw-r--r--src/parser.hpp7
-rw-r--r--src/semantic_info.hpp37
-rw-r--r--src/tokenizer.cpp3
-rw-r--r--src/tokenizer.hpp1
14 files changed, 494 insertions, 281 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 7e02b1eb89..2d88389dab 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -119,7 +119,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node) {
resolve_type(g, node->data.fn_proto.return_type);
}
-static void preview_function_declarations(CodeGen *g, AstNode *node) {
+static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, AstNode *node) {
switch (node->type) {
case NodeTypeExternBlock:
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) {
fn_table_entry->proto_node = fn_proto;
fn_table_entry->is_extern = true;
fn_table_entry->calling_convention = LLVMCCallConv;
+ fn_table_entry->import_entry = import;
g->fn_table.put(name, fn_table_entry);
}
break;
@@ -162,6 +163,7 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
node->codegen_node->data.fn_def_node.skip = true;
} else {
FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
+ fn_table_entry->import_entry = import;
fn_table_entry->proto_node = proto_node;
fn_table_entry->fn_def_node = node;
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) {
} else {
g->root_export_decl = node;
- if (!g->out_name)
- g->out_name = &node->data.root_export_decl.name;
+ if (!g->root_out_name)
+ g->root_out_name = &node->data.root_export_decl.name;
Buf *out_type = &node->data.root_export_decl.type;
OutType export_out_type;
@@ -215,6 +217,9 @@ static void preview_function_declarations(CodeGen *g, AstNode *node) {
g->out_type = export_out_type;
}
break;
+ case NodeTypeUse:
+ zig_panic("TODO use");
+ break;
case NodeTypeDirective:
case NodeTypeParamDecl:
case NodeTypeFnProto:
@@ -379,6 +384,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, BlockContext *context, Ty
case NodeTypeRootExportDecl:
case NodeTypeExternBlock:
case NodeTypeFnDef:
+ case NodeTypeUse:
zig_unreachable();
}
zig_unreachable();
@@ -437,6 +443,75 @@ static void check_fn_def_control_flow(CodeGen *g, AstNode *node) {
}
}
+static void analyze_expression(CodeGen *g, AstNode *node) {
+ switch (node->type) {
+ case NodeTypeBlock:
+ for (int i = 0; i < node->data.block.statements.length; i += 1) {
+ AstNode *child = node->data.block.statements.at(i);
+ analyze_expression(g, child);
+ }
+ break;
+ case NodeTypeReturnExpr:
+ if (node->data.return_expr.expr) {
+ analyze_expression(g, node->data.return_expr.expr);
+ }
+ break;
+ case NodeTypeBinOpExpr:
+ analyze_expression(g, node->data.bin_op_expr.op1);
+ analyze_expression(g, node->data.bin_op_expr.op2);
+ break;
+ case NodeTypeFnCallExpr:
+ {
+ Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
+
+ auto entry = g->fn_table.maybe_get(name);
+ if (!entry) {
+ add_node_error(g, node,
+ buf_sprintf("undefined function: '%s'", buf_ptr(name)));
+ } else {
+ FnTableEntry *fn_table_entry = entry->value;
+ assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
+ int expected_param_count = fn_table_entry->proto_node->data.fn_proto.params.length;
+ int actual_param_count = node->data.fn_call_expr.params.length;
+ if (expected_param_count != actual_param_count) {
+ add_node_error(g, node,
+ buf_sprintf("wrong number of arguments. Expected %d, got %d.",
+ expected_param_count, actual_param_count));
+ }
+ }
+
+ for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
+ AstNode *child = node->data.fn_call_expr.params.at(i);
+ analyze_expression(g, child);
+ }
+ break;
+ }
+ case NodeTypeCastExpr:
+ zig_panic("TODO");
+ break;
+ case NodeTypePrefixOpExpr:
+ zig_panic("TODO");
+ break;
+ case NodeTypeNumberLiteral:
+ case NodeTypeStringLiteral:
+ case NodeTypeUnreachable:
+ case NodeTypeSymbol:
+ // nothing to do
+ break;
+ case NodeTypeDirective:
+ case NodeTypeFnDecl:
+ case NodeTypeFnProto:
+ case NodeTypeParamDecl:
+ case NodeTypeType:
+ case NodeTypeRoot:
+ case NodeTypeRootExportDecl:
+ case NodeTypeExternBlock:
+ case NodeTypeFnDef:
+ case NodeTypeUse:
+ zig_unreachable();
+ }
+}
+
static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
switch (node->type) {
case NodeTypeFnDef:
@@ -470,9 +545,9 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
case NodeTypeRootExportDecl:
case NodeTypeExternBlock:
+ case NodeTypeUse:
// already looked at these in the preview pass
break;
-
case NodeTypeDirective:
case NodeTypeParamDecl:
case NodeTypeFnProto:
@@ -493,13 +568,13 @@ static void analyze_top_level_declaration(CodeGen *g, AstNode *node) {
}
}
-static void analyze_root(CodeGen *g, AstNode *node) {
+static void analyze_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
assert(node->type == NodeTypeRoot);
// find function declarations
for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
AstNode *child = node->data.root.top_level_decls.at(i);
- preview_function_declarations(g, child);
+ preview_function_declarations(g, import, child);
}
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) {
analyze_top_level_declaration(g, child);
}
- if (!g->out_name) {
+ if (!g->root_out_name) {
add_node_error(g, node,
buf_sprintf("missing export declaration and output name not provided"));
} else if (g->out_type == OutTypeUnknown) {
@@ -516,91 +591,7 @@ static void analyze_root(CodeGen *g, AstNode *node) {
}
}
-static void define_primitive_types(CodeGen *g) {
- {
- // if this type is anywhere in the AST, we should never hit codegen.
- TypeTableEntry *entry = allocate<TypeTableEntry>(1);
- buf_init_from_str(&entry->name, "(invalid)");
- g->builtin_types.entry_invalid = entry;
- }
- {
- TypeTableEntry *entry = allocate<TypeTableEntry>(1);
- entry->type_ref = LLVMInt8Type();
- buf_init_from_str(&entry->name, "u8");
- entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
- LLVMZigEncoding_DW_ATE_unsigned());
- g->type_table.put(&entry->name, entry);
- g->builtin_types.entry_u8 = entry;
- }
- {
- TypeTableEntry *entry = allocate<TypeTableEntry>(1);
- entry->type_ref = LLVMInt32Type();
- buf_init_from_str(&entry->name, "i32");
- entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
- LLVMZigEncoding_DW_ATE_signed());
- g->type_table.put(&entry->name, entry);
- g->builtin_types.entry_i32 = entry;
- }
- {
- TypeTableEntry *entry = allocate<TypeTableEntry>(1);
- entry->type_ref = LLVMVoidType();
- buf_init_from_str(&entry->name, "void");
- entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
- LLVMZigEncoding_DW_ATE_unsigned());
- g->type_table.put(&entry->name, entry);
- g->builtin_types.entry_void = entry;
- }
- {
- TypeTableEntry *entry = allocate<TypeTableEntry>(1);
- entry->type_ref = LLVMVoidType();
- buf_init_from_str(&entry->name, "unreachable");
- entry->di_type = g->builtin_types.entry_void->di_type;
- g->type_table.put(&entry->name, entry);
- g->builtin_types.entry_unreachable = entry;
- }
-}
-
-
-void semantic_analyze(CodeGen *g) {
- LLVMInitializeAllTargets();
- LLVMInitializeAllTargetMCs();
- LLVMInitializeAllAsmPrinters();
- LLVMInitializeAllAsmParsers();
- LLVMInitializeNativeTarget();
-
- g->is_native_target = true;
- char *native_triple = LLVMGetDefaultTargetTriple();
-
- LLVMTargetRef target_ref;
- char *err_msg = nullptr;
- if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
- zig_panic("unable to get target from triple: %s", err_msg);
- }
-
- char *native_cpu = LLVMZigGetHostCPUName();
- char *native_features = LLVMZigGetNativeFeatures();
-
- LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
- LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
-
- LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
-
- g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
- native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
-
- g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
-
-
- g->module = LLVMModuleCreateWithName("ZigModule");
-
- g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
-
- g->builder = LLVMCreateBuilder();
- g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
-
-
- define_primitive_types(g);
-
- analyze_root(g, g->root);
+void semantic_analyze(CodeGen *g, ImportTableEntry *import_table_entry) {
+ analyze_root(g, import_table_entry, import_table_entry->root);
}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 0dca23194d..374fcad748 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -9,7 +9,8 @@
#define ZIG_ANALYZE_HPP
struct CodeGen;
+struct ImportTableEntry;
-void semantic_analyze(CodeGen *g);
+void semantic_analyze(CodeGen *g, ImportTableEntry *entry);
#endif
diff --git a/src/codegen.cpp b/src/codegen.cpp
index c5e90cf75a..cb1b1b222e 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -11,26 +11,21 @@
#include "os.hpp"
#include "config.h"
#include "error.hpp"
-
#include "semantic_info.hpp"
+#include "analyze.hpp"
#include <stdio.h>
#include <errno.h>
-CodeGen *create_codegen(AstNode *root, Buf *in_full_path) {
+CodeGen *codegen_create(Buf *root_source_dir) {
CodeGen *g = allocate<CodeGen>(1);
- g->root = root;
g->fn_table.init(32);
g->str_table.init(32);
g->type_table.init(32);
g->link_table.init(32);
- g->is_static = false;
+ g->import_table.init(32);
g->build_type = CodeGenBuildTypeDebug;
- g->strip_debug_symbols = false;
- g->out_name = nullptr;
- g->out_type = OutTypeUnknown;
-
- os_path_split(in_full_path, &g->in_dir, &g->in_file);
+ g->root_source_dir = root_source_dir;
return g;
}
@@ -42,6 +37,10 @@ void codegen_set_is_static(CodeGen *g, bool is_static) {
g->is_static = is_static;
}
+void codegen_set_verbose(CodeGen *g, bool verbose) {
+ g->verbose = verbose;
+}
+
void codegen_set_strip(CodeGen *g, bool strip) {
g->strip_debug_symbols = strip;
}
@@ -51,7 +50,7 @@ void codegen_set_out_type(CodeGen *g, OutType out_type) {
}
void codegen_set_out_name(CodeGen *g, Buf *out_name) {
- g->out_name = out_name;
+ g->root_out_name = out_name;
}
static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
@@ -425,16 +424,17 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
case NodeTypeBlock:
case NodeTypeExternBlock:
case NodeTypeDirective:
+ case NodeTypeUse:
zig_unreachable();
}
zig_unreachable();
}
-static void gen_block(CodeGen *g, AstNode *block_node, bool add_implicit_return) {
+static void gen_block(CodeGen *g, ImportTableEntry *import, AstNode *block_node, bool add_implicit_return) {
assert(block_node->type == NodeTypeBlock);
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, g->block_scopes.last(),
- g->di_file, block_node->line + 1, block_node->column + 1);
+ import->di_file, block_node->line + 1, block_node->column + 1);
g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block));
add_debug_source_node(g, block_node);
@@ -466,22 +466,11 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro
return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0);
}
-void code_gen(CodeGen *g) {
+static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
- Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
- bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
- const char *flags = "";
- unsigned runtime_version = 0;
- g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
- buf_ptr(&g->in_file), buf_ptr(&g->in_dir),
- buf_ptr(producer), is_optimized, flags, runtime_version,
- "", 0, !g->strip_debug_symbols);
-
g->block_scopes.append(LLVMZigCompileUnitToScope(g->compile_unit));
- g->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&g->in_file), buf_ptr(&g->in_dir));
-
// Generate function prototypes
auto it = g->fn_table.entry_iterator();
@@ -523,6 +512,7 @@ void code_gen(CodeGen *g) {
// Generate function definitions.
for (int i = 0; i < g->fn_defs.length; i += 1) {
FnTableEntry *fn_table_entry = g->fn_defs.at(i);
+ ImportTableEntry *import = fn_table_entry->import_entry;
AstNode *fn_def_node = fn_table_entry->fn_def_node;
LLVMValueRef fn = fn_table_entry->fn_value;
g->cur_fn = fn_table_entry;
@@ -532,14 +522,15 @@ void code_gen(CodeGen *g) {
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
// Add debug info.
- LLVMZigDIScope *fn_scope = LLVMZigFileToScope(g->di_file);
+ LLVMZigDIScope *fn_scope = LLVMZigFileToScope(import->di_file);
unsigned line_number = fn_def_node->line + 1;
unsigned scope_line = line_number;
bool is_definition = true;
unsigned flags = 0;
+ bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
- fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number,
- create_di_function_type(g, fn_proto, g->di_file), fn_table_entry->internal_linkage,
+ fn_scope, buf_ptr(&fn_proto->name), "", import->di_file, line_number,
+ create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage,
is_definition, scope_line, flags, is_optimized, fn);
g->block_scopes.append(LLVMZigSubprogramToScope(subprogram));
@@ -555,7 +546,7 @@ void code_gen(CodeGen *g) {
LLVMGetParams(fn, codegen_fn_def->params);
bool add_implicit_return = codegen_fn_def->add_implicit_return;
- gen_block(g, fn_def_node->data.fn_def.body, add_implicit_return);
+ gen_block(g, import, fn_def_node->data.fn_def.body, add_implicit_return);
g->block_scopes.pop();
}
@@ -563,7 +554,9 @@ void code_gen(CodeGen *g) {
LLVMZigDIBuilderFinalize(g->dbuilder);
- LLVMDumpModule(g->module);
+ if (g->verbose) {
+ LLVMDumpModule(g->module);
+ }
// in release mode, we're sooooo confident that we've generated correct ir,
// that we skip the verify module step in order to get better performance.
@@ -573,13 +566,171 @@ void code_gen(CodeGen *g) {
#endif
}
-void code_gen_optimize(CodeGen *g) {
- LLVMZigOptimizeModule(g->target_machine, g->module);
- LLVMDumpModule(g->module);
+static void define_primitive_types(CodeGen *g) {
+ {
+ // if this type is anywhere in the AST, we should never hit codegen.
+ TypeTableEntry *entry = allocate<TypeTableEntry>(1);
+ buf_init_from_str(&entry->name, "(invalid)");
+ g->builtin_types.entry_invalid = entry;
+ }
+ {
+ TypeTableEntry *entry = allocate<TypeTableEntry>(1);
+ entry->type_ref = LLVMInt8Type();
+ buf_init_from_str(&entry->name, "u8");
+ entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 8, 8,
+ LLVMZigEncoding_DW_ATE_unsigned());
+ g->type_table.put(&entry->name, entry);
+ g->builtin_types.entry_u8 = entry;
+ }
+ {
+ TypeTableEntry *entry = allocate<TypeTableEntry>(1);
+ entry->type_ref = LLVMInt32Type();
+ buf_init_from_str(&entry->name, "i32");
+ entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 32, 32,
+ LLVMZigEncoding_DW_ATE_signed());
+ g->type_table.put(&entry->name, entry);
+ g->builtin_types.entry_i32 = entry;
+ }
+ {
+ TypeTableEntry *entry = allocate<TypeTableEntry>(1);
+ entry->type_ref = LLVMVoidType();
+ buf_init_from_str(&entry->name, "void");
+ entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, 0,
+ LLVMZigEncoding_DW_ATE_unsigned());
+ g->type_table.put(&entry->name, entry);
+ g->builtin_types.entry_void = entry;
+ }
+ {
+ TypeTableEntry *entry = allocate<TypeTableEntry>(1);
+ entry->type_ref = LLVMVoidType();
+ buf_init_from_str(&entry->name, "unreachable");
+ entry->di_type = g->builtin_types.entry_void->di_type;
+ g->type_table.put(&entry->name, entry);
+ g->builtin_types.entry_unreachable = entry;
+ }
}
-ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
- return &g->errors;
+
+
+static void init(CodeGen *g, Buf *source_path) {
+ LLVMInitializeAllTargets();
+ LLVMInitializeAllTargetMCs();
+ LLVMInitializeAllAsmPrinters();
+ LLVMInitializeAllAsmParsers();
+ LLVMInitializeNativeTarget();
+
+ g->is_native_target = true;
+ char *native_triple = LLVMGetDefaultTargetTriple();
+
+ LLVMTargetRef target_ref;
+ char *err_msg = nullptr;
+ if (LLVMGetTargetFromTriple(native_triple, &target_ref, &err_msg)) {
+ zig_panic("unable to get target from triple: %s", err_msg);
+ }
+
+ char *native_cpu = LLVMZigGetHostCPUName();
+ char *native_features = LLVMZigGetNativeFeatures();
+
+ LLVMCodeGenOptLevel opt_level = (g->build_type == CodeGenBuildTypeDebug) ?
+ LLVMCodeGenLevelNone : LLVMCodeGenLevelAggressive;
+
+ LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
+
+ g->target_machine = LLVMCreateTargetMachine(target_ref, native_triple,
+ native_cpu, native_features, opt_level, reloc_mode, LLVMCodeModelDefault);
+
+ g->target_data_ref = LLVMGetTargetMachineData(g->target_machine);
+
+
+ g->module = LLVMModuleCreateWithName("ZigModule");
+
+ g->pointer_size_bytes = LLVMPointerSize(g->target_data_ref);
+
+ g->builder = LLVMCreateBuilder();
+ g->dbuilder = LLVMZigCreateDIBuilder(g->module, true);
+
+
+ define_primitive_types(g);
+
+ Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
+ bool is_optimized = g->build_type == CodeGenBuildTypeRelease;
+ const char *flags = "";
+ unsigned runtime_version = 0;
+ g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
+ buf_ptr(source_path), buf_ptr(g->root_source_dir),
+ buf_ptr(producer), is_optimized, flags, runtime_version,
+ "", 0, !g->strip_debug_symbols);
+
+
+}
+
+void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) {
+ if (!g->initialized) {
+ g->initialized = true;
+ init(g, source_path);
+ }
+
+ Buf full_path = BUF_INIT;
+ os_path_join(g->root_source_dir, source_path, &full_path);
+
+ Buf dirname = BUF_INIT;
+ Buf basename = BUF_INIT;
+ os_path_split(&full_path, &dirname, &basename);
+
+ if (g->verbose) {
+ fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(source_path));
+ fprintf(stderr, "----------------\n");
+ fprintf(stderr, "%s\n", buf_ptr(source_code));
+
+ fprintf(stderr, "\nTokens:\n");
+ fprintf(stderr, "---------\n");
+ }
+
+ ZigList<Token> *tokens = tokenize(source_code);
+
+ if (g->verbose) {
+ print_tokens(source_code, tokens);
+
+ fprintf(stderr, "\nAST:\n");
+ fprintf(stderr, "------\n");
+ }
+
+ ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
+ import_entry->root = ast_parse(source_code, tokens);
+ assert(import_entry->root);
+ if (g->verbose) {
+ ast_print(import_entry->root, 0);
+
+ fprintf(stderr, "\nSemantic Analysis:\n");
+ fprintf(stderr, "--------------------\n");
+ }
+
+ import_entry->path = source_path;
+ import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(&basename), buf_ptr(&dirname));
+ g->import_table.put(source_path, import_entry);
+
+ semantic_analyze(g, import_entry);
+
+ if (g->errors.length == 0) {
+ if (g->verbose) {
+ fprintf(stderr, "OK\n");
+ }
+ } else {
+ for (int i = 0; i < g->errors.length; i += 1) {
+ ErrorMsg *err = &g->errors.at(i);
+ fprintf(stderr, "Error: Line %d, column %d: %s\n",
+ err->line_start + 1, err->column_start + 1,
+ buf_ptr(err->msg));
+ }
+ exit(1);
+ }
+
+ if (g->verbose) {
+ fprintf(stderr, "\nCode Generation:\n");
+ fprintf(stderr, "------------------\n");
+ }
+
+ do_code_gen(g);
}
static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
@@ -601,15 +752,15 @@ static Buf *to_c_type(CodeGen *g, AstNode *type_node) {
}
static void generate_h_file(CodeGen *g) {
- Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->out_name));
+ Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");
if (!out_h)
zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));
- Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->out_name));
+ Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));
buf_upcase(export_macro);
- Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->out_name));
+ Buf *extern_c_macro = buf_sprintf("%s_EXTERN_C", buf_ptr(g->root_out_name));
buf_upcase(extern_c_macro);
Buf h_buf = BUF_INIT;
@@ -644,7 +795,8 @@ static void generate_h_file(CodeGen *g) {
}
}
- Buf *ifdef_dance_name = buf_sprintf("%s_%s_H", buf_ptr(g->out_name), buf_ptr(g->out_name));
+ Buf *ifdef_dance_name = buf_sprintf("%s_%s_H",
+ buf_ptr(g->root_out_name), buf_ptr(g->root_out_name));
buf_upcase(ifdef_dance_name);
fprintf(out_h, "#ifndef %s\n", buf_ptr(ifdef_dance_name));
@@ -677,9 +829,27 @@ static void generate_h_file(CodeGen *g) {
zig_panic("unable to close h file: %s", strerror(errno));
}
-void code_gen_link(CodeGen *g, const char *out_file) {
+void codegen_link(CodeGen *g, const char *out_file) {
+ bool is_optimized = (g->build_type == CodeGenBuildTypeRelease);
+ if (is_optimized) {
+ if (g->verbose) {
+ fprintf(stderr, "\nOptimization:\n");
+ fprintf(stderr, "---------------\n");
+ }
+
+ LLVMZigOptimizeModule(g->target_machine, g->module);
+
+ if (g->verbose) {
+ LLVMDumpModule(g->module);
+ }
+ }
+ if (g->verbose) {
+ fprintf(stderr, "\nLink:\n");
+ fprintf(stderr, "-------\n");
+ }
+
if (!out_file) {
- out_file = buf_ptr(g->out_name);
+ out_file = buf_ptr(g->root_out_name);
}
Buf out_file_o = BUF_INIT;
@@ -728,8 +898,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
if (g->out_type == OutTypeLib) {
Buf *out_lib_so = buf_sprintf("lib%s.so.%d.%d.%d",
- buf_ptr(g->out_name), g->version_major, g->version_minor, g->version_patch);
- Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->out_name), g->version_major);
+ buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
+ Buf *soname = buf_sprintf("lib%s.so.%d", buf_ptr(g->root_out_name), g->version_major);
args.append("-shared");
args.append("-soname");
args.append(buf_ptr(soname));
@@ -756,4 +926,8 @@ void code_gen_link(CodeGen *g, const char *out_file) {
if (g->out_type == OutTypeLib) {
generate_h_file(g);
}
+
+ if (g->verbose) {
+ fprintf(stderr, "OK\n");
+ }
}
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 7795a3d3d9..403931b834 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -29,7 +29,7 @@ struct ErrorMsg {
};
-CodeGen *create_codegen(AstNode *root, Buf *in_file);
+CodeGen *codegen_create(Buf *root_source_dir);
enum CodeGenBuildType {
CodeGenBuildTypeDebug,
@@ -38,15 +38,12 @@ enum CodeGenBuildType {
void codegen_set_build_type(CodeGen *codegen, CodeGenBuildType build_type);
void codegen_set_is_static(CodeGen *codegen, bool is_static);
void codegen_set_strip(CodeGen *codegen, bool strip);
+void codegen_set_verbose(CodeGen *codegen, bool verbose);
void codegen_set_out_type(CodeGen *codegen, OutType out_type);
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
-void code_gen_optimize(CodeGen *g);
+void codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code);
-void code_gen(CodeGen *g);
-
-void code_gen_link(CodeGen *g, const char *out_file);
-
-ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g);
+void codegen_link(CodeGen *g, const char *out_file);
#endif
diff --git a/src/error.cpp b/src/error.cpp
index e7dab68147..7c3064c143 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -5,6 +5,7 @@ const char *err_str(int err) {
case ErrorNone: return "(no error)";
case ErrorNoMem: return "out of memory";
case ErrorInvalidFormat: return "invalid format";
+ case ErrorSemanticAnalyzeFail: return "semantic analyze failed";
}
return "(invalid error)";
}
diff --git a/src/error.hpp b/src/error.hpp
index 3a975f2177..7da2cf8322 100644
--- a/src/error.hpp
+++ b/src/error.hpp
@@ -12,6 +12,7 @@ enum Error {
ErrorNone,
ErrorNoMem,
ErrorInvalidFormat,
+ ErrorSemanticAnalyzeFail,
};
const char *err_str(int err);
diff --git a/src/main.cpp b/src/main.cpp
index a39bb8feb5..b88d6ecd6b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,25 +6,11 @@
*/
#include "config.h"
-#include "util.hpp"
-#include "list.hpp"
#include "buffer.hpp"
-#include "parser.hpp"
-#include "tokenizer.hpp"
-#include "error.hpp"
#include "codegen.hpp"
-#include "analyze.hpp"
+#include "os.hpp"
#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <stdint.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <inttypes.h>
static int usage(const char *arg0) {
fprintf(stderr, "Usage: %s [command] [options] target\n"
@@ -38,6 +24,7 @@ static int usage(const char *arg0) {
" --export [exe|lib|obj] override output type\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
+ " --verbose turn on compiler debug output\n"
, arg0);
return EXIT_FAILURE;
}
@@ -47,98 +34,47 @@ static int version(void) {
return EXIT_SUCCESS;
}
-static Buf *fetch_file(FILE *f) {
- int fd = fileno(f);
- struct stat st;
- if (fstat(fd, &st))
- zig_panic("unable to stat file: %s", strerror(errno));
- off_t big_size = st.st_size;
- if (big_size > INT_MAX)
- zig_panic("file too big");
- int size = (int)big_size;
-
- Buf *buf = buf_alloc_fixed(size);
- size_t amt_read = fread(buf_ptr(buf), 1, buf_len(buf), f);
- if (amt_read != (size_t)buf_len(buf))
- zig_panic("error reading: %s", strerror(errno));
-
- return buf;
-}
-
-static int build(const char *arg0, const char *in_file, const char *out_file, bool release,
- bool strip, bool is_static, OutType out_type, char *out_name)
-{
- static char cur_dir[1024];
+struct Build {
+ const char *in_file;
+ const char *out_file;
+ bool release;
+ bool strip;
+ bool is_static;
+ OutType out_type;
+ const char *out_name;
+ bool verbose;
+};
- if (!in_file)
+static int build(const char *arg0, Build *b) {
+ if (!b->in_file)
return usage(arg0);
- FILE *in_f;
- if (strcmp(in_file, "-") == 0) {
- in_f = stdin;
- char *result = getcwd(cur_dir, sizeof(cur_dir));
- if (!result)
- zig_panic("unable to get current working directory: %s", strerror(errno));
- } else {
- in_f = fopen(in_file, "rb");
- if (!in_f)
- zig_panic("unable to open %s for reading: %s\n", in_file, strerror(errno));
- }
+ Buf in_file_buf = BUF_INIT;
+ buf_init_from_str(&in_file_buf, b->in_file);
- fprintf(stderr, "Original source:\n");
- fprintf(stderr, "----------------\n");
- Buf *in_data = fetch_file(in_f);
- fprintf(stderr, "%s\n", buf_ptr(in_data));
-
- fprintf(stderr, "\nTokens:\n");
- fprintf(stderr, "---------\n");
- ZigList<Token> *tokens = tokenize(in_data);
- print_tokens(in_data, tokens);
-
- fprintf(stderr, "\nAST:\n");
- fprintf(stderr, "------\n");
- AstNode *root = ast_parse(in_data, tokens);
- assert(root);
- ast_print(root, 0);
-
- fprintf(stderr, "\nSemantic Analysis:\n");
- fprintf(stderr, "--------------------\n");
- CodeGen *codegen = create_codegen(root, buf_create_from_str(in_file));
- codegen_set_build_type(codegen, release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
- codegen_set_strip(codegen, strip);
- codegen_set_is_static(codegen, is_static);
- if (out_type != OutTypeUnknown)
- codegen_set_out_type(codegen, out_type);
- if (out_name)
- codegen_set_out_name(codegen, buf_create_from_str(out_name));
- semantic_analyze(codegen);
- ZigList<ErrorMsg> *errors = codegen_error_messages(codegen);
- if (errors->length == 0) {
- fprintf(stderr, "OK\n");
+ Buf root_source_dir = BUF_INIT;
+ Buf root_source_code = BUF_INIT;
+ Buf root_source_name = BUF_INIT;
+ if (buf_eql_str(&in_file_buf, "-")) {
+ os_get_cwd(&root_source_dir);
+ os_fetch_file(stdin, &root_source_code);
+ buf_init_from_str(&root_source_name, "");
} else {
- for (int i = 0; i < errors->length; i += 1) {
- ErrorMsg *err = &errors->at(i);
- fprintf(stderr, "Error: Line %d, column %d: %s\n",
- err->line_start + 1, err->column_start + 1,
- buf_ptr(err->msg));
- }
- return 1;
+ os_path_split(&in_file_buf, &root_source_dir, &root_source_name);
+ os_fetch_file_path(buf_create_from_str(b->in_file), &root_source_code);
}
- fprintf(stderr, "\nCode Generation:\n");
- fprintf(stderr, "------------------\n");
- code_gen(codegen);
-
- if (release) {
- fprintf(stderr, "\nOptimization:\n");
- fprintf(stderr, "---------------\n");
- code_gen_optimize(codegen);
- }
-
- fprintf(stderr, "\nLink:\n");
- fprintf(stderr, "-------\n");
- code_gen_link(codegen, out_file);
- fprintf(stderr, "OK\n");
+ CodeGen *g = codegen_create(&root_source_dir);
+ codegen_set_build_type(g, b->release ? CodeGenBuildTypeRelease : CodeGenBuildTypeDebug);
+ codegen_set_strip(g, b->strip);
+ codegen_set_is_static(g, b->is_static);
+ if (b->out_type != OutTypeUnknown)
+ codegen_set_out_type(g, b->out_type);
+ if (b->out_name)
+ codegen_set_out_name(g, buf_create_from_str(b->out_name));
+ codegen_set_verbose(g, b->verbose);
+ codegen_add_code(g, &root_source_name, &root_source_code);
+ codegen_link(g, b->out_file);
return 0;
}
@@ -151,43 +87,39 @@ enum Cmd {
int main(int argc, char **argv) {
char *arg0 = argv[0];
- char *in_file = NULL;
- char *out_file = NULL;
- bool release = false;
- bool strip = false;
- bool is_static = false;
-
- OutType out_type = OutTypeUnknown;
- char *out_name = NULL;
+ Build b = {0};
Cmd cmd = CmdNone;
+
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
if (arg[0] == '-' && arg[1] == '-') {
if (strcmp(arg, "--release") == 0) {
- release = true;
+ b.release = true;
} else if (strcmp(arg, "--strip") == 0) {
- strip = true;
+ b.strip = true;
} else if (strcmp(arg, "--static") == 0) {
- is_static = true;
+ b.is_static = true;
+ } else if (strcmp(arg, "--verbose") == 0) {
+ b.verbose = true;
} else if (i + 1 >= argc) {
return usage(arg0);
} else {
i += 1;
if (strcmp(arg, "--output") == 0) {
- out_file = argv[i];
+ b.out_file = argv[i];
} else if (strcmp(arg, "--export") == 0) {
if (strcmp(argv[i], "exe") == 0) {
- out_type = OutTypeExe;
+ b.out_type = OutTypeExe;
} else if (strcmp(argv[i], "lib") == 0) {
- out_type = OutTypeLib;
+ b.out_type = OutTypeLib;
} else if (strcmp(argv[i], "obj") == 0) {
- out_type = OutTypeObj;
+ b.out_type = OutTypeObj;
} else {
return usage(arg0);
}
} else if (strcmp(arg, "--name") == 0) {
- out_name = argv[i];
+ b.out_name = argv[i];
} else {
return usage(arg0);
}
@@ -206,8 +138,8 @@ int main(int argc, char **argv) {
case CmdNone:
zig_unreachable();
case CmdBuild:
- if (!in_file) {
- in_file = arg;
+ if (!b.in_file) {
+ b.in_file = arg;
} else {
return usage(arg0);
}
@@ -222,7 +154,7 @@ int main(int argc, char **argv) {
case CmdNone:
return usage(arg0);
case CmdBuild:
- return build(arg0, in_file, out_file, release, strip, is_static, out_type, out_name);
+ return build(arg0, &b);
case CmdVersion:
return version();
}
diff --git a/src/os.cpp b/src/os.cpp
index bab72de2b9..61dd1c01ee 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -13,8 +13,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <stdio.h>
#include <fcntl.h>
+#include <limits.h>
void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached) {
pid_t pid = fork();
@@ -37,7 +37,7 @@ void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detache
zig_panic("execvp failed: %s", strerror(errno));
}
-static void read_all_fd(int fd, Buf *out_buf) {
+static void read_all_fd_stream(int fd, Buf *out_buf) {
static const ssize_t buf_size = 0x2000;
buf_resize(out_buf, buf_size);
ssize_t actual_buf_len = 0;
@@ -72,6 +72,12 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
buf_init_from_buf(out_basename, full_path);
}
+void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
+ buf_init_from_buf(out_full_path, dirname);
+ buf_append_char(out_full_path, '/');
+ buf_append_buf(out_full_path, basename);
+}
+
void os_exec_process(const char *exe, ZigList<const char *> &args,
int *return_code, Buf *out_stderr, Buf *out_stdout)
{
@@ -117,8 +123,8 @@ void os_exec_process(const char *exe, ZigList<const char *> &args,
waitpid(pid, return_code, 0);
- read_all_fd(stdout_pipe[0], out_stdout);
- read_all_fd(stderr_pipe[0], out_stderr);
+ read_all_fd_stream(stdout_pipe[0], out_stdout);
+ read_all_fd_stream(stderr_pipe[0], out_stderr);
}
}
@@ -133,3 +139,44 @@ void os_write_file(Buf *full_path, Buf *contents) {
if (close(fd) == -1)
zig_panic("close failed");
}
+
+int os_fetch_file(FILE *f, Buf *out_contents) {
+ int fd = fileno(f);
+ struct stat st;
+ if (fstat(fd, &st))
+ zig_panic("unable to stat file: %s", strerror(errno));
+ off_t big_size = st.st_size;
+ if (big_size > INT_MAX)
+ zig_panic("file too big");
+ int size = (int)big_size;
+
+ buf_resize(out_contents, size);
+ ssize_t ret = read(fd, buf_ptr(out_contents), size);
+
+ if (ret != size)
+ zig_panic("unable to read file: %s", strerror(errno));
+
+ return 0;
+}
+
+int os_fetch_file_path(Buf *full_path, Buf *out_contents) {
+ FILE *f = fopen(buf_ptr(full_path), "rb");
+ if (!f)
+ zig_panic("unable to open %s: %s\n", buf_ptr(full_path), strerror(errno));
+ int result = os_fetch_file(f, out_contents);
+ fclose(f);
+ return result;
+}
+
+int os_get_cwd(Buf *out_cwd) {
+ int err = ERANGE;
+ buf_resize(out_cwd, 512);
+ while (err == ERANGE) {
+ buf_resize(out_cwd, buf_len(out_cwd) * 2);
+ err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno;
+ }
+ if (err)
+ zig_panic("unable to get cwd: %s", strerror(err));
+
+ return 0;
+}
diff --git a/src/os.hpp b/src/os.hpp
index a17c2b56f1..8bb5d8ea4f 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -11,13 +11,22 @@
#include "list.hpp"
#include "buffer.hpp"
+#include <stdio.h>
+
void os_spawn_process(const char *exe, ZigList<const char *> &args, bool detached);
void os_exec_process(const char *exe, ZigList<const char *> &args,
int *return_code, Buf *out_stderr, Buf *out_stdout);
void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
+void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
void os_write_file(Buf *full_path, Buf *contents);
+int os_fetch_file(FILE *file, Buf *out_contents);
+int os_fetch_file_path(Buf *full_path, Buf *out_contents);
+
+int os_get_cwd(Buf *out_cwd);
+
+
#endif
diff --git a/src/parser.cpp b/src/parser.cpp
index 10f43d26d4..613c559235 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -100,6 +100,8 @@ const char *node_type_str(NodeType node_type) {
return "Symbol";
case NodeTypePrefixOpExpr:
return "PrefixOpExpr";
+ case NodeTypeUse:
+ return "Use";
}
zig_unreachable();
}
@@ -241,6 +243,9 @@ void ast_print(AstNode *node, int indent) {
fprintf(stderr, "PrimaryExpr Symbol %s\n",
buf_ptr(&node->data.symbol));
break;
+ case NodeTypeUse:
+ fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
+ break;
}
}
@@ -1231,7 +1236,36 @@ static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index, b
}
/*
-TopLevelDecl : FnDef | ExternBlock | RootExportDecl
+Use : many(Directive) token(Use) token(String) token(Semicolon)
+*/
+static AstNode *ast_parse_use(ParseContext *pc, int *token_index, bool mandatory) {
+ assert(mandatory == false);
+
+ Token *use_kw = &pc->tokens->at(*token_index);
+ if (use_kw->id != TokenIdKeywordUse)
+ return nullptr;
+ *token_index += 1;
+
+ Token *use_name = &pc->tokens->at(*token_index);
+ *token_index += 1;
+ ast_expect_token(pc, use_name, TokenIdStringLiteral);
+
+ Token *semicolon = &pc->tokens->at(*token_index);
+ *token_index += 1;
+ ast_expect_token(pc, semicolon, TokenIdSemicolon);
+
+ AstNode *node = ast_create_node(NodeTypeUse, use_kw);
+
+ parse_string_literal(pc, use_name, &node->data.use.path);
+
+ node->data.use.directives = pc->directive_list;
+ pc->directive_list = nullptr;
+
+ return node;
+}
+
+/*
+TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use
*/
static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
for (;;) {
@@ -1258,6 +1292,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
continue;
}
+ AstNode *use_node = ast_parse_use(pc, token_index, false);
+ if (use_node) {
+ top_level_decls->append(use_node);
+ continue;
+ }
+
if (pc->directive_list->length > 0) {
ast_error(directive_token, "invalid directive");
}
diff --git a/src/parser.hpp b/src/parser.hpp
index 6d99dfbc4c..cc7b3dd0b6 100644
--- a/src/parser.hpp
+++ b/src/parser.hpp
@@ -35,6 +35,7 @@ enum NodeType {
NodeTypeSymbol,
NodeTypePrefixOpExpr,
NodeTypeFnCallExpr,
+ NodeTypeUse,
};
struct AstNodeRoot {
@@ -158,6 +159,11 @@ struct AstNodePrefixOpExpr {
AstNode *primary_expr;
};
+struct AstNodeUse {
+ Buf path;
+ ZigList<AstNode *> *directives;
+};
+
struct AstNode {
enum NodeType type;
AstNode *parent;
@@ -180,6 +186,7 @@ struct AstNode {
AstNodeCastExpr cast_expr;
AstNodePrefixOpExpr prefix_op_expr;
AstNodeFnCallExpr fn_call_expr;
+ AstNodeUse use;
Buf number;
Buf string;
Buf symbol;
diff --git a/src/semantic_info.hpp b/src/semantic_info.hpp
index 13a05b1207..dc87c12930 100644
--- a/src/semantic_info.hpp
+++ b/src/semantic_info.hpp
@@ -12,15 +12,6 @@
#include "hash_map.hpp"
#include "zig_llvm.hpp"
-struct FnTableEntry {
- LLVMValueRef fn_value;
- AstNode *proto_node;
- AstNode *fn_def_node;
- bool is_extern;
- bool internal_linkage;
- unsigned calling_convention;
-};
-
struct TypeTableEntry {
LLVMTypeRef type_ref;
LLVMZigDIType *di_type;
@@ -33,17 +24,35 @@ struct TypeTableEntry {
TypeTableEntry *pointer_mut_parent;
};
+struct ImportTableEntry {
+ AstNode *root;
+ Buf *path; // relative to root_source_dir
+ LLVMZigDIFile *di_file;
+};
+
+struct FnTableEntry {
+ LLVMValueRef fn_value;
+ AstNode *proto_node;
+ AstNode *fn_def_node;
+ bool is_extern;
+ bool internal_linkage;
+ unsigned calling_convention;
+ ImportTableEntry *import_entry;
+};
+
struct CodeGen {
LLVMModuleRef module;
- AstNode *root;
ZigList<ErrorMsg> errors;
LLVMBuilderRef builder;
LLVMZigDIBuilder *dbuilder;
LLVMZigDICompileUnit *compile_unit;
+
+ // reminder: hash tables must be initialized before use
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
+ HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
struct {
TypeTableEntry *entry_u8;
@@ -60,12 +69,10 @@ struct CodeGen {
CodeGenBuildType build_type;
LLVMTargetMachineRef target_machine;
bool is_native_target;
- Buf in_file;
- Buf in_dir;
+ Buf *root_source_dir;
+ Buf *root_out_name;
ZigList<LLVMZigDIScope *> block_scopes;
- LLVMZigDIFile *di_file;
ZigList<FnTableEntry *> fn_defs;
- Buf *out_name;
OutType out_type;
FnTableEntry *cur_fn;
bool c_stdint_used;
@@ -73,6 +80,8 @@ struct CodeGen {
int version_major;
int version_minor;
int version_patch;
+ bool verbose;
+ bool initialized;
};
struct TypeNode {
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 3e8a201f52..94f3966f0f 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -180,6 +180,8 @@ static void end_token(Tokenize *t) {
t->cur_tok->id = TokenIdKeywordExport;
} else if (mem_eql_str(token_mem, token_len, "as")) {
t->cur_tok->id = TokenIdKeywordAs;
+ } else if (mem_eql_str(token_mem, token_len, "use")) {
+ t->cur_tok->id = TokenIdKeywordUse;
}
t->cur_tok = nullptr;
@@ -562,6 +564,7 @@ static const char * token_name(Token *token) {
case TokenIdKeywordPub: return "Pub";
case TokenIdKeywordExport: return "Export";
case TokenIdKeywordAs: return "As";
+ case TokenIdKeywordUse: return "Use";
case TokenIdLParen: return "LParen";
case TokenIdRParen: return "RParen";
case TokenIdComma: return "Comma";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index 2c9ad61957..94cbb15d43 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -22,6 +22,7 @@ enum TokenId {
TokenIdKeywordPub,
TokenIdKeywordExport,
TokenIdKeywordAs,
+ TokenIdKeywordUse,
TokenIdLParen,
TokenIdRParen,
TokenIdComma,