From b735764898412c5b9388fdf729c8ad8db43ddde5 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 9 Jun 2019 19:24:24 -0400 Subject: different array literal syntax when inferring the size old syntax: []i32{1, 2, 3} new syntax: [_]i32{1, 2, 3} closes #1797 --- src/all_types.hpp | 7 +++++++ src/analyze.cpp | 1 + src/ast_render.cpp | 8 ++++++++ src/ir.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++----------- src/parser.cpp | 43 +++++++++++++++++++++++++++++---------- src/tokenizer.cpp | 21 +++++++++++++++++++ src/tokenizer.hpp | 1 + 7 files changed, 117 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/all_types.hpp b/src/all_types.hpp index 2a6bb1feb5..1a7e2a910b 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; @@ -2590,6 +2596,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..cbf293c7fe 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3024,6 +3024,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: 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/ir.cpp b/src/ir.cpp index fb9e7b51c7..21d2646c3e 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(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(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(); } @@ -17961,16 +17981,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 +18092,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; diff --git a/src/parser.cpp b/src/parser.cpp index 3d7bbf7801..89836f9bc8 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; @@ -1852,11 +1855,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 +1878,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { expect_token(pc, TokenIdRParen); AsmOutput *res = allocate(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 +1901,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(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 +2609,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 +3021,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/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, -- cgit v1.2.3 From 6c160b8856921e5e1d0a437794b3b7ee7e1a4d0b Mon Sep 17 00:00:00 2001 From: SamTebbs33 Date: Sat, 8 Jun 2019 15:58:11 +0100 Subject: Add check for null body in if, for and while --- src/parser.cpp | 15 +++++++++++++++ test/compile_errors.zig | 27 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) (limited to 'src') diff --git a/src/parser.cpp b/src/parser.cpp index 89836f9bc8..af98a4be93 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -890,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) { @@ -994,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); @@ -1023,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) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 15ac7d6f1b..7896a0b732 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -230,6 +230,33 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:10:25: error: expression value is ignored", ); + cases.add( + "empty while loop body", + \\export fn a() void { + \\ while(true); + \\} + , + "tmp.zig:2:16: error: expected loop body, found ';'", + ); + + cases.add( + "empty for loop body", + \\export fn a() void { + \\ for(undefined) |x|; + \\} + , + "tmp.zig:2:23: error: expected loop body, found ';'", + ); + + cases.add( + "empty if body", + \\export fn a() void { + \\ if(true); + \\} + , + "tmp.zig:2:13: error: expected if body, found ';'", + ); + cases.add( "import outside package path", \\comptime{ -- cgit v1.2.3 From b7811d32690a9f3b4912635e16e6aa5ace25362c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 10 Jun 2019 00:45:24 -0400 Subject: whitespace cleanup --- src/parser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/parser.cpp b/src/parser.cpp index af98a4be93..33f8836ef3 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -891,7 +891,7 @@ static AstNode *ast_parse_if_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); + Token *tok = eat_token(pc); ast_error(pc, tok, "expected if body, found '%s'", token_name(tok->id)); } @@ -1000,7 +1000,7 @@ static AstNode *ast_parse_for_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); + Token *tok = eat_token(pc); ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); } @@ -1034,7 +1034,7 @@ static AstNode *ast_parse_while_statement(ParseContext *pc) { } if (body == nullptr) { - Token *tok = eat_token(pc); + Token *tok = eat_token(pc); ast_error(pc, tok, "expected loop body, found '%s'", token_name(tok->id)); } -- cgit v1.2.3 From 42ea2d0d1c3b8cafdfc9a383cbb1bab274eb0140 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 15:20:52 -0400 Subject: fix `@export` for arrays and allow sections on extern variables previously `@export` for an array would panic with a TODO message. now it will do the export. However, it uses the variable's name rather than the name passed to `@export`. Issue #2679 remains open for that problem. --- src/analyze.cpp | 12 ++---------- src/ir.cpp | 10 +++++++++- test/compile_errors.zig | 20 -------------------- 3 files changed, 11 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/analyze.cpp b/src/analyze.cpp index cbf293c7fe..04665cc53b 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2780,12 +2780,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) { @@ -3258,10 +3253,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; } } diff --git a/src/ir.cpp b/src/ir.cpp index 21d2646c3e..a1227fbd93 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13901,6 +13901,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) { @@ -13968,7 +13977,6 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio case ZigTypeIdInt: case ZigTypeIdFloat: case ZigTypeIdPointer: - case ZigTypeIdArray: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdUndefined: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 7896a0b732..e85b2f3395 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4645,16 +4645,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:1: note: declared here", ); - cases.add( - "setting a section on an extern variable", - \\extern var foo: i32 linksection(".text2"); - \\export fn entry() i32 { - \\ return foo; - \\} - , - "tmp.zig:1:33: error: cannot set section of external variable 'foo'", - ); - cases.add( "setting a section on a local variable", \\export fn entry() i32 { @@ -4665,16 +4655,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:30: error: cannot set section of local variable 'foo'", ); - cases.add( - "setting a section on an extern fn", - \\extern fn foo() linksection(".text2") void; - \\export fn entry() void { - \\ foo(); - \\} - , - "tmp.zig:1:29: error: cannot set section of external function 'foo'", - ); - cases.add( "returning address of local variable - simple", \\export fn foo() *i32 { -- cgit v1.2.3 From f8f054b354088eb9e76d9207972022bc1d3dfc28 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 17:23:24 -0400 Subject: fix `@export` for arrays not respecting the symbol name Previously, the symbol name parameter of `@export` would be ignored for variables, and the variable name would be used for the symbol name. Now it works as expected. See #2679 --- doc/langref.html.in | 2 +- src/all_types.hpp | 15 ++++-------- src/analyze.cpp | 29 ++++++++++++----------- src/analyze.hpp | 1 + src/codegen.cpp | 67 ++++++++++++++++++++++++++++++----------------------- src/ir.cpp | 18 ++------------ 6 files changed, 61 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/doc/langref.html.in b/doc/langref.html.in index 2623a9d467..c18528a2db 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6648,7 +6648,7 @@ test "main" { {#header_close#} {#header_open|@export#} -
{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8{#endsyntax#}
+
{#syntax#}@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void{#endsyntax#}

Creates a symbol in the output object file.

diff --git a/src/all_types.hpp b/src/all_types.hpp index 1a7e2a910b..5aa1c78ea1 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1334,7 +1334,7 @@ enum FnInline { FnInlineNever, }; -struct FnExport { +struct GlobalExport { Buf name; GlobalLinkageId linkage; }; @@ -1372,7 +1372,7 @@ struct ZigFn { AstNode *set_cold_node; - ZigList export_list; + ZigList export_list; LLVMValueRef valgrind_client_request_array; @@ -1896,14 +1896,6 @@ struct CodeGen { size_t clang_argv_len; }; -enum VarLinkage { - VarLinkageInternal, - VarLinkageExportStrong, - VarLinkageExportWeak, - VarLinkageExportLinkOnce, - VarLinkageExternal, -}; - struct ZigVar { Buf name; ConstExprValue *const_value; @@ -1926,8 +1918,9 @@ struct ZigVar { // this pointer to the redefined variable. ZigVar *next_var; + ZigList export_list; + uint32_t align_bytes; - VarLinkage linkage; bool shadowable; bool src_is_const; diff --git a/src/analyze.cpp b/src/analyze.cpp index 04665cc53b..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; } @@ -3189,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 @@ -3212,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)) @@ -3227,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; } @@ -3239,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)) { @@ -3262,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/codegen.cpp b/src/codegen.cpp index 12b07ea6bc..bdc8de63d1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -475,7 +475,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 +529,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 +6691,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 +6748,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 +6809,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. @@ -9168,7 +9177,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 a1227fbd93..6c1c84da3b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -13791,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); @@ -14002,7 +13988,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio if (load_ptr->ptr->id == IrInstructionIdVarPtr) { IrInstructionVarPtr *var_ptr = reinterpret_cast(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); } } @@ -14295,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; -- cgit v1.2.3 From 362c79140fc0638b0f85ed9b2a49f3fead14bb9b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 18:18:43 -0400 Subject: expose builtin.strip_debug_info zig code now can be made aware that it will not have any debug information available at runtime. --- src/codegen.cpp | 2 ++ src/main.cpp | 1 + 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/codegen.cpp b/src/codegen.cpp index bdc8de63d1..88168caff8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7948,6 +7948,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); @@ -7988,6 +7989,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); diff --git a/src/main.cpp b/src/main.cpp index 29c17212cf..9c14ba3250 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -954,6 +954,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; -- cgit v1.2.3 From 7c5ceb0c4cdf5fafadd92b13048bc9878554abc4 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 14 Jun 2019 18:45:41 -0400 Subject: standard library integrates with knowledge of stripped debug info --- src/codegen.cpp | 9 ++++++++- src/target.cpp | 4 ++++ src/target.hpp | 1 + std/debug.zig | 11 +++++++---- 4 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/codegen.cpp b/src/codegen.cpp index 88168caff8..cee8c0ec0c 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) { @@ -7514,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; } 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/std/debug.zig b/std/debug.zig index 253f250713..ae9a5227c9 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -85,8 +85,8 @@ fn wantTtyColor() bool { /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { const stderr = getStderrStream() catch return; - if (os.wasi.is_the_target) { - stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return; + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; } const debug_info = getSelfDebugInfo() catch |err| { @@ -151,8 +151,8 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { const stderr = getStderrStream() catch return; - if (os.wasi.is_the_target) { - stderr.print("Unable to dump stack trace: unimplemented on WASI\n") catch return; + if (builtin.strip_debug_info) { + stderr.print("Unable to dump stack trace: debug info stripped\n") catch return; return; } const debug_info = getSelfDebugInfo() catch |err| { @@ -223,6 +223,7 @@ pub fn writeStackTrace( debug_info: *DebugInfo, tty_color: bool, ) !void { + if (builtin.strip_debug_info) return error.MissingDebugInfo; var frame_index: usize = 0; var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len); @@ -783,6 +784,8 @@ pub const OpenSelfDebugInfoError = error{ }; pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo { + if (builtin.strip_debug_info) + return error.MissingDebugInfo; if (windows.is_the_target) { return openSelfDebugInfoWindows(allocator); } -- cgit v1.2.3 From aa60d2a688c965dcccf8e2c42afe5c180daba8fc Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Sun, 16 Jun 2019 02:10:06 +0200 Subject: fixes resolving aligment of child type in slice --- src/ir.cpp | 2 +- test/stage1/behavior.zig | 1 + test/stage1/behavior/bugs/2689.zig | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 test/stage1/behavior/bugs/2689.zig (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 6c1c84da3b..0936f78df3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16794,7 +16794,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdPromise: case ZigTypeIdVector: { - if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) 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); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index f477bb64ed..707d46fd8c 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -27,6 +27,7 @@ comptime { _ = @import("behavior/bugs/2114.zig"); _ = @import("behavior/bugs/2346.zig"); _ = @import("behavior/bugs/2578.zig"); + _ = @import("behavior/bugs/2689.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); diff --git a/test/stage1/behavior/bugs/2689.zig b/test/stage1/behavior/bugs/2689.zig new file mode 100644 index 0000000000..d1c1062ada --- /dev/null +++ b/test/stage1/behavior/bugs/2689.zig @@ -0,0 +1,7 @@ +test "slice with alignment" { + const S = packed struct { + a: u8, + }; + + var a: []align(8) S = undefined; +} -- cgit v1.2.3 From f4b8850002d5f617450a9d08b05519f390bd3f21 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Jun 2019 14:14:57 -0400 Subject: fix type info crash on extern lib name --- src/ir.cpp | 5 +++-- test/stage1/behavior/type_info.zig | 27 +++++++++++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 0936f78df3..5c09e48b2d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18613,10 +18613,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/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig index f05b02e7ab..4ae81aff20 100644 --- a/test/stage1/behavior/type_info.zig +++ b/test/stage1/behavior/type_info.zig @@ -1,7 +1,9 @@ -const expect = @import("std").testing.expect; -const mem = @import("std").mem; -const TypeInfo = @import("builtin").TypeInfo; -const TypeId = @import("builtin").TypeId; +const std = @import("std"); +const expect = std.testing.expect; +const mem = std.mem; +const builtin = @import("builtin"); +const TypeInfo = builtin.TypeInfo; +const TypeId = builtin.TypeId; test "type info: tag type, void info" { testBasic(); @@ -317,3 +319,20 @@ test "type info: TypeId -> TypeInfo impl cast" { _ = passTypeInfo(TypeId.Void); _ = comptime passTypeInfo(TypeId.Void); } + +test "type info: extern fns with and without lib names" { + const S = struct { + extern fn bar1() void; + extern "cool" fn bar2() void; + }; + const info = @typeInfo(S); + comptime { + for (info.Struct.decls) |decl| { + if (std.mem.eql(u8, decl.name, "bar1")) { + expect(decl.data.Fn.lib_name == null); + } else { + std.testing.expectEqual(([]const u8)("cool"), decl.data.Fn.lib_name.?); + } + } + } +} -- cgit v1.2.3 From 4d3356435f453bdc24ac3c6c2da74d98c981db15 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sun, 16 Jun 2019 13:17:33 -0500 Subject: stage1: check for null in buf_len and buf_ptr follow up for f4b8850002d5 --- src/buffer.hpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') 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; } -- cgit v1.2.3 From 21dff1c4e280663c7a637f3b014c0d7326efcd3d Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Sun, 16 Jun 2019 21:58:05 -0600 Subject: Remove duplicate exe name with zig run --- src/codegen.cpp | 3 ++- src/libc_installation.cpp | 6 +++-- src/link.cpp | 3 ++- src/main.cpp | 28 ++++++++++-------------- src/os.cpp | 56 +++++++++++++++++++++++------------------------ src/os.hpp | 4 ++-- 6 files changed, 49 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/codegen.cpp b/src/codegen.cpp index cee8c0ec0c..3dd6995c61 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8801,6 +8801,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { Termination term; ZigList args = {}; + args.append(buf_ptr(self_exe_path)); args.append("cc"); Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path)); @@ -8819,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); 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 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 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 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 9c14ba3250..9b1892061b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -467,6 +467,7 @@ int main(int argc, char **argv) { init_all_targets(); ZigList 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"); } @@ -1161,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) { @@ -1213,17 +1216,10 @@ int main(int argc, char **argv) { } Termination term; - if (test_exec_args.length > 0) { - ZigList 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 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..bc28b1e7a6 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 &args, Termination *term) { - const char **argv = allocate(args.length + 2); - argv[0] = exe; - argv[args.length + 1] = nullptr; +static void os_spawn_process_posix(ZigList &args, Termination *term) { + const char **argv = allocate(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(argv), environ); + int rc = posix_spawnp(&pid, args.at(0), nullptr, nullptr, const_cast(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 &args, #endif #if defined(ZIG_OS_WINDOWS) -static void os_windows_create_command_line(Buf *command_line, const char *exe, ZigList &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 &args) { + buf_resize(command_line, 0); + 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 &args, Termination *term) { +static void os_spawn_process_windows(ZigList &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 &arg } #endif -void os_spawn_process(const char *exe, ZigList &args, Termination *term) { +void os_spawn_process(ZigList &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 &args, +static Error os_exec_process_posix(ZigList &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 &args, if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) zig_panic("dup2 failed"); - const char **argv = allocate(args.length + 2); - argv[0] = exe; - argv[args.length + 1] = nullptr; + const char **argv = allocate(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(argv)); + execvp(argv[0], const_cast(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 &args, // LocalFree(messageBuffer); //} -static Error os_exec_process_windows(const char *exe, ZigList &args, +static Error os_exec_process_windows(ZigList &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 &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 &args, +Error os_exec_process(ZigList &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 &args, Termination *term); -Error os_exec_process(const char *exe, ZigList &args, +void os_spawn_process(ZigList &args, Termination *term); +Error os_exec_process(ZigList &args, Termination *term, Buf *out_stderr, Buf *out_stdout); Error os_execv(const char *exe, const char **argv); -- cgit v1.2.3 From 8ed88280a62f2a400d00b5ac20618539693dad36 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Jun 2019 11:18:53 -0400 Subject: Revert "fixes resolving aligment of child type in slice" This reverts commit aa60d2a688c965dcccf8e2c42afe5c180daba8fc. The copyright ownership of this 10 line patch is under dispute. See #2701 for details. So I'll revert it and then fix it myself without looking at this patch. --- src/ir.cpp | 2 +- test/stage1/behavior.zig | 1 - test/stage1/behavior/bugs/2689.zig | 7 ------- 3 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 test/stage1/behavior/bugs/2689.zig (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 5c09e48b2d..21751b9a96 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16794,7 +16794,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdPromise: case ZigTypeIdVector: { - if ((err = type_resolve(ira->codegen, child_type, ResolveStatusAlignmentKnown))) + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) 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); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 707d46fd8c..f477bb64ed 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -27,7 +27,6 @@ comptime { _ = @import("behavior/bugs/2114.zig"); _ = @import("behavior/bugs/2346.zig"); _ = @import("behavior/bugs/2578.zig"); - _ = @import("behavior/bugs/2689.zig"); _ = @import("behavior/bugs/394.zig"); _ = @import("behavior/bugs/421.zig"); _ = @import("behavior/bugs/529.zig"); diff --git a/test/stage1/behavior/bugs/2689.zig b/test/stage1/behavior/bugs/2689.zig deleted file mode 100644 index d1c1062ada..0000000000 --- a/test/stage1/behavior/bugs/2689.zig +++ /dev/null @@ -1,7 +0,0 @@ -test "slice with alignment" { - const S = packed struct { - a: u8, - }; - - var a: []align(8) S = undefined; -} -- cgit v1.2.3 From 9050a07540b7387dade8184d3a3daf957e805e4f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Jun 2019 11:31:05 -0400 Subject: when resolving slice types, might need to... ...resolve alignment if custom alignment is provided fixes #2689 --- src/ir.cpp | 4 +++- test/stage1/behavior/slice.zig | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ir.cpp b/src/ir.cpp index 21751b9a96..b74a99b37d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -16794,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); diff --git a/test/stage1/behavior/slice.zig b/test/stage1/behavior/slice.zig index 5fa6c24026..d4a8353ca7 100644 --- a/test/stage1/behavior/slice.zig +++ b/test/stage1/behavior/slice.zig @@ -54,3 +54,14 @@ test "comptime slices are disambiguated" { expect(sliceSum([_]u8{ 1, 2 }) == 3); expect(sliceSum([_]u8{ 3, 4 }) == 7); } + +test "slice type with custom alignment" { + const LazilyResolvedType = struct { + anything: i32, + }; + var slice: []align(32) LazilyResolvedType = undefined; + var array: [10]LazilyResolvedType align(32) = undefined; + slice = &array; + slice[1].anything = 42; + expect(array[1].anything == 42); +} -- cgit v1.2.3 From 3ac9e3c8880193a047e1c14cbabd8743e6819831 Mon Sep 17 00:00:00 2001 From: emekoi Date: Sat, 22 Jun 2019 19:54:11 -0500 Subject: make string literal const on windows --- src/os.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/os.cpp b/src/os.cpp index bc28b1e7a6..5fa70bd260 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -128,7 +128,7 @@ static void os_spawn_process_posix(ZigList &args, Termination *ter static void os_windows_create_command_line(Buf *command_line, ZigList &args) { buf_resize(command_line, 0); - char *prefix = "\""; + const char *prefix = "\""; for (size_t arg_i = 0; arg_i < args.length; arg_i += 1) { const char *arg = args.at(arg_i); buf_append_str(command_line, prefix); -- cgit v1.2.3