rewrite how importing works
* Introduce the concept of packages. Closes #3 * Add support for error notes. * Introduce `@import` and `@c_import` builtin functions and remove the `import` and `c_import` top level declarations. * Introduce the `use` top level declaration. * Add `--check-unused` parameter to perform semantic analysis and codegen on all top level declarations, not just exported ones and ones referenced by exported ones. * Delete the root export node and add `--library` argument.
This commit is contained in:
347
src/codegen.cpp
347
src/codegen.cpp
@@ -47,19 +47,30 @@ static void init_darwin_native(CodeGen *g) {
|
||||
}
|
||||
}
|
||||
|
||||
static PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path) {
|
||||
PackageTableEntry *entry = allocate<PackageTableEntry>(1);
|
||||
entry->package_table.init(4);
|
||||
buf_init_from_str(&entry->root_src_dir, root_src_dir);
|
||||
buf_init_from_str(&entry->root_src_path, root_src_path);
|
||||
return entry;
|
||||
}
|
||||
|
||||
CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
|
||||
CodeGen *g = allocate<CodeGen>(1);
|
||||
g->import_table.init(32);
|
||||
g->builtin_fn_table.init(32);
|
||||
g->primitive_type_table.init(32);
|
||||
g->unresolved_top_level_decls.init(32);
|
||||
g->fn_type_table.init(32);
|
||||
g->error_table.init(16);
|
||||
g->is_release_build = false;
|
||||
g->is_test_build = false;
|
||||
g->root_source_dir = root_source_dir;
|
||||
g->error_value_count = 1;
|
||||
|
||||
g->root_package = new_package(buf_ptr(root_source_dir), "");
|
||||
g->std_package = new_package(ZIG_STD_DIR, "index.zig");
|
||||
g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
|
||||
|
||||
|
||||
if (target) {
|
||||
// cross compiling, so we can't rely on all the configured stuff since
|
||||
// that's for native compilation
|
||||
@@ -117,6 +128,10 @@ void codegen_set_verbose(CodeGen *g, bool verbose) {
|
||||
g->verbose = verbose;
|
||||
}
|
||||
|
||||
void codegen_set_check_unused(CodeGen *g, bool check_unused) {
|
||||
g->check_unused = check_unused;
|
||||
}
|
||||
|
||||
void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
|
||||
g->err_color = err_color;
|
||||
}
|
||||
@@ -157,6 +172,14 @@ void codegen_add_lib_dir(CodeGen *g, const char *dir) {
|
||||
g->lib_dirs.append(dir);
|
||||
}
|
||||
|
||||
void codegen_add_link_lib(CodeGen *g, const char *lib) {
|
||||
if (strcmp(lib, "c") == 0) {
|
||||
g->link_libc = true;
|
||||
} else {
|
||||
g->link_libs.append(buf_create_from_str(lib));
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
|
||||
g->windows_subsystem_windows = mwindows;
|
||||
g->windows_subsystem_console = mconsole;
|
||||
@@ -316,6 +339,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
|
||||
case BuiltinFnIdCInclude:
|
||||
case BuiltinFnIdCDefine:
|
||||
case BuiltinFnIdCUndef:
|
||||
case BuiltinFnIdImport:
|
||||
case BuiltinFnIdCImport:
|
||||
zig_unreachable();
|
||||
case BuiltinFnIdCtz:
|
||||
case BuiltinFnIdClz:
|
||||
@@ -844,7 +869,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
|
||||
|
||||
LLVMValueRef struct_ptr;
|
||||
if (struct_expr_node->type == NodeTypeSymbol) {
|
||||
VariableTableEntry *var = struct_expr_node->data.symbol_expr.variable;
|
||||
VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable;
|
||||
assert(var);
|
||||
|
||||
if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {
|
||||
@@ -983,6 +1008,17 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTableEntry *variable) {
|
||||
if (!type_has_bits(variable->type)) {
|
||||
return nullptr;
|
||||
} else if (variable->is_ptr) {
|
||||
assert(variable->value_ref);
|
||||
return get_handle_value(g, source_node, variable->value_ref, variable->type);
|
||||
} else {
|
||||
return variable->value_ref;
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
|
||||
assert(node->type == NodeTypeFieldAccessExpr);
|
||||
|
||||
@@ -1016,6 +1052,10 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
} else if (struct_type->id == TypeTableEntryIdNamespace) {
|
||||
VariableTableEntry *variable = get_resolved_expr(node)->variable;
|
||||
assert(variable);
|
||||
return gen_variable(g, node, variable);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
@@ -1027,7 +1067,7 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
|
||||
LLVMValueRef target_ref;
|
||||
|
||||
if (node->type == NodeTypeSymbol) {
|
||||
VariableTableEntry *var = node->data.symbol_expr.variable;
|
||||
VariableTableEntry *var = get_resolved_expr(node)->variable;
|
||||
assert(var);
|
||||
|
||||
*out_type_entry = var->type;
|
||||
@@ -2468,21 +2508,18 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
|
||||
|
||||
static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
|
||||
assert(node->type == NodeTypeSymbol);
|
||||
VariableTableEntry *variable = node->data.symbol_expr.variable;
|
||||
VariableTableEntry *variable = get_resolved_expr(node)->variable;
|
||||
if (variable) {
|
||||
if (!type_has_bits(variable->type)) {
|
||||
return nullptr;
|
||||
} else if (variable->is_ptr) {
|
||||
assert(variable->value_ref);
|
||||
return get_handle_value(g, node, variable->value_ref, variable->type);
|
||||
} else {
|
||||
return variable->value_ref;
|
||||
}
|
||||
return gen_variable(g, node, variable);
|
||||
}
|
||||
|
||||
zig_unreachable();
|
||||
|
||||
/* TODO delete
|
||||
FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;
|
||||
assert(fn_entry);
|
||||
return fn_entry->fn_value;
|
||||
*/
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
|
||||
@@ -2703,14 +2740,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
|
||||
// caught by constant expression eval codegen
|
||||
zig_unreachable();
|
||||
case NodeTypeRoot:
|
||||
case NodeTypeRootExportDecl:
|
||||
case NodeTypeFnProto:
|
||||
case NodeTypeFnDef:
|
||||
case NodeTypeFnDecl:
|
||||
case NodeTypeParamDecl:
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeImport:
|
||||
case NodeTypeCImport:
|
||||
case NodeTypeUse:
|
||||
case NodeTypeStructDecl:
|
||||
case NodeTypeStructField:
|
||||
case NodeTypeStructValueField:
|
||||
@@ -2891,6 +2926,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
|
||||
case TypeTableEntryIdNumLitInt:
|
||||
case TypeTableEntryIdUndefLit:
|
||||
case TypeTableEntryIdVoid:
|
||||
case TypeTableEntryIdNamespace:
|
||||
zig_unreachable();
|
||||
|
||||
}
|
||||
@@ -2943,14 +2979,14 @@ static bool skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
if (fn_entry == g->main_fn) {
|
||||
return true;
|
||||
}
|
||||
return fn_entry->ref_count == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fn_entry->is_test) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fn_entry->ref_count == 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) {
|
||||
@@ -3296,6 +3332,12 @@ static void define_builtin_types(CodeGen *g) {
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_invalid = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace);
|
||||
buf_init_from_str(&entry->name, "(namespace)");
|
||||
entry->zero_bits = true;
|
||||
g->builtin_types.entry_namespace = entry;
|
||||
}
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
|
||||
buf_init_from_str(&entry->name, "(float literal)");
|
||||
@@ -3499,14 +3541,6 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->builtin_types.entry_type = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
{
|
||||
// partially complete the error type. we complete it later after we know
|
||||
// error_value_count.
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
|
||||
buf_init_from_str(&entry->name, "error");
|
||||
g->builtin_types.entry_pure_error = entry;
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
||||
g->builtin_types.entry_u8 = get_int_type(g, false, 8);
|
||||
g->builtin_types.entry_u16 = get_int_type(g, false, 16);
|
||||
@@ -3517,6 +3551,21 @@ static void define_builtin_types(CodeGen *g) {
|
||||
g->builtin_types.entry_i32 = get_int_type(g, true, 32);
|
||||
g->builtin_types.entry_i64 = get_int_type(g, true, 64);
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
|
||||
buf_init_from_str(&entry->name, "error");
|
||||
|
||||
// TODO allow overriding this type and keep track of max value and emit an
|
||||
// error if there are too many errors declared
|
||||
g->err_tag_type = g->builtin_types.entry_u16;
|
||||
|
||||
g->builtin_types.entry_pure_error = entry;
|
||||
entry->type_ref = g->err_tag_type->type_ref;
|
||||
entry->di_type = g->err_tag_type->di_type;
|
||||
|
||||
g->primitive_type_table.put(&entry->name, entry);
|
||||
}
|
||||
|
||||
{
|
||||
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
|
||||
entry->zero_bits = true; // only allowed at compile time
|
||||
@@ -3685,12 +3734,11 @@ static void define_builtin_fns(CodeGen *g) {
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "const_eval", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1);
|
||||
create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "c_import", 1);
|
||||
}
|
||||
|
||||
static void init(CodeGen *g, Buf *source_path) {
|
||||
g->lib_search_paths.append(g->root_source_dir);
|
||||
g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR));
|
||||
|
||||
g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
|
||||
|
||||
get_target_triple(&g->triple_str, &g->zig_target);
|
||||
@@ -3741,7 +3789,7 @@ static void init(CodeGen *g, Buf *source_path) {
|
||||
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(source_path), buf_ptr(&g->root_package->root_src_dir),
|
||||
buf_ptr(producer), is_optimized, flags, runtime_version,
|
||||
"", 0, !g->strip_debug_symbols);
|
||||
|
||||
@@ -3761,9 +3809,6 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source
|
||||
ImportTableEntry *import = allocate<ImportTableEntry>(1);
|
||||
import->source_code = source_code;
|
||||
import->path = full_path;
|
||||
import->fn_table.init(32);
|
||||
import->type_table.init(8);
|
||||
import->error_table.init(8);
|
||||
g->root_import = import;
|
||||
|
||||
init(g, full_path);
|
||||
@@ -3791,214 +3836,7 @@ void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {
|
||||
}
|
||||
|
||||
|
||||
static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {
|
||||
char *dot1 = strstr(buf_ptr(buf), ".");
|
||||
if (!dot1)
|
||||
return ErrorInvalidFormat;
|
||||
char *dot2 = strstr(dot1 + 1, ".");
|
||||
if (!dot2)
|
||||
return ErrorInvalidFormat;
|
||||
|
||||
*major = (int)strtol(buf_ptr(buf), nullptr, 10);
|
||||
*minor = (int)strtol(dot1 + 1, nullptr, 10);
|
||||
*patch = (int)strtol(dot2 + 1, nullptr, 10);
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) {
|
||||
int err;
|
||||
if ((err = parse_version_string(version_buf, &g->version_major, &g->version_minor, &g->version_patch))) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("invalid version string"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
|
||||
Buf *src_dirname, Buf *src_basename, Buf *source_code)
|
||||
{
|
||||
int err;
|
||||
Buf *full_path = buf_alloc();
|
||||
os_path_join(src_dirname, src_basename, full_path);
|
||||
|
||||
if (g->verbose) {
|
||||
fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
|
||||
fprintf(stderr, "----------------\n");
|
||||
fprintf(stderr, "%s\n", buf_ptr(source_code));
|
||||
|
||||
fprintf(stderr, "\nTokens:\n");
|
||||
fprintf(stderr, "---------\n");
|
||||
}
|
||||
|
||||
Tokenization tokenization = {0};
|
||||
tokenize(source_code, &tokenization);
|
||||
|
||||
if (tokenization.err) {
|
||||
ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
|
||||
source_code, tokenization.line_offsets, tokenization.err);
|
||||
|
||||
print_err_msg(err, g->err_color);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (g->verbose) {
|
||||
print_tokens(source_code, tokenization.tokens);
|
||||
|
||||
fprintf(stderr, "\nAST:\n");
|
||||
fprintf(stderr, "------\n");
|
||||
}
|
||||
|
||||
ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
|
||||
import_entry->source_code = source_code;
|
||||
import_entry->line_offsets = tokenization.line_offsets;
|
||||
import_entry->path = full_path;
|
||||
import_entry->fn_table.init(32);
|
||||
import_entry->type_table.init(8);
|
||||
import_entry->error_table.init(8);
|
||||
|
||||
import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
|
||||
&g->next_node_index);
|
||||
assert(import_entry->root);
|
||||
if (g->verbose) {
|
||||
ast_print(stderr, import_entry->root, 0);
|
||||
}
|
||||
|
||||
import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
|
||||
g->import_table.put(abs_full_path, import_entry);
|
||||
|
||||
import_entry->block_context = new_block_context(import_entry->root, nullptr);
|
||||
import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
|
||||
|
||||
|
||||
assert(import_entry->root->type == NodeTypeRoot);
|
||||
for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
|
||||
AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
|
||||
|
||||
if (top_level_decl->type == NodeTypeRootExportDecl) {
|
||||
if (g->root_import) {
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("root export declaration only valid in root source file"));
|
||||
} else {
|
||||
ZigList<AstNode *> *directives = top_level_decl->data.root_export_decl.directives;
|
||||
if (directives) {
|
||||
for (int i = 0; i < directives->length; i += 1) {
|
||||
AstNode *directive_node = directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
AstNode *param_node = directive_node->data.directive.expr;
|
||||
assert(param_node->type == NodeTypeStringLiteral);
|
||||
Buf *param = ¶m_node->data.string_literal.buf;
|
||||
|
||||
if (param) {
|
||||
if (buf_eql_str(name, "version")) {
|
||||
set_root_export_version(g, param, directive_node);
|
||||
} else if (buf_eql_str(name, "link")) {
|
||||
if (buf_eql_str(param, "c")) {
|
||||
g->link_libc = true;
|
||||
} else {
|
||||
g->link_libs.append(param);
|
||||
}
|
||||
} else {
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g->root_export_decl) {
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("only one root export declaration allowed"));
|
||||
} else {
|
||||
g->root_export_decl = top_level_decl;
|
||||
|
||||
if (!g->root_out_name)
|
||||
g->root_out_name = &top_level_decl->data.root_export_decl.name;
|
||||
|
||||
Buf *out_type = &top_level_decl->data.root_export_decl.type;
|
||||
OutType export_out_type;
|
||||
if (buf_eql_str(out_type, "executable")) {
|
||||
export_out_type = OutTypeExe;
|
||||
} else if (buf_eql_str(out_type, "library")) {
|
||||
export_out_type = OutTypeLib;
|
||||
} else if (buf_eql_str(out_type, "object")) {
|
||||
export_out_type = OutTypeObj;
|
||||
} else {
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("invalid export type: '%s'", buf_ptr(out_type)));
|
||||
}
|
||||
if (g->out_type == OutTypeUnknown) {
|
||||
g->out_type = export_out_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (top_level_decl->type == NodeTypeImport) {
|
||||
Buf *import_target_path = &top_level_decl->data.import.path;
|
||||
Buf full_path = BUF_INIT;
|
||||
Buf *import_code = buf_alloc();
|
||||
bool found_it = false;
|
||||
|
||||
for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
|
||||
Buf *search_path = g->lib_search_paths.at(path_i);
|
||||
os_path_join(search_path, import_target_path, &full_path);
|
||||
|
||||
Buf *abs_full_path = buf_alloc();
|
||||
if ((err = os_path_real(&full_path, abs_full_path))) {
|
||||
if (err == ErrorFileNotFound) {
|
||||
continue;
|
||||
} else {
|
||||
g->error_during_imports = true;
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
|
||||
goto done_looking_at_imports;
|
||||
}
|
||||
}
|
||||
|
||||
auto entry = g->import_table.maybe_get(abs_full_path);
|
||||
if (entry) {
|
||||
found_it = true;
|
||||
top_level_decl->data.import.import = entry->value;
|
||||
} else {
|
||||
if ((err = os_fetch_file_path(abs_full_path, import_code))) {
|
||||
if (err == ErrorFileNotFound) {
|
||||
continue;
|
||||
} else {
|
||||
g->error_during_imports = true;
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
|
||||
goto done_looking_at_imports;
|
||||
}
|
||||
}
|
||||
top_level_decl->data.import.import = codegen_add_code(g,
|
||||
abs_full_path, search_path, &top_level_decl->data.import.path, import_code);
|
||||
found_it = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!found_it) {
|
||||
g->error_during_imports = true;
|
||||
add_node_error(g, top_level_decl,
|
||||
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
|
||||
}
|
||||
} else if (top_level_decl->type == NodeTypeFnDef) {
|
||||
AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
|
||||
assert(proto_node->type == NodeTypeFnProto);
|
||||
Buf *proto_name = &proto_node->data.fn_proto.name;
|
||||
|
||||
bool is_private = (proto_node->data.fn_proto.visib_mod == VisibModPrivate);
|
||||
|
||||
if (buf_eql_str(proto_name, "main") && !is_private) {
|
||||
g->have_exported_main = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done_looking_at_imports:
|
||||
|
||||
return import_entry;
|
||||
}
|
||||
|
||||
static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
|
||||
static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package, const char *basename) {
|
||||
Buf *std_dir = buf_create_from_str(ZIG_STD_DIR);
|
||||
Buf *code_basename = buf_create_from_str(basename);
|
||||
Buf path_to_code_src = BUF_INIT;
|
||||
@@ -4013,12 +3851,22 @@ static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
|
||||
zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
|
||||
}
|
||||
|
||||
return codegen_add_code(g, abs_full_path, std_dir, code_basename, import_code);
|
||||
return add_source_file(g, package, abs_full_path, std_dir, code_basename, import_code);
|
||||
}
|
||||
|
||||
static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
|
||||
PackageTableEntry *package = new_package(ZIG_STD_DIR, "");
|
||||
package->package_table.put(buf_create_from_str("std"), g->std_package);
|
||||
package->package_table.put(buf_create_from_str("@root"), g->root_package);
|
||||
return package;
|
||||
}
|
||||
|
||||
void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
|
||||
Buf source_path = BUF_INIT;
|
||||
os_path_join(src_dir, src_basename, &source_path);
|
||||
|
||||
buf_init_from_buf(&g->root_package->root_src_path, src_basename);
|
||||
|
||||
init(g, &source_path);
|
||||
|
||||
Buf *abs_full_path = buf_alloc();
|
||||
@@ -4027,19 +3875,14 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
|
||||
zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
|
||||
}
|
||||
|
||||
g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);
|
||||
g->root_import = add_source_file(g, g->root_package, abs_full_path, src_dir, src_basename, source_code);
|
||||
|
||||
if (!g->root_out_name) {
|
||||
add_node_error(g, g->root_import->root,
|
||||
buf_sprintf("missing export declaration and output name not provided"));
|
||||
} else if (g->out_type == OutTypeUnknown) {
|
||||
add_node_error(g, g->root_import->root,
|
||||
buf_sprintf("missing export declaration and export type not provided"));
|
||||
}
|
||||
assert(g->root_out_name);
|
||||
assert(g->out_type != OutTypeUnknown);
|
||||
|
||||
if (!g->link_libc && !g->is_test_build) {
|
||||
if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {
|
||||
g->bootstrap_import = add_special_code(g, "bootstrap.zig");
|
||||
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4120,7 +3963,7 @@ void codegen_generate_h_file(CodeGen *g) {
|
||||
assert(proto_node->type == NodeTypeFnProto);
|
||||
AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
|
||||
|
||||
if (fn_proto->visib_mod != VisibModExport)
|
||||
if (fn_proto->top_level_decl.visib_mod != VisibModExport)
|
||||
continue;
|
||||
|
||||
Buf return_type_c = BUF_INIT;
|
||||
|
||||
Reference in New Issue
Block a user