aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhryx <codroid@gmail.com>2019-06-23 12:31:22 -0700
committerhryx <codroid@gmail.com>2019-06-23 12:31:22 -0700
commitc423697c78462f4e817869a3b25e72af33ce09ed (patch)
tree9fa567896dbf4c4b34ac5afc3fa2c899e8275b66 /src
parent1c86a191da400bd47a5044a5b84cf9a05b15066b (diff)
parent9153b17c922e3166a824d300781ca4e6da015787 (diff)
downloadzig-c423697c78462f4e817869a3b25e72af33ce09ed.tar.gz
zig-c423697c78462f4e817869a3b25e72af33ce09ed.zip
Merge branch 'master' into translate-c-userland
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp22
-rw-r--r--src/analyze.cpp42
-rw-r--r--src/analyze.hpp1
-rw-r--r--src/ast_render.cpp8
-rw-r--r--src/buffer.hpp2
-rw-r--r--src/codegen.cpp81
-rw-r--r--src/ir.cpp96
-rw-r--r--src/libc_installation.cpp6
-rw-r--r--src/link.cpp3
-rw-r--r--src/main.cpp29
-rw-r--r--src/os.cpp56
-rw-r--r--src/os.hpp4
-rw-r--r--src/parser.cpp58
-rw-r--r--src/target.cpp4
-rw-r--r--src/target.hpp1
-rw-r--r--src/tokenizer.cpp21
-rw-r--r--src/tokenizer.hpp1
17 files changed, 276 insertions, 159 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2a6bb1feb5..5aa1c78ea1 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -460,6 +460,7 @@ enum NodeType {
NodeTypeContainerInitExpr,
NodeTypeStructValueField,
NodeTypeArrayType,
+ NodeTypeInferredArrayType,
NodeTypeErrorType,
NodeTypeIfErrorExpr,
NodeTypeIfOptional,
@@ -685,6 +686,10 @@ struct AstNodePointerType {
bool is_volatile;
};
+struct AstNodeInferredArrayType {
+ AstNode *child_type;
+};
+
struct AstNodeArrayType {
AstNode *size;
AstNode *child_type;
@@ -989,6 +994,7 @@ struct AstNode {
AstNodeContinueExpr continue_expr;
AstNodeUnreachableExpr unreachable_expr;
AstNodeArrayType array_type;
+ AstNodeInferredArrayType inferred_array_type;
AstNodeErrorType error_type;
AstNodeErrorSetDecl err_set_decl;
AstNodeCancelExpr cancel_expr;
@@ -1328,7 +1334,7 @@ enum FnInline {
FnInlineNever,
};
-struct FnExport {
+struct GlobalExport {
Buf name;
GlobalLinkageId linkage;
};
@@ -1366,7 +1372,7 @@ struct ZigFn {
AstNode *set_cold_node;
- ZigList<FnExport> export_list;
+ ZigList<GlobalExport> export_list;
LLVMValueRef valgrind_client_request_array;
@@ -1890,14 +1896,6 @@ struct CodeGen {
size_t clang_argv_len;
};
-enum VarLinkage {
- VarLinkageInternal,
- VarLinkageExportStrong,
- VarLinkageExportWeak,
- VarLinkageExportLinkOnce,
- VarLinkageExternal,
-};
-
struct ZigVar {
Buf name;
ConstExprValue *const_value;
@@ -1920,8 +1918,9 @@ struct ZigVar {
// this pointer to the redefined variable.
ZigVar *next_var;
+ ZigList<GlobalExport> export_list;
+
uint32_t align_bytes;
- VarLinkage linkage;
bool shadowable;
bool src_is_const;
@@ -2590,6 +2589,7 @@ struct IrInstructionContainerInitList {
IrInstruction base;
IrInstruction *container_type;
+ IrInstruction *elem_type;
size_t item_count;
IrInstruction **items;
LLVMValueRef tmp_ptr;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 0878cf04a7..c7e35367c3 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2712,6 +2712,13 @@ ZigType *get_test_fn_type(CodeGen *g) {
return g->test_fn_type;
}
+void add_var_export(CodeGen *g, ZigVar *var, Buf *symbol_name, GlobalLinkageId linkage) {
+ GlobalExport *global_export = var->export_list.add_one();
+ memset(global_export, 0, sizeof(GlobalExport));
+ buf_init_from_buf(&global_export->name, symbol_name);
+ global_export->linkage = linkage;
+}
+
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) {
if (ccc) {
if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
@@ -2731,8 +2738,8 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
}
}
- FnExport *fn_export = fn_table_entry->export_list.add_one();
- memset(fn_export, 0, sizeof(FnExport));
+ GlobalExport *fn_export = fn_table_entry->export_list.add_one();
+ memset(fn_export, 0, sizeof(GlobalExport));
buf_init_from_buf(&fn_export->name, symbol_name);
fn_export->linkage = linkage;
}
@@ -2780,12 +2787,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope, fn_table_entry);
if (fn_proto->section_expr != nullptr) {
- if (fn_table_entry->body_node == nullptr) {
- add_node_error(g, fn_proto->section_expr,
- buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_table_entry->symbol_name)));
- } else {
- analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name);
- }
+ analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name);
}
if (fn_table_entry->type_entry->id == ZigTypeIdInvalid) {
@@ -3024,6 +3026,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeContainerInitExpr:
case NodeTypeStructValueField:
case NodeTypeArrayType:
+ case NodeTypeInferredArrayType:
case NodeTypeErrorType:
case NodeTypeIfErrorExpr:
case NodeTypeIfOptional:
@@ -3193,15 +3196,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
assert(!is_export || !is_extern);
- VarLinkage linkage;
- if (is_export) {
- linkage = VarLinkageExportStrong;
- } else if (is_extern) {
- linkage = VarLinkageExternal;
- } else {
- linkage = VarLinkageInternal;
- }
-
ConstExprValue *init_value = nullptr;
// TODO more validation for types that can't be used for export/extern variables
@@ -3216,7 +3210,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
if (implicit_type->id == ZigTypeIdUnreachable) {
add_node_error(g, source_node, buf_sprintf("variable initialization is unreachable"));
implicit_type = g->builtin_types.entry_invalid;
- } else if ((!is_const || linkage == VarLinkageExternal) &&
+ } else if ((!is_const || is_extern) &&
(implicit_type->id == ZigTypeIdComptimeFloat ||
implicit_type->id == ZigTypeIdComptimeInt ||
implicit_type->id == ZigTypeIdEnumLiteral))
@@ -3231,7 +3225,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
implicit_type = g->builtin_types.entry_invalid;
}
assert(implicit_type->id == ZigTypeIdInvalid || init_value->special != ConstValSpecialRuntime);
- } else if (linkage != VarLinkageExternal) {
+ } else if (!is_extern) {
add_node_error(g, source_node, buf_sprintf("variables must be initialized"));
implicit_type = g->builtin_types.entry_invalid;
}
@@ -3243,7 +3237,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
tld_var->var = add_variable(g, source_node, tld_var->base.parent_scope, var_decl->symbol,
is_const, init_val, &tld_var->base, type);
- tld_var->var->linkage = linkage;
tld_var->var->is_thread_local = is_thread_local;
if (implicit_type != nullptr && type_is_invalid(implicit_type)) {
@@ -3257,10 +3250,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
}
if (var_decl->section_expr != nullptr) {
- if (var_decl->is_extern) {
- add_node_error(g, var_decl->section_expr,
- buf_sprintf("cannot set section of external variable '%s'", buf_ptr(var_decl->symbol)));
- } else if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) {
+ if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) {
tld_var->section_name = nullptr;
}
}
@@ -3269,6 +3259,10 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
add_node_error(g, source_node, buf_sprintf("threadlocal variable cannot be constant"));
}
+ if (is_export) {
+ add_var_export(g, tld_var->var, &tld_var->var->name, GlobalLinkageIdStrong);
+ }
+
g->global_vars.append(tld_var);
}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 57f1072355..8d78ef86e2 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -198,6 +198,7 @@ ZigPackage *new_anonymous_package(void);
Buf *const_value_to_buffer(ConstExprValue *const_val);
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
+void add_var_export(CodeGen *g, ZigVar *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage);
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index defe40cb19..d93efe2193 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -239,6 +239,8 @@ static const char *node_type_str(NodeType node_type) {
return "ContainerInitExpr";
case NodeTypeArrayType:
return "ArrayType";
+ case NodeTypeInferredArrayType:
+ return "InferredArrayType";
case NodeTypeErrorType:
return "ErrorType";
case NodeTypeIfErrorExpr:
@@ -848,6 +850,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
render_node_ungrouped(ar, node->data.array_type.child_type);
break;
}
+ case NodeTypeInferredArrayType:
+ {
+ fprintf(ar->f, "[_]");
+ render_node_ungrouped(ar, node->data.inferred_array_type.child_type);
+ break;
+ }
case NodeTypePromiseType:
{
fprintf(ar->f, "promise");
diff --git a/src/buffer.hpp b/src/buffer.hpp
index 082d584e2c..d4a911fc21 100644
--- a/src/buffer.hpp
+++ b/src/buffer.hpp
@@ -27,11 +27,13 @@ Buf *buf_sprintf(const char *format, ...)
Buf *buf_vprintf(const char *format, va_list ap);
static inline size_t buf_len(Buf *buf) {
+ assert(buf);
assert(buf->list.length);
return buf->list.length - 1;
}
static inline char *buf_ptr(Buf *buf) {
+ assert(buf);
assert(buf->list.length);
return buf->list.items;
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 12b07ea6bc..3dd6995c61 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -203,6 +203,10 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
get_target_triple(&g->triple_str, g->zig_target);
g->pointer_size_bytes = target_arch_pointer_bit_width(g->zig_target->arch) / 8;
+ if (!target_has_debug_info(g->zig_target)) {
+ g->strip_debug_symbols = true;
+ }
+
return g;
}
@@ -248,6 +252,9 @@ void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
void codegen_set_strip(CodeGen *g, bool strip) {
g->strip_debug_symbols = strip;
+ if (!target_has_debug_info(g->zig_target)) {
+ g->strip_debug_symbols = true;
+ }
}
void codegen_set_out_name(CodeGen *g, Buf *out_name) {
@@ -475,7 +482,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
symbol_name = get_mangled_name(g, unmangled_name, false);
linkage = GlobalLinkageIdInternal;
} else {
- FnExport *fn_export = &fn_table_entry->export_list.items[0];
+ GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
linkage = fn_export->linkage;
}
@@ -529,7 +536,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
}
for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
- FnExport *fn_export = &fn_table_entry->export_list.items[i];
+ GlobalExport *fn_export = &fn_table_entry->export_list.items[i];
LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),
fn_table_entry->llvm_value, buf_ptr(&fn_export->name));
}
@@ -6691,27 +6698,14 @@ static void validate_inline_fns(CodeGen *g) {
}
static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
- if (var->is_thread_local && (!g->is_single_threaded || var->linkage != VarLinkageInternal)) {
+ bool is_extern = var->decl_node->data.variable_declaration.is_extern;
+ bool is_export = var->decl_node->data.variable_declaration.is_export;
+ bool is_internal_linkage = !is_extern && !is_export;
+ if (var->is_thread_local && (!g->is_single_threaded || !is_internal_linkage)) {
LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
}
}
-static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) {
- switch (var_linkage) {
- case VarLinkageInternal:
- return LLVMInternalLinkage;
- case VarLinkageExportStrong:
- return LLVMExternalLinkage;
- case VarLinkageExportWeak:
- return LLVMWeakODRLinkage;
- case VarLinkageExportLinkOnce:
- return LLVMLinkOnceODRLinkage;
- case VarLinkageExternal:
- return LLVMExternalLinkage;
- }
- zig_unreachable();
-}
-
static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
@@ -6761,31 +6755,48 @@ static void do_code_gen(CodeGen *g) {
assert(var->decl_node);
+ GlobalLinkageId linkage;
+ Buf *unmangled_name = &var->name;
+ Buf *symbol_name;
+ if (var->export_list.length == 0) {
+ if (var->decl_node->data.variable_declaration.is_extern) {
+ symbol_name = unmangled_name;
+ linkage = GlobalLinkageIdStrong;
+ } else {
+ symbol_name = get_mangled_name(g, unmangled_name, false);
+ linkage = GlobalLinkageIdInternal;
+ }
+ } else {
+ GlobalExport *global_export = &var->export_list.items[0];
+ symbol_name = &global_export->name;
+ linkage = global_export->linkage;
+ }
+
LLVMValueRef global_value;
- if (var->linkage == VarLinkageExternal) {
- LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name));
+ bool externally_initialized = var->decl_node->data.variable_declaration.expr == nullptr;
+ if (externally_initialized) {
+ LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(symbol_name));
if (existing_llvm_var) {
global_value = LLVMConstBitCast(existing_llvm_var,
LLVMPointerType(get_llvm_type(g, var->var_type), 0));
} else {
- global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(&var->name));
+ global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(symbol_name));
// TODO debug info for the extern variable
- LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
+ LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
set_global_tls(g, var, global_value);
}
} else {
- bool exported = (var->linkage != VarLinkageInternal);
- const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
- render_const_val(g, var->const_value, mangled_name);
- render_const_val_global(g, var->const_value, mangled_name);
+ bool exported = (linkage != GlobalLinkageIdInternal);
+ render_const_val(g, var->const_value, buf_ptr(symbol_name));
+ render_const_val_global(g, var->const_value, buf_ptr(symbol_name));
global_value = var->const_value->global_refs->llvm_global;
if (exported) {
- LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
+ LLVMSetLinkage(global_value, to_llvm_linkage(linkage));
maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
@@ -6805,6 +6816,11 @@ static void do_code_gen(CodeGen *g) {
}
var->value_ref = global_value;
+
+ for (size_t export_i = 1; export_i < var->export_list.length; export_i += 1) {
+ GlobalExport *global_export = &var->export_list.items[export_i];
+ LLVMAddAlias(g->module, LLVMTypeOf(var->value_ref), var->value_ref, buf_ptr(&global_export->name));
+ }
}
// Generate function definitions.
@@ -7505,7 +7521,7 @@ static bool detect_single_threaded(CodeGen *g) {
}
static bool detect_err_ret_tracing(CodeGen *g) {
- return !target_is_wasm(g->zig_target) &&
+ return !g->strip_debug_symbols &&
g->build_mode != BuildModeFastRelease &&
g->build_mode != BuildModeSmallRelease;
}
@@ -7939,6 +7955,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
+ buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
{
TargetSubsystem detected_subsystem = detect_subsystem(g);
@@ -7979,6 +7996,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
// Only a few things affect builtin.zig
cache_buf(&cache_hash, compiler_id);
cache_int(&cache_hash, g->build_mode);
+ cache_bool(&cache_hash, g->strip_debug_symbols);
cache_bool(&cache_hash, g->is_test_build);
cache_bool(&cache_hash, g->is_single_threaded);
cache_int(&cache_hash, g->zig_target->is_native);
@@ -8783,6 +8801,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
Termination term;
ZigList<const char *> args = {};
+ args.append(buf_ptr(self_exe_path));
args.append("cc");
Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
@@ -8801,7 +8820,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
if (g->verbose_cc) {
print_zig_cc_cmd("zig", &args);
}
- os_spawn_process(buf_ptr(self_exe_path), args, &term);
+ os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nThe following command failed:\n");
print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
@@ -9168,7 +9187,7 @@ static void gen_h_file(CodeGen *g) {
if (fn_table_entry->export_list.length == 0) {
symbol_name = &fn_table_entry->symbol_name;
} else {
- FnExport *fn_export = &fn_table_entry->export_list.items[0];
+ GlobalExport *fn_export = &fn_table_entry->export_list.items[0];
symbol_name = &fn_export->name;
}
diff --git a/src/ir.cpp b/src/ir.cpp
index fb9e7b51c7..b74a99b37d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1427,15 +1427,17 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *container_type, size_t item_count, IrInstruction **items)
+ IrInstruction *container_type, IrInstruction *elem_type, size_t item_count, IrInstruction **items)
{
IrInstructionContainerInitList *container_init_list_instruction =
ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
container_init_list_instruction->container_type = container_type;
+ container_init_list_instruction->elem_type = elem_type;
container_init_list_instruction->item_count = item_count;
container_init_list_instruction->items = items;
if (container_type != nullptr) ir_ref_instruction(container_type, irb->current_basic_block);
+ if (elem_type != nullptr) ir_ref_instruction(elem_type, irb->current_basic_block);
for (size_t i = 0; i < item_count; i += 1) {
ir_ref_instruction(items[i], irb->current_basic_block);
}
@@ -5396,11 +5398,25 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
ContainerInitKind kind = container_init_expr->kind;
- IrInstruction *container_type = ir_gen_node(irb, container_init_expr->type, scope);
- if (container_type == irb->codegen->invalid_instruction)
- return container_type;
+ IrInstruction *container_type = nullptr;
+ IrInstruction *elem_type = nullptr;
+ if (container_init_expr->type->type == NodeTypeInferredArrayType) {
+ elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope);
+ if (elem_type == irb->codegen->invalid_instruction)
+ return elem_type;
+ } else {
+ container_type = ir_gen_node(irb, container_init_expr->type, scope);
+ if (container_type == irb->codegen->invalid_instruction)
+ return container_type;
+ }
if (kind == ContainerInitKindStruct) {
+ if (elem_type != nullptr) {
+ add_node_error(irb->codegen, container_init_expr->type,
+ buf_sprintf("initializing array with struct syntax"));
+ return irb->codegen->invalid_instruction;
+ }
+
size_t field_count = container_init_expr->entries.length;
IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
for (size_t i = 0; i < field_count; i += 1) {
@@ -5429,7 +5445,7 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
values[i] = expr_value;
}
- return ir_build_container_init_list(irb, scope, node, container_type, item_count, values);
+ return ir_build_container_init_list(irb, scope, node, container_type, elem_type, item_count, values);
} else {
zig_unreachable();
}
@@ -7693,6 +7709,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_suspend(irb, scope, node), lval);
case NodeTypeEnumLiteral:
return ir_lval_wrap(irb, scope, ir_gen_enum_literal(irb, scope, node), lval);
+ case NodeTypeInferredArrayType:
+ add_node_error(irb->codegen, node,
+ buf_sprintf("inferred array size invalid here"));
+ return irb->codegen->invalid_instruction;
}
zig_unreachable();
}
@@ -13771,20 +13791,6 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
}
-static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) {
- switch (id) {
- case GlobalLinkageIdStrong:
- return VarLinkageExportStrong;
- case GlobalLinkageIdWeak:
- return VarLinkageExportWeak;
- case GlobalLinkageIdLinkOnce:
- return VarLinkageExportLinkOnce;
- case GlobalLinkageIdInternal:
- return VarLinkageInternal;
- }
- zig_unreachable();
-}
-
static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
IrInstruction *name = instruction->name->child;
Buf *symbol_name = ir_resolve_str(ira, name);
@@ -13881,6 +13887,15 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
want_var_export = true;
}
break;
+ case ZigTypeIdArray:
+ if (!type_allowed_in_extern(ira->codegen, target->value.type->data.array.child_type)) {
+ ir_add_error(ira, target,
+ buf_sprintf("array element type '%s' not extern-compatible",
+ buf_ptr(&target->value.type->data.array.child_type->name)));
+ } else {
+ want_var_export = true;
+ }
+ break;
case ZigTypeIdMetaType: {
ZigType *type_value = target->value.data.x_type;
switch (type_value->id) {
@@ -13948,7 +13963,6 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
- case ZigTypeIdArray:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdUndefined:
@@ -13974,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
if (load_ptr->ptr->id == IrInstructionIdVarPtr) {
IrInstructionVarPtr *var_ptr = reinterpret_cast<IrInstructionVarPtr *>(load_ptr->ptr);
ZigVar *var = var_ptr->var;
- var->linkage = global_linkage_to_var_linkage(global_linkage_id);
+ add_var_export(ira->codegen, var, symbol_name, global_linkage_id);
}
}
@@ -14267,7 +14281,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
ConstExprValue *mem_slot = nullptr;
bool comptime_var_mem = ir_get_var_is_comptime(var);
- bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal;
+ bool linkage_makes_it_runtime = var->decl_node->data.variable_declaration.is_extern;
bool is_const = var->src_is_const;
bool is_volatile = false;
@@ -16780,7 +16794,9 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
case ZigTypeIdPromise:
case ZigTypeIdVector:
{
- if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
+ ResolveStatus needed_status = (align_bytes == 0) ?
+ ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
+ if ((err = type_resolve(ira->codegen, child_type, needed_status)))
return ira->codegen->invalid_instruction;
ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero);
@@ -17961,16 +17977,31 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
{
Error err;
- ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
- if (type_is_invalid(container_type))
- return ira->codegen->invalid_instruction;
-
size_t elem_count = instruction->item_count;
- if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
+ ZigType *container_type;
+ if (instruction->container_type != nullptr) {
+ container_type = ir_resolve_type(ira, instruction->container_type->child);
+ if (type_is_invalid(container_type))
+ return ira->codegen->invalid_instruction;
+ } else {
+ ZigType *elem_type = ir_resolve_type(ira, instruction->elem_type->child);
+ if (type_is_invalid(elem_type))
+ return ira->codegen->invalid_instruction;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown))) {
+ return ira->codegen->invalid_instruction;
+ }
+ container_type = get_array_type(ira->codegen, elem_type, elem_count);
+ }
+
+ if (is_slice(container_type)) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("expected array type or [_], found slice"));
+ return ira->codegen->invalid_instruction;
+ } else if (container_type->id == ZigTypeIdStruct && !is_slice(container_type) && elem_count == 0) {
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
0, nullptr);
- } else if (is_slice(container_type) || container_type->id == ZigTypeIdArray) {
+ } else if (container_type->id == ZigTypeIdArray) {
// array is same as slice init but we make a compile error if the length is wrong
ZigType *child_type;
if (container_type->id == ZigTypeIdArray) {
@@ -18057,7 +18088,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
IrInstruction *new_instruction = ir_build_container_init_list(&ira->new_irb,
instruction->base.scope, instruction->base.source_node,
- nullptr, elem_count, new_items);
+ nullptr, nullptr, elem_count, new_items);
new_instruction->value.type = fixed_size_array_type;
ir_add_alloca(ira, new_instruction, fixed_size_array_type);
return new_instruction;
@@ -18584,10 +18615,11 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
true, false, PtrLenUnknown,
0, 0, 0, false);
fn_decl_fields[6].type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
- if (fn_node->is_extern && buf_len(fn_node->lib_name) > 0) {
+ if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {
fn_decl_fields[6].data.x_optional = create_const_vals(1);
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
- init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0, buf_len(fn_node->lib_name), true);
+ init_const_slice(ira->codegen, fn_decl_fields[6].data.x_optional, lib_name, 0,
+ buf_len(fn_node->lib_name), true);
} else {
fn_decl_fields[6].data.x_optional = nullptr;
}
diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp
index d1773b89e7..135941dc40 100644
--- a/src/libc_installation.cpp
+++ b/src/libc_installation.cpp
@@ -153,6 +153,7 @@ static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, b
const char *cc_exe = getenv("CC");
cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
ZigList<const char *> args = {};
+ args.append(cc_exe);
args.append("-E");
args.append("-Wp,-v");
args.append("-xc");
@@ -166,7 +167,7 @@ static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, b
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
Error err;
- if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
if (verbose) {
fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
}
@@ -277,12 +278,13 @@ Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirnam
const char *cc_exe = getenv("CC");
cc_exe = (cc_exe == nullptr) ? CC_EXE : cc_exe;
ZigList<const char *> args = {};
+ args.append(cc_exe);
args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
Termination term;
Buf *out_stderr = buf_alloc();
Buf *out_stdout = buf_alloc();
Error err;
- if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ if ((err = os_exec_process(args, &term, out_stderr, out_stdout))) {
if (err == ErrorFileNotFound)
return ErrorNoCCompilerInstalled;
if (verbose) {
diff --git a/src/link.cpp b/src/link.cpp
index 3a437e4eda..277dcbc5c6 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -1721,10 +1721,11 @@ void codegen_link(CodeGen *g) {
if (g->system_linker_hack && g->zig_target->os == OsMacOSX) {
Termination term;
ZigList<const char *> args = {};
+ args.append("ld");
for (size_t i = 1; i < lj.args.length; i += 1) {
args.append(lj.args.at(i));
}
- os_spawn_process("ld", args, &term);
+ os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
exit(1);
}
diff --git a/src/main.cpp b/src/main.cpp
index 29c17212cf..9b1892061b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -467,6 +467,7 @@ int main(int argc, char **argv) {
init_all_targets();
ZigList<const char *> args = {0};
+ args.append(NULL); // placeholder
args.append(zig_exe_path);
args.append(NULL); // placeholder
args.append(NULL); // placeholder
@@ -525,8 +526,8 @@ int main(int argc, char **argv) {
g->enable_time_report = timing_info;
codegen_set_out_name(g, buf_create_from_str("build"));
- args.items[1] = buf_ptr(&build_file_dirname);
- args.items[2] = buf_ptr(&full_cache_dir);
+ args.items[2] = buf_ptr(&build_file_dirname);
+ args.items[3] = buf_ptr(&full_cache_dir);
bool build_file_exists;
if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
@@ -580,12 +581,14 @@ int main(int argc, char **argv) {
codegen_build_and_link(g);
Termination term;
- os_spawn_process(buf_ptr(&g->output_file_path), args, &term);
+ args.items[0] = buf_ptr(&g->output_file_path);
+ os_spawn_process(args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nBuild failed. The following command failed:\n");
- fprintf(stderr, "%s", buf_ptr(&g->output_file_path));
+ const char *prefix = "";
for (size_t i = 0; i < args.length; i += 1) {
- fprintf(stderr, " %s", args.at(i));
+ fprintf(stderr, "%s%s", prefix, args.at(i));
+ prefix = " ";
}
fprintf(stderr, "\n");
}
@@ -954,6 +957,7 @@ int main(int argc, char **argv) {
case CmdBuiltin: {
CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
out_type, build_mode, override_lib_dir, override_std_dir, nullptr, nullptr);
+ codegen_set_strip(g, strip);
g->subsystem = subsystem;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
@@ -1160,7 +1164,7 @@ int main(int argc, char **argv) {
args.pop();
Termination term;
- os_spawn_process(exec_path, args, &term);
+ os_spawn_process(args, &term);
return term.code;
} else if (cmd == CmdBuild) {
if (g->enable_cache) {
@@ -1212,17 +1216,10 @@ int main(int argc, char **argv) {
}
Termination term;
- if (test_exec_args.length > 0) {
- ZigList<const char *> rest_args = {0};
- for (size_t i = 1; i < test_exec_args.length; i += 1) {
- rest_args.append(test_exec_args.at(i));
- }
- os_spawn_process(test_exec_args.items[0], rest_args, &term);
- } else {
- ZigList<const char *> no_args = {0};
- os_spawn_process(buf_ptr(test_exe_path), no_args, &term);
+ if (test_exec_args.length == 0) {
+ test_exec_args.append(buf_ptr(test_exe_path));
}
-
+ os_spawn_process(test_exec_args, &term);
if (term.how != TerminationIdClean || term.code != 0) {
fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
diff --git a/src/os.cpp b/src/os.cpp
index e3d223325f..5fa70bd260 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -105,16 +105,15 @@ static void populate_termination(Termination *term, int status) {
}
}
-static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {
- const char **argv = allocate<const char *>(args.length + 2);
- argv[0] = exe;
- argv[args.length + 1] = nullptr;
+static void os_spawn_process_posix(ZigList<const char *> &args, Termination *term) {
+ const char **argv = allocate<const char *>(args.length + 1);
for (size_t i = 0; i < args.length; i += 1) {
- argv[i + 1] = args.at(i);
+ argv[i] = args.at(i);
}
+ argv[args.length] = nullptr;
pid_t pid;
- int rc = posix_spawnp(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ);
+ int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast<char *const*>(argv), environ);
if (rc != 0) {
zig_panic("posix_spawn failed: %s", strerror(rc));
}
@@ -126,16 +125,14 @@ static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args,
#endif
#if defined(ZIG_OS_WINDOWS)
-static void os_windows_create_command_line(Buf *command_line, const char *exe, ZigList<const char *> &args) {
- buf_resize(command_line, 0);
-
- buf_append_char(command_line, '\"');
- buf_append_str(command_line, exe);
- buf_append_char(command_line, '\"');
+static void os_windows_create_command_line(Buf *command_line, ZigList<const char *> &args) {
+ buf_resize(command_line, 0);
+ const char *prefix = "\"";
for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) {
- buf_append_str(command_line, " \"");
const char *arg = args.at(arg_i);
+ buf_append_str(command_line, prefix);
+ prefix = " \"";
size_t arg_len = strlen(arg);
for (size_t c_i = 0; c_i < arg_len; c_i += 1) {
if (arg[c_i] == '\"') {
@@ -147,14 +144,15 @@ static void os_windows_create_command_line(Buf *command_line, const char *exe, Z
}
}
-static void os_spawn_process_windows(const char *exe, ZigList<const char *> &args, Termination *term) {
+static void os_spawn_process_windows(ZigList<const char *> &args, Termination *term) {
Buf command_line = BUF_INIT;
- os_windows_create_command_line(&command_line, exe, args);
+ os_windows_create_command_line(&command_line, args);
PROCESS_INFORMATION piProcInfo = {0};
STARTUPINFO siStartInfo = {0};
siStartInfo.cb = sizeof(STARTUPINFO);
+ const char *exe = args.at(0);
BOOL success = CreateProcessA(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
&siStartInfo, &piProcInfo);
@@ -173,11 +171,11 @@ static void os_spawn_process_windows(const char *exe, ZigList<const char *> &arg
}
#endif
-void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term) {
+void os_spawn_process(ZigList<const char *> &args, Termination *term) {
#if defined(ZIG_OS_WINDOWS)
- os_spawn_process_windows(exe, args, term);
+ os_spawn_process_windows(args, term);
#elif defined(ZIG_OS_POSIX)
- os_spawn_process_posix(exe, args, term);
+ os_spawn_process_posix(args, term);
#else
#error "missing os_spawn_process implementation"
#endif
@@ -785,7 +783,7 @@ Error os_file_exists(Buf *full_path, bool *result) {
}
#if defined(ZIG_OS_POSIX)
-static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
+static Error os_exec_process_posix(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
int stdin_pipe[2];
@@ -817,13 +815,12 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
if (dup2(stderr_pipe[1], STDERR_FILENO) == -1)
zig_panic("dup2 failed");
- const char **argv = allocate<const char *>(args.length + 2);
- argv[0] = exe;
- argv[args.length + 1] = nullptr;
+ const char **argv = allocate<const char *>(args.length + 1);
+ argv[args.length] = nullptr;
for (size_t i = 0; i < args.length; i += 1) {
- argv[i + 1] = args.at(i);
+ argv[i] = args.at(i);
}
- execvp(exe, const_cast<char * const *>(argv));
+ execvp(argv[0], const_cast<char * const *>(argv));
Error report_err = ErrorUnexpected;
if (errno == ENOENT) {
report_err = ErrorFileNotFound;
@@ -874,11 +871,11 @@ static Error os_exec_process_posix(const char *exe, ZigList<const char *> &args,
// LocalFree(messageBuffer);
//}
-static Error os_exec_process_windows(const char *exe, ZigList<const char *> &args,
+static Error os_exec_process_windows(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
Buf command_line = BUF_INIT;
- os_windows_create_command_line(&command_line, exe, args);
+ os_windows_create_command_line(&command_line, args);
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
@@ -925,6 +922,7 @@ static Error os_exec_process_windows(const char *exe, ZigList<const char *> &arg
siStartInfo.hStdInput = g_hChildStd_IN_Rd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+ const char *exe = args.at(0);
BOOL success = CreateProcess(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,
&siStartInfo, &piProcInfo);
@@ -1005,13 +1003,13 @@ Error os_execv(const char *exe, const char **argv) {
#endif
}
-Error os_exec_process(const char *exe, ZigList<const char *> &args,
+Error os_exec_process(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout)
{
#if defined(ZIG_OS_WINDOWS)
- return os_exec_process_windows(exe, args, term, out_stderr, out_stdout);
+ return os_exec_process_windows(args, term, out_stderr, out_stdout);
#elif defined(ZIG_OS_POSIX)
- return os_exec_process_posix(exe, args, term, out_stderr, out_stdout);
+ return os_exec_process_posix(args, term, out_stderr, out_stdout);
#else
#error "missing os_exec_process implementation"
#endif
diff --git a/src/os.hpp b/src/os.hpp
index 058bb2020c..c8135e9844 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -100,8 +100,8 @@ struct OsFileAttr {
int os_init(void);
-void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
-Error os_exec_process(const char *exe, ZigList<const char *> &args,
+void os_spawn_process(ZigList<const char *> &args, Termination *term);
+Error os_exec_process(ZigList<const char *> &args,
Termination *term, Buf *out_stderr, Buf *out_stdout);
Error os_execv(const char *exe, const char **argv);
diff --git a/src/parser.cpp b/src/parser.cpp
index 3d7bbf7801..33f8836ef3 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -288,6 +288,9 @@ static AstNode *ast_parse_prefix_op_expr(
case NodeTypeArrayType:
right = &prefix->data.array_type.child_type;
break;
+ case NodeTypeInferredArrayType:
+ right = &prefix->data.inferred_array_type.child_type;
+ break;
case NodeTypePointerType: {
// We might get two pointers from *_ptr_type_start
AstNode *child = prefix->data.pointer_type.op_expr;
@@ -887,6 +890,11 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
+ if (body == nullptr) {
+ Token *tok = eat_token(pc);
+ ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id));
+ }
+
Token *err_payload = nullptr;
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
@@ -991,6 +999,11 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
+ if (body == nullptr) {
+ Token *tok = eat_token(pc);
+ ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
+ }
+
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
else_body = ast_expect(pc, ast_parse_statement);
@@ -1020,6 +1033,11 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) {
body = ast_parse_assign_expr(pc);
}
+ if (body == nullptr) {
+ Token *tok = eat_token(pc);
+ ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id));
+ }
+
Token *err_payload = nullptr;
AstNode *else_body = nullptr;
if (eat_token_if(pc, TokenIdKeywordElse) != nullptr) {
@@ -1852,11 +1870,15 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {
// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
- if (eat_token_if(pc, TokenIdLBracket) == nullptr)
- return nullptr;
-
- Token *sym_name = expect_token(pc, TokenIdSymbol);
- expect_token(pc, TokenIdRBracket);
+ Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
+ if (sym_name == nullptr) {
+ if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
+ return nullptr;
+ } else {
+ sym_name = expect_token(pc, TokenIdSymbol);
+ expect_token(pc, TokenIdRBracket);
+ }
+ }
Token *str = expect_token(pc, TokenIdStringLiteral);
expect_token(pc, TokenIdLParen);
@@ -1871,7 +1893,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
expect_token(pc, TokenIdRParen);
AsmOutput *res = allocate<AsmOutput>(1);
- res->asm_symbolic_name = token_buf(sym_name);
+ res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
res->constraint = token_buf(str);
res->variable_name = token_buf(var_name);
res->return_type = return_type;
@@ -1894,18 +1916,23 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {
// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
- if (eat_token_if(pc, TokenIdLBracket) == nullptr)
- return nullptr;
+ Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
+ if (sym_name == nullptr) {
+ if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
+ return nullptr;
+ } else {
+ sym_name = expect_token(pc, TokenIdSymbol);
+ expect_token(pc, TokenIdRBracket);
+ }
+ }
- Token *sym_name = expect_token(pc, TokenIdSymbol);
- expect_token(pc, TokenIdRBracket);
Token *constraint = expect_token(pc, TokenIdStringLiteral);
expect_token(pc, TokenIdLParen);
AstNode *expr = ast_expect(pc, ast_parse_expr);
expect_token(pc, TokenIdRParen);
AsmInput *res = allocate<AsmInput>(1);
- res->asm_symbolic_name = token_buf(sym_name);
+ res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
res->constraint = token_buf(constraint);
res->expr = expr;
return res;
@@ -2597,6 +2624,12 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
return ptr;
}
+ Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
+ if (arr_init != nullptr) {
+ return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);
+ }
+
+
return nullptr;
}
@@ -3003,6 +3036,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.array_type.child_type, visit, context);
visit_field(&node->data.array_type.align_expr, visit, context);
break;
+ case NodeTypeInferredArrayType:
+ visit_field(&node->data.array_type.child_type, visit, context);
+ break;
case NodeTypePromiseType:
visit_field(&node->data.promise_type.payload_type, visit, context);
break;
diff --git a/src/target.cpp b/src/target.cpp
index 7862f6d449..1d74304584 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -1585,3 +1585,7 @@ void target_libc_enum(size_t index, ZigTarget *out_target) {
out_target->vendor = ZigLLVM_UnknownVendor;
out_target->is_native = false;
}
+
+bool target_has_debug_info(const ZigTarget *target) {
+ return !target_is_wasm(target);
+}
diff --git a/src/target.hpp b/src/target.hpp
index 7fa99bcda8..7fca430df6 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -177,6 +177,7 @@ bool target_is_musl(const ZigTarget *target);
bool target_is_wasm(const ZigTarget *target);
bool target_is_single_threaded(const ZigTarget *target);
bool target_supports_stack_probing(const ZigTarget *target);
+bool target_has_debug_info(const ZigTarget *target);
uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch);
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 7bae45f477..a0acde52e9 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -224,6 +224,7 @@ enum TokenizeState {
TokenizeStateLBracket,
TokenizeStateLBracketStar,
TokenizeStateLBracketStarC,
+ TokenizeStateLBracketUnderscore,
};
@@ -774,6 +775,9 @@ void tokenize(Buf *buf, Tokenization *out) {
case '*':
t.state = TokenizeStateLBracketStar;
break;
+ case '_':
+ t.state = TokenizeStateLBracketUnderscore;
+ break;
default:
// reinterpret as just an lbracket
t.pos -= 1;
@@ -782,6 +786,21 @@ void tokenize(Buf *buf, Tokenization *out) {
continue;
}
break;
+ case TokenizeStateLBracketUnderscore:
+ switch (c) {
+ case ']':
+ set_token_id(&t, t.cur_tok, TokenIdBracketUnderscoreBracket);
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ // reinterpret as just an lbracket
+ t.pos -= 2;
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ continue;
+ }
+ break;
case TokenizeStateLBracketStar:
switch (c) {
case 'c':
@@ -1443,6 +1462,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateLineStringContinueC:
case TokenizeStateLBracketStar:
case TokenizeStateLBracketStarC:
+ case TokenizeStateLBracketUnderscore:
tokenize_error(&t, "unexpected EOF");
break;
case TokenizeStateLineComment:
@@ -1581,6 +1601,7 @@ const char * token_name(TokenId id) {
case TokenIdTimesPercent: return "*%";
case TokenIdTimesPercentEq: return "*%=";
case TokenIdBarBarEq: return "||=";
+ case TokenIdBracketUnderscoreBracket: return "[_]";
case TokenIdCount:
zig_unreachable();
}
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index b17d056109..d5174c24de 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -30,6 +30,7 @@ enum TokenId {
TokenIdBitXorEq,
TokenIdBracketStarBracket,
TokenIdBracketStarCBracket,
+ TokenIdBracketUnderscoreBracket,
TokenIdCharLiteral,
TokenIdCmpEq,
TokenIdCmpGreaterOrEq,