From 1fdebc1dc4881a00766f7c2b4b2d8ee6ad6e79b6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 18 Dec 2017 09:59:57 -0500 Subject: wip export rewrite --- src/ir.cpp | 459 +++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 264 insertions(+), 195 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/ir.cpp b/src/ir.cpp index ce7d8dcedd..81b64a318d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -207,6 +207,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) { return IrInstructionIdDeclVar; } +static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { + return IrInstructionIdExport; +} + static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) { return IrInstructionIdLoadPtr; } @@ -523,14 +527,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast return IrInstructionIdCanImplicitCast; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { - return IrInstructionIdSetGlobalSection; -} - -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalLinkage *) { - return IrInstructionIdSetGlobalLinkage; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) { return IrInstructionIdDeclRef; } @@ -1205,6 +1201,24 @@ static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_ return new_instruction; } +static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, + IrInstruction *name, IrInstruction *target, IrInstruction *linkage) +{ + IrInstructionExport *export_instruction = ir_build_instruction( + irb, scope, source_node); + export_instruction->base.value.special = ConstValSpecialStatic; + export_instruction->base.value.type = irb->codegen->builtin_types.entry_void; + export_instruction->name = name; + export_instruction->target = target; + export_instruction->linkage = linkage; + + ir_ref_instruction(name, irb->current_basic_block); + ir_ref_instruction(target, irb->current_basic_block); + if (linkage) ir_ref_instruction(linkage, irb->current_basic_block); + + return &export_instruction->base; +} + static IrInstruction *ir_build_load_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) { IrInstructionLoadPtr *instruction = ir_build_instruction(irb, scope, source_node); instruction->ptr = ptr; @@ -2159,32 +2173,6 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A return &instruction->base; } -static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, - Tld *tld, IrInstruction *value) -{ - IrInstructionSetGlobalSection *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->tld = tld; - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstruction *ir_build_set_global_linkage(IrBuilder *irb, Scope *scope, AstNode *source_node, - Tld *tld, IrInstruction *value) -{ - IrInstructionSetGlobalLinkage *instruction = ir_build_instruction( - irb, scope, source_node); - instruction->tld = tld; - instruction->value = value; - - ir_ref_instruction(value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, Tld *tld, LVal lval) { @@ -2396,6 +2384,21 @@ static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instr return nullptr; } +static IrInstruction *ir_instruction_export_get_dep(IrInstructionExport *instruction, size_t index) { + if (index < 1) return instruction->name; + index -= 1; + + if (index < 1) return instruction->target; + index -= 1; + + if (instruction->linkage != nullptr) { + if (index < 1) return instruction->linkage; + index -= 1; + } + + return nullptr; +} + static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) { switch (index) { case 0: return instruction->ptr; @@ -2979,20 +2982,6 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp } } -static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { - switch (index) { - case 0: return instruction->value; - default: return nullptr; - } -} - -static IrInstruction *ir_instruction_setgloballinkage_get_dep(IrInstructionSetGlobalLinkage *instruction, size_t index) { - switch (index) { - case 0: return instruction->value; - default: return nullptr; - } -} - static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) { return nullptr; } @@ -3106,6 +3095,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_binop_get_dep((IrInstructionBinOp *) instruction, index); case IrInstructionIdDeclVar: return ir_instruction_declvar_get_dep((IrInstructionDeclVar *) instruction, index); + case IrInstructionIdExport: + return ir_instruction_export_get_dep((IrInstructionExport *) instruction, index); case IrInstructionIdLoadPtr: return ir_instruction_loadptr_get_dep((IrInstructionLoadPtr *) instruction, index); case IrInstructionIdStorePtr: @@ -3264,10 +3255,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); case IrInstructionIdCanImplicitCast: return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); - case IrInstructionIdSetGlobalSection: - return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); - case IrInstructionIdSetGlobalLinkage: - return ir_instruction_setgloballinkage_get_dep((IrInstructionSetGlobalLinkage *) instruction, index); case IrInstructionIdDeclRef: return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); case IrInstructionIdPanic: @@ -4528,39 +4515,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); } - case BuiltinFnIdSetGlobalSection: - case BuiltinFnIdSetGlobalLinkage: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - if (arg0_node->type != NodeTypeSymbol) { - add_node_error(irb->codegen, arg0_node, buf_sprintf("expected identifier")); - return irb->codegen->invalid_instruction; - } - Buf *variable_name = arg0_node->data.symbol_expr.symbol; - Tld *tld = find_decl(irb->codegen, scope, variable_name); - if (!tld) { - add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", - buf_ptr(variable_name))); - return irb->codegen->invalid_instruction; - } - if (tld->id != TldIdVar && tld->id != TldIdFn) { - add_node_error(irb->codegen, node, buf_sprintf("'%s' must be global variable or function", - buf_ptr(variable_name))); - return irb->codegen->invalid_instruction; - } - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_instruction) - return arg1_value; - - if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { - return ir_build_set_global_section(irb, scope, node, tld, arg1_value); - } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) { - return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value); - } else { - zig_unreachable(); - } - } case BuiltinFnIdPanic: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -4784,6 +4738,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); } + case BuiltinFnIdExport: + case BuiltinFnIdExportWithLinkage: + { + AstNode *arg0_node = node->data.fn_call_expr.params.at(0); + IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); + if (arg0_value == irb->codegen->invalid_instruction) + return arg0_value; + + AstNode *arg1_node = node->data.fn_call_expr.params.at(1); + IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); + if (arg1_value == irb->codegen->invalid_instruction) + return arg1_value; + + IrInstruction *arg2_value; + if (builtin_fn->id == BuiltinFnIdExportWithLinkage) { + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_instruction) + return arg2_value; + } else { + arg2_value = nullptr; + } + + return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); + } } zig_unreachable(); } @@ -5106,6 +5085,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod return align_value; } + if (variable_declaration->section_expr != nullptr) { + add_node_error(irb->codegen, variable_declaration->section_expr, + buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); + } + IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); if (init_value == irb->codegen->invalid_instruction) return init_value; @@ -6355,6 +6339,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeSwitchRange: case NodeTypeStructField: case NodeTypeLabel: + case NodeTypeFnDef: + case NodeTypeFnDecl: + case NodeTypeErrorValueDecl: + case NodeTypeTestDecl: zig_unreachable(); case NodeTypeBlock: return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval); @@ -6436,14 +6424,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); case NodeTypeFnProto: return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); - case NodeTypeFnDef: - zig_panic("TODO IR gen NodeTypeFnDef"); - case NodeTypeFnDecl: - zig_panic("TODO IR gen NodeTypeFnDecl"); - case NodeTypeErrorValueDecl: - zig_panic("TODO IR gen NodeTypeErrorValueDecl"); - case NodeTypeTestDecl: - zig_panic("TODO IR gen NodeTypeTestDecl"); } zig_unreachable(); } @@ -10481,6 +10461,194 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc return ira->codegen->builtin_types.entry_void; } +static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { + IrInstruction *name = instruction->name->other; + Buf *symbol_name = ir_resolve_str(ira, name); + if (symbol_name == nullptr) { + return ira->codegen->builtin_types.entry_invalid; + } + + IrInstruction *target = instruction->target->other; + if (type_is_invalid(target->value.type)) { + return ira->codegen->builtin_types.entry_invalid; + } + + GlobalLinkageId global_linkage_id = GlobalLinkageIdStrong; + if (instruction->linkage != nullptr) { + IrInstruction *linkage_value = instruction->linkage->other; + if (!ir_resolve_global_linkage(ira, linkage_value, &global_linkage_id)) { + return ira->codegen->builtin_types.entry_invalid; + } + } + + auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, instruction->base.source_node); + if (entry) { + AstNode *other_export_node = entry->value; + ErrorMsg *msg = ir_add_error(ira, &instruction->base, + buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); + add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); + } + + switch (target->value.type->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + case TypeTableEntryIdUnreachable: + zig_unreachable(); + case TypeTableEntryIdFn: { + FnTableEntry *fn_entry = target->value.data.x_fn.fn_entry; + CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; + switch (cc) { + case CallingConventionUnspecified: { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported function must specify calling convention")); + add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); + } break; + case CallingConventionC: + if (buf_eql_str(symbol_name, "main") && ira->codegen->libc_link_lib != nullptr) { + ira->codegen->have_c_main = true; + ira->codegen->windows_subsystem_windows = false; + ira->codegen->windows_subsystem_console = true; + } else if (buf_eql_str(symbol_name, "WinMain") && + ira->codegen->zig_target.os == ZigLLVM_Win32) + { + ira->codegen->have_winmain = true; + ira->codegen->windows_subsystem_windows = true; + ira->codegen->windows_subsystem_console = false; + } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && + ira->codegen->zig_target.os == ZigLLVM_Win32) + { + ira->codegen->have_winmain_crt_startup = true; + } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && + ira->codegen->zig_target.os == ZigLLVM_Win32) + { + ira->codegen->have_dllmain_crt_startup = true; + } + // fallthrough + case CallingConventionNaked: + case CallingConventionCold: + case CallingConventionStdcall: { + FnExport *fn_export = fn_entry->export_list.add_one(); + memset(fn_export, 0, sizeof(FnExport)); + buf_init_from_buf(&fn_export->name, symbol_name); + fn_export->linkage = global_linkage_id; + fn_export->source_node = instruction->base.source_node; + } break; + } + } break; + case TypeTableEntryIdStruct: + if (is_slice(target->value.type)) { + ir_add_error(ira, target, + buf_sprintf("unable to export value of type '%s'", buf_ptr(&target->value.type->name))); + } else if (target->value.type->data.structure.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported struct value must be declared extern")); + add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdUnion: + if (target->value.type->data.unionation.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported union value must be declared extern")); + add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdEnum: + if (target->value.type->data.enumeration.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported enum value must be declared extern")); + add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdMetaType: { + TypeTableEntry *type_value = target->value.data.x_type; + switch (type_value->id) { + case TypeTableEntryIdInvalid: + case TypeTableEntryIdVar: + zig_unreachable(); + case TypeTableEntryIdStruct: + if (is_slice(type_value)) { + ir_add_error(ira, target, + buf_sprintf("unable to export type '%s'", buf_ptr(&type_value->name))); + } else if (type_value->data.structure.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported struct must be declared extern")); + add_error_note(ira->codegen, msg, type_value->data.structure.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdUnion: + if (type_value->data.unionation.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported union must be declared extern")); + add_error_note(ira->codegen, msg, type_value->data.unionation.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdEnum: + if (type_value->data.enumeration.layout != ContainerLayoutExtern) { + ErrorMsg *msg = ir_add_error(ira, target, + buf_sprintf("exported enum must be declared extern")); + add_error_note(ira->codegen, msg, type_value->data.enumeration.decl_node, buf_sprintf("declared here")); + } + break; + case TypeTableEntryIdFn: { + if (type_value->data.fn.fn_type_id.cc == CallingConventionUnspecified) { + ir_add_error(ira, target, + buf_sprintf("exported function type must specify calling convention")); + } + } break; + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdPointer: + case TypeTableEntryIdArray: + case TypeTableEntryIdBool: + break; + case TypeTableEntryIdMetaType: + case TypeTableEntryIdVoid: + case TypeTableEntryIdUnreachable: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdMaybe: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdOpaque: + ir_add_error(ira, target, + buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); + break; + } + } break; + case TypeTableEntryIdVoid: + case TypeTableEntryIdBool: + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdPointer: + case TypeTableEntryIdArray: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + case TypeTableEntryIdUndefLit: + case TypeTableEntryIdNullLit: + case TypeTableEntryIdMaybe: + case TypeTableEntryIdErrorUnion: + case TypeTableEntryIdPureError: + zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); + case TypeTableEntryIdNamespace: + case TypeTableEntryIdBlock: + case TypeTableEntryIdBoundFn: + case TypeTableEntryIdArgTuple: + case TypeTableEntryIdOpaque: + ir_add_error(ira, target, + buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); + break; + } + + ir_build_const_from(ira, &instruction->base); + return ira->codegen->builtin_types.entry_void; +} + static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) { @@ -12399,102 +12567,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, return ira->codegen->builtin_types.entry_type; } -static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, - IrInstructionSetGlobalSection *instruction) -{ - Tld *tld = instruction->tld; - IrInstruction *section_value = instruction->value->other; - - resolve_top_level_decl(ira->codegen, tld, true, instruction->base.source_node); - if (tld->resolution == TldResolutionInvalid) - return ira->codegen->builtin_types.entry_invalid; - - Buf *section_name = ir_resolve_str(ira, section_value); - if (!section_name) - return ira->codegen->builtin_types.entry_invalid; - - AstNode **set_global_section_node; - Buf **section_name_ptr; - if (tld->id == TldIdVar) { - TldVar *tld_var = (TldVar *)tld; - set_global_section_node = &tld_var->set_global_section_node; - section_name_ptr = &tld_var->section_name; - - if (tld_var->var->linkage == VarLinkageExternal) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, - buf_sprintf("cannot set section of external variable '%s'", buf_ptr(&tld_var->var->name))); - add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); - return ira->codegen->builtin_types.entry_invalid; - } - } else if (tld->id == TldIdFn) { - TldFn *tld_fn = (TldFn *)tld; - FnTableEntry *fn_entry = tld_fn->fn_entry; - set_global_section_node = &fn_entry->set_global_section_node; - section_name_ptr = &fn_entry->section_name; - - if (fn_entry->def_scope == nullptr) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base, - buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_entry->symbol_name))); - add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); - return ira->codegen->builtin_types.entry_invalid; - } - } else { - // error is caught in pass1 IR gen - zig_unreachable(); - } - - AstNode *source_node = instruction->base.source_node; - if (*set_global_section_node) { - ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("section set twice")); - add_error_note(ira->codegen, msg, *set_global_section_node, buf_sprintf("first set here")); - return ira->codegen->builtin_types.entry_invalid; - } - *set_global_section_node = source_node; - *section_name_ptr = section_name; - - ir_build_const_from(ira, &instruction->base); - return ira->codegen->builtin_types.entry_void; -} - -static TypeTableEntry *ir_analyze_instruction_set_global_linkage(IrAnalyze *ira, - IrInstructionSetGlobalLinkage *instruction) -{ - Tld *tld = instruction->tld; - IrInstruction *linkage_value = instruction->value->other; - - GlobalLinkageId linkage_scalar; - if (!ir_resolve_global_linkage(ira, linkage_value, &linkage_scalar)) - return ira->codegen->builtin_types.entry_invalid; - - AstNode **set_global_linkage_node; - GlobalLinkageId *dest_linkage_ptr; - if (tld->id == TldIdVar) { - TldVar *tld_var = (TldVar *)tld; - set_global_linkage_node = &tld_var->set_global_linkage_node; - dest_linkage_ptr = &tld_var->linkage; - } else if (tld->id == TldIdFn) { - TldFn *tld_fn = (TldFn *)tld; - FnTableEntry *fn_entry = tld_fn->fn_entry; - set_global_linkage_node = &fn_entry->set_global_linkage_node; - dest_linkage_ptr = &fn_entry->linkage; - } else { - // error is caught in pass1 IR gen - zig_unreachable(); - } - - AstNode *source_node = instruction->base.source_node; - if (*set_global_linkage_node) { - ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("linkage set twice")); - add_error_note(ira->codegen, msg, *set_global_linkage_node, buf_sprintf("first set here")); - return ira->codegen->builtin_types.entry_invalid; - } - *set_global_linkage_node = source_node; - *dest_linkage_ptr = linkage_scalar; - - ir_build_const_from(ira, &instruction->base); - return ira->codegen->builtin_types.entry_void; -} - static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, IrInstructionSetDebugSafety *set_debug_safety_instruction) { @@ -16165,10 +16237,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); case IrInstructionIdPtrTypeChild: return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); - case IrInstructionIdSetGlobalSection: - return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); - case IrInstructionIdSetGlobalLinkage: - return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction); case IrInstructionIdSetDebugSafety: return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); case IrInstructionIdSetFloatMode: @@ -16311,6 +16379,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); case IrInstructionIdTagType: return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); + case IrInstructionIdExport: + return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); } zig_unreachable(); } @@ -16418,12 +16488,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free case IrInstructionIdCheckSwitchProngs: case IrInstructionIdCheckStatementIsVoid: - case IrInstructionIdSetGlobalSection: - case IrInstructionIdSetGlobalLinkage: case IrInstructionIdPanic: case IrInstructionIdSetEvalBranchQuota: case IrInstructionIdPtrTypeOf: case IrInstructionIdSetAlignStack: + case IrInstructionIdExport: return true; case IrInstructionIdPhi: case IrInstructionIdUnOp: -- cgit v1.2.3 From c627f9ea18b5f194860c6bf3730f3f0407c224f2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2017 01:19:49 -0500 Subject: wip bring back export keyword --- doc/langref.html.in | 14 ++++--- src/all_types.hpp | 10 ++--- src/analyze.cpp | 29 ++++++++++++- src/ir.cpp | 2 +- src/parser.cpp | 114 ++++++++++++++++++++++++++++++++-------------------- src/tokenizer.cpp | 2 + src/tokenizer.hpp | 1 + 7 files changed, 112 insertions(+), 60 deletions(-) (limited to 'src/ir.cpp') diff --git a/doc/langref.html.in b/doc/langref.html.in index f302cbec5d..beb113682a 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -5819,9 +5819,11 @@ TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) ErrorValueDecl = "error" Symbol ";" -GlobalVarDecl = VariableDeclaration ";" +GlobalVarDecl = option("export") VariableDeclaration ";" -VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression +LocalVarDecl = option("comptime") VariableDeclaration + +VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression ContainerMember = (ContainerField | FnDef | GlobalVarDecl) @@ -5831,9 +5833,9 @@ UseDecl = "use" Expression ";" ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" -FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) +FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) -FnDef = option("inline" | "extern") FnProto Block +FnDef = option("inline" | "export") FnProto Block ParamDeclList = "(" list(ParamDecl, ",") ")" @@ -5841,7 +5843,7 @@ ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") Block = "{" many(Statement) option(Expression) "}" -Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" +Statement = Label | LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" Label = Symbol ":" @@ -5947,7 +5949,7 @@ StructLiteralField = "." Symbol "=" Expression PrefixOp = "!" | "-" | "~" | "*" | ("&" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" -PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl +PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr diff --git a/src/all_types.hpp b/src/all_types.hpp index 9256777428..106ccf6471 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -315,12 +315,6 @@ struct TldVar { VariableTableEntry *var; Buf *extern_lib_name; Buf *section_name; - - size_t export_count; - union { - TldExport *tld; // if export_count == 1 - TldExport **tld_list; // if export_count > 1 - } export_data; }; struct TldFn { @@ -428,6 +422,7 @@ struct AstNodeFnProto { AstNode *return_type; bool is_var_args; bool is_extern; + bool is_export; bool is_inline; CallingConvention cc; AstNode *fn_def_node; @@ -485,7 +480,8 @@ struct AstNodeVariableDeclaration { VisibMod visib_mod; Buf *symbol; bool is_const; - bool is_inline; + bool is_comptime; + bool is_export; bool is_extern; // one or both of type and expr will be non null AstNode *type; diff --git a/src/analyze.cpp b/src/analyze.cpp index 84d9b9feaf..470d54ff84 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1062,7 +1062,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; if (fn_proto->cc == CallingConventionUnspecified) { - bool extern_abi = fn_proto->is_extern; + bool extern_abi = fn_proto->is_extern || fn_proto->is_export; fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified; } else { fn_type_id->cc = fn_proto->cc; @@ -2675,6 +2675,26 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { } static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { + bool is_export = false; + if (tld->id == TldIdVar) { + assert(tld->source_node->type == NodeTypeVariableDeclaration); + is_export = tld->source_node->data.variable_declaration.is_export; + } else if (tld->id == TldIdFn) { + assert(tld->source_node->type == NodeTypeFnProto); + is_export = tld->source_node->data.fn_proto.is_export; + } + if (is_export) { + g->resolve_queue.append(tld); + + auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node); + if (entry) { + AstNode *other_source_node = entry->value; + ErrorMsg *msg = add_node_error(g, tld->source_node, + buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); + add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here")); + } + } + { auto entry = decls_scope->decl_table.put_unique(tld->name, tld); if (entry) { @@ -3006,6 +3026,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { bool is_const = var_decl->is_const; bool is_extern = var_decl->is_extern; + bool is_export = var_decl->is_export; TypeTableEntry *explicit_type = nullptr; if (var_decl->type) { @@ -3013,8 +3034,12 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { explicit_type = validate_var_type(g, var_decl->type, proposed_type); } + assert(!is_export || !is_extern); + VarLinkage linkage; - if (is_extern) { + if (is_export) { + linkage = VarLinkageExport; + } else if (is_extern) { linkage = VarLinkageExternal; } else { linkage = VarLinkageInternal; diff --git a/src/ir.cpp b/src/ir.cpp index 81b64a318d..78f7c25dca 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -5066,7 +5066,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod bool is_const = variable_declaration->is_const; bool is_extern = variable_declaration->is_extern; IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, - ir_should_inline(irb->exec, scope) || variable_declaration->is_inline); + ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol, is_const, is_const, is_shadowable, is_comptime); // we detect IrInstructionIdDeclVar in gen_block to make sure the next node diff --git a/src/parser.cpp b/src/parser.cpp index 07c221e287..a2b06410ea 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b } /* -PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl +PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" */ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { @@ -791,13 +791,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo if (container_decl) return container_decl; - if (token->id == TokenIdKeywordExtern) { - *token_index += 1; - AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate); - node->data.fn_proto.is_extern = true; - return node; - } - if (!mandatory) return nullptr; @@ -1534,38 +1527,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { } /* -VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression +VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression */ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, - VisibMod visib_mod) + VisibMod visib_mod, bool is_comptime, bool is_export) { Token *first_token = &pc->tokens->at(*token_index); Token *var_token; bool is_const; - bool is_comptime; - if (first_token->id == TokenIdKeywordCompTime) { - is_comptime = true; - var_token = &pc->tokens->at(*token_index + 1); - - if (var_token->id == TokenIdKeywordVar) { - is_const = false; - } else if (var_token->id == TokenIdKeywordConst) { - is_const = true; - } else if (mandatory) { - ast_invalid_token_error(pc, var_token); - } else { - return nullptr; - } - - *token_index += 2; - } else if (first_token->id == TokenIdKeywordVar) { - is_comptime = false; + if (first_token->id == TokenIdKeywordVar) { is_const = false; var_token = first_token; *token_index += 1; } else if (first_token->id == TokenIdKeywordConst) { - is_comptime = false; is_const = true; var_token = first_token; *token_index += 1; @@ -1577,7 +1552,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token); - node->data.variable_declaration.is_inline = is_comptime; + node->data.variable_declaration.is_comptime = is_comptime; node->data.variable_declaration.is_const = is_const; node->data.variable_declaration.visib_mod = visib_mod; @@ -1620,6 +1595,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to return node; } +/* +GlobalVarDecl = option("export") VariableDeclaration ";" +*/ +static AstNode *ast_parse_global_var_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { + Token *first_token = &pc->tokens->at(*token_index); + + bool is_export = false;; + if (first_token->id == TokenIdKeywordExport) { + *token_index += 1; + is_export = true; + } + + AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, is_export); + if (node == nullptr) { + if (is_export) { + *token_index -= 1; + } + return nullptr; + } + return node; +} + +/* +LocalVarDecl = option("comptime") VariableDeclaration +*/ +static AstNode *ast_parse_local_var_decl(ParseContext *pc, size_t *token_index) { + Token *first_token = &pc->tokens->at(*token_index); + + bool is_comptime = false;; + if (first_token->id == TokenIdKeywordCompTime) { + *token_index += 1; + is_comptime = true; + } + + AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate, is_comptime, false); + if (node == nullptr) { + if (is_comptime) { + *token_index -= 1; + } + return nullptr; + } + return node; +} + /* BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression */ @@ -2171,7 +2190,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand for (;;) { AstNode *statement_node = ast_parse_label(pc, token_index, false); if (!statement_node) - statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); + statement_node = ast_parse_local_var_decl(pc, token_index); if (!statement_node) statement_node = ast_parse_defer_expr(pc, token_index); if (!statement_node) @@ -2213,13 +2232,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand } /* -FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) +FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("->" TypeExpr) */ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { Token *first_token = &pc->tokens->at(*token_index); Token *fn_token; CallingConvention cc; + bool is_extern = false; if (first_token->id == TokenIdKeywordColdCC) { *token_index += 1; fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); @@ -2232,8 +2252,13 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m *token_index += 1; fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); cc = CallingConventionStdcall; + } else if (first_token->id == TokenIdKeywordExtern) { + *token_index += 1; + fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); + cc = CallingConventionC; } else if (first_token->id == TokenIdKeywordFn) { fn_token = first_token; + is_extern = true; *token_index += 1; cc = CallingConventionUnspecified; } else if (mandatory) { @@ -2246,6 +2271,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); node->data.fn_proto.visib_mod = visib_mod; node->data.fn_proto.cc = cc; + node->data.fn_proto.is_extern = is_extern; Token *fn_name = &pc->tokens->at(*token_index); @@ -2286,35 +2312,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m } /* -FnDef = option("inline" | "extern") FnProto Block +FnDef = option("inline" | "export") FnProto Block */ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { Token *first_token = &pc->tokens->at(*token_index); bool is_inline; - bool is_extern; + bool is_export; if (first_token->id == TokenIdKeywordInline) { *token_index += 1; is_inline = true; - is_extern = false; - } else if (first_token->id == TokenIdKeywordExtern) { + is_export = false; + } else if (first_token->id == TokenIdKeywordExport) { *token_index += 1; - is_extern = true; + is_export = true; is_inline = false; } else { is_inline = false; - is_extern = false; + is_export = false; } AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod); if (!fn_proto) { - if (is_inline || is_extern) { + if (is_inline || is_export) { *token_index -= 1; } return nullptr; } fn_proto->data.fn_proto.is_inline = is_inline; - fn_proto->data.fn_proto.is_extern = is_extern; + fn_proto->data.fn_proto.is_export = is_export; Token *semi_token = &pc->tokens->at(*token_index); if (semi_token->id == TokenIdSemicolon) { @@ -2360,7 +2386,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo return fn_proto_node; } - AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); + AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, false); if (var_decl_node) { ast_eat_token(pc, token_index, TokenIdSemicolon); @@ -2473,7 +2499,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, continue; } - AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); + AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); if (var_decl_node) { ast_eat_token(pc, token_index, TokenIdSemicolon); node->data.container_decl.decls.append(var_decl_node); @@ -2566,7 +2592,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) /* TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl -TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl) +TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) */ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList *top_level_decls) { for (;;) { @@ -2615,7 +2641,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig continue; } - AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); + AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); if (var_decl_node) { ast_eat_token(pc, token_index, TokenIdSemicolon); top_level_decls->append(var_decl_node); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index a14f709744..9bcc79ede7 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -119,6 +119,7 @@ static const struct ZigKeyword zig_keywords[] = { {"else", TokenIdKeywordElse}, {"enum", TokenIdKeywordEnum}, {"error", TokenIdKeywordError}, + {"export", TokenIdKeywordExport}, {"extern", TokenIdKeywordExtern}, {"false", TokenIdKeywordFalse}, {"fn", TokenIdKeywordFn}, @@ -1518,6 +1519,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordElse: return "else"; case TokenIdKeywordEnum: return "enum"; case TokenIdKeywordError: return "error"; + case TokenIdKeywordExport: return "export"; case TokenIdKeywordExtern: return "extern"; case TokenIdKeywordFalse: return "false"; case TokenIdKeywordFn: return "fn"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index b0444b9c3b..58a20adc1a 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -59,6 +59,7 @@ enum TokenId { TokenIdKeywordElse, TokenIdKeywordEnum, TokenIdKeywordError, + TokenIdKeywordExport, TokenIdKeywordExtern, TokenIdKeywordFalse, TokenIdKeywordFn, -- cgit v1.2.3 From 27ba4f0baf5168b2fb8f0dd72b04f528092f075a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2017 01:49:42 -0500 Subject: export keyword works again --- src/all_types.hpp | 1 - src/analyze.cpp | 33 +++++++++++++++++++++++++++++++++ src/analyze.hpp | 1 + src/ir.cpp | 30 +++--------------------------- src/parser.cpp | 1 + 5 files changed, 38 insertions(+), 28 deletions(-) (limited to 'src/ir.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index 106ccf6471..1ec3c809a2 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1183,7 +1183,6 @@ enum FnInline { struct FnExport { Buf name; GlobalLinkageId linkage; - AstNode *source_node; }; struct FnTableEntry { diff --git a/src/analyze.cpp b/src/analyze.cpp index 470d54ff84..e2df4955da 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2577,6 +2577,34 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { return g->test_fn_type; } +void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) { + if (ccc) { + if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { + g->have_c_main = true; + g->windows_subsystem_windows = false; + g->windows_subsystem_console = true; + } else if (buf_eql_str(symbol_name, "WinMain") && + g->zig_target.os == ZigLLVM_Win32) + { + g->have_winmain = true; + g->windows_subsystem_windows = true; + g->windows_subsystem_console = false; + } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && + g->zig_target.os == ZigLLVM_Win32) + { + g->have_winmain_crt_startup = true; + } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && + g->zig_target.os == ZigLLVM_Win32) + { + g->have_dllmain_crt_startup = true; + } + } + FnExport *fn_export = fn_table_entry->export_list.add_one(); + memset(fn_export, 0, sizeof(FnExport)); + buf_init_from_buf(&fn_export->name, symbol_name); + fn_export->linkage = linkage; +} + static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { ImportTableEntry *import = tld_fn->base.import; AstNode *source_node = tld_fn->base.source_node; @@ -2588,6 +2616,11 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { FnTableEntry *fn_table_entry = create_fn(source_node); get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); + if (fn_proto->is_export) { + bool ccc = (fn_proto->cc == CallingConventionUnspecified || fn_proto->cc == CallingConventionC); + add_fn_export(g, fn_table_entry, &fn_table_entry->symbol_name, GlobalLinkageIdStrong, ccc); + } + tld_fn->fn_entry = fn_table_entry; if (fn_table_entry->body_node) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 0e727568c6..6224e64dd5 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -183,5 +183,6 @@ TypeTableEntry *get_align_amt_type(CodeGen *g); PackageTableEntry *new_anonymous_package(void); Buf *const_value_to_buffer(ConstExprValue *const_val); +void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); #endif diff --git a/src/ir.cpp b/src/ir.cpp index 78f7c25dca..4afc1a2c60 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10504,35 +10504,11 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); } break; case CallingConventionC: - if (buf_eql_str(symbol_name, "main") && ira->codegen->libc_link_lib != nullptr) { - ira->codegen->have_c_main = true; - ira->codegen->windows_subsystem_windows = false; - ira->codegen->windows_subsystem_console = true; - } else if (buf_eql_str(symbol_name, "WinMain") && - ira->codegen->zig_target.os == ZigLLVM_Win32) - { - ira->codegen->have_winmain = true; - ira->codegen->windows_subsystem_windows = true; - ira->codegen->windows_subsystem_console = false; - } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && - ira->codegen->zig_target.os == ZigLLVM_Win32) - { - ira->codegen->have_winmain_crt_startup = true; - } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && - ira->codegen->zig_target.os == ZigLLVM_Win32) - { - ira->codegen->have_dllmain_crt_startup = true; - } - // fallthrough case CallingConventionNaked: case CallingConventionCold: - case CallingConventionStdcall: { - FnExport *fn_export = fn_entry->export_list.add_one(); - memset(fn_export, 0, sizeof(FnExport)); - buf_init_from_buf(&fn_export->name, symbol_name); - fn_export->linkage = global_linkage_id; - fn_export->source_node = instruction->base.source_node; - } break; + case CallingConventionStdcall: + add_fn_export(ira->codegen, fn_entry, symbol_name, global_linkage_id, cc == CallingConventionC); + break; } } break; case TypeTableEntryIdStruct: diff --git a/src/parser.cpp b/src/parser.cpp index a2b06410ea..cc337471ba 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1553,6 +1553,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token); node->data.variable_declaration.is_comptime = is_comptime; + node->data.variable_declaration.is_export = is_export; node->data.variable_declaration.is_const = is_const; node->data.variable_declaration.visib_mod = visib_mod; -- cgit v1.2.3 From 9d9201c3b48873e432dc6824d42b5ca96b236daa Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 19 Dec 2017 02:39:43 -0500 Subject: bring back code that uses export and fix tests partial revert of 1fdebc1dc4881a00766f7c2b4b2d8ee6ad6e79b6 --- doc/langref.html.in | 6 + example/hello_world/hello_libc.zig | 8 +- example/mix_o_files/base64.zig | 5 +- example/shared_library/mathtest.zig | 5 +- src/all_types.hpp | 1 - src/ast_render.cpp | 7 +- src/codegen.cpp | 3 +- src/ir.cpp | 14 +- src/parser.cpp | 30 +- src/translate_c.cpp | 5 +- std/special/bootstrap.zig | 7 +- std/special/builtin.zig | 35 +- std/special/compiler_rt/index.zig | 68 +-- test/cases/asm.zig | 13 +- test/cases/misc.zig | 20 +- test/compare_output.zig | 16 +- test/compile_errors.zig | 829 +++++++++++++----------------------- test/standalone/issue_339/test.zig | 5 +- test/translate_c.zig | 64 +-- 19 files changed, 443 insertions(+), 698 deletions(-) (limited to 'src/ir.cpp') diff --git a/doc/langref.html.in b/doc/langref.html.in index beb113682a..e17e1ecd8f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -136,6 +136,7 @@
  • @divFloor
  • @divTrunc
  • @embedFile
  • +
  • @export
  • @tagName
  • @EnumTagType
  • @errorName
  • @@ -4368,6 +4369,11 @@ test.zig:6:2: error: found compile log statement +

    @export

    +
    @export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -> []const u8
    +

    + Creates a symbol in the output object file. +

    @tagName

    @tagName(value: var) -> []const u8

    diff --git a/example/hello_world/hello_libc.zig b/example/hello_world/hello_libc.zig index 16d0f303cc..ea8aec1e4f 100644 --- a/example/hello_world/hello_libc.zig +++ b/example/hello_world/hello_libc.zig @@ -5,13 +5,9 @@ const c = @cImport({ @cInclude("string.h"); }); -comptime { - @export("main", main); -} - -extern fn main(argc: c_int, argv: &&u8) -> c_int { - const msg = c"Hello, world!\n"; +const msg = c"Hello, world!\n"; +export fn main(argc: c_int, argv: &&u8) -> c_int { if (c.printf(msg) != c_int(c.strlen(msg))) return -1; diff --git a/example/mix_o_files/base64.zig b/example/mix_o_files/base64.zig index a8358e9685..49c9bc6012 100644 --- a/example/mix_o_files/base64.zig +++ b/example/mix_o_files/base64.zig @@ -1,9 +1,6 @@ const base64 = @import("std").base64; -comptime { - @export("decode_base_64", decode_base_64); -} -extern fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) -> usize { +export fn decode_base_64(dest_ptr: &u8, dest_len: usize, source_ptr: &const u8, source_len: usize) -> usize { const src = source_ptr[0..source_len]; const dest = dest_ptr[0..dest_len]; const base64_decoder = base64.standard_decoder_unsafe; diff --git a/example/shared_library/mathtest.zig b/example/shared_library/mathtest.zig index f6d0a61c90..a11642554f 100644 --- a/example/shared_library/mathtest.zig +++ b/example/shared_library/mathtest.zig @@ -1,6 +1,3 @@ -comptime { - @export("add", add); -} -extern fn add(a: i32, b: i32) -> i32 { +export fn add(a: i32, b: i32) -> i32 { a + b } diff --git a/src/all_types.hpp b/src/all_types.hpp index 1ec3c809a2..28477c8107 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1285,7 +1285,6 @@ enum BuiltinFnId { BuiltinFnIdSetAlignStack, BuiltinFnIdArgType, BuiltinFnIdExport, - BuiltinFnIdExportWithLinkage, }; struct BuiltinFnEntry { diff --git a/src/ast_render.cpp b/src/ast_render.cpp index fc01c79ca6..c22c16d90a 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -111,6 +111,10 @@ static const char *extern_string(bool is_extern) { return is_extern ? "extern " : ""; } +static const char *export_string(bool is_export) { + return is_export ? "export " : ""; +} + //static const char *calling_convention_string(CallingConvention cc) { // switch (cc) { // case CallingConventionUnspecified: return ""; @@ -410,8 +414,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { { const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); const char *extern_str = extern_string(node->data.fn_proto.is_extern); + const char *export_str = export_string(node->data.fn_proto.is_export); const char *inline_str = inline_string(node->data.fn_proto.is_inline); - fprintf(ar->f, "%s%s%sfn", pub_str, inline_str, extern_str); + fprintf(ar->f, "%s%s%s%sfn", pub_str, inline_str, export_str, extern_str); if (node->data.fn_proto.name != nullptr) { fprintf(ar->f, " "); print_symbol(ar, node->data.fn_proto.name); diff --git a/src/codegen.cpp b/src/codegen.cpp index 5be26eb445..7fe4f95f85 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5016,8 +5016,7 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0); create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); - create_builtin_fn(g, BuiltinFnIdExport, "export", 2); - create_builtin_fn(g, BuiltinFnIdExportWithLinkage, "exportWithLinkage", 3); + create_builtin_fn(g, BuiltinFnIdExport, "export", 3); } static const char *bool_to_str(bool b) { diff --git a/src/ir.cpp b/src/ir.cpp index 4afc1a2c60..7bd045bd92 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4739,7 +4739,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); } case BuiltinFnIdExport: - case BuiltinFnIdExportWithLinkage: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); @@ -4751,15 +4750,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo if (arg1_value == irb->codegen->invalid_instruction) return arg1_value; - IrInstruction *arg2_value; - if (builtin_fn->id == BuiltinFnIdExportWithLinkage) { - AstNode *arg2_node = node->data.fn_call_expr.params.at(2); - arg2_value = ir_gen_node(irb, arg2_node, scope); - if (arg2_value == irb->codegen->invalid_instruction) - return arg2_value; - } else { - arg2_value = nullptr; - } + AstNode *arg2_node = node->data.fn_call_expr.params.at(2); + IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); + if (arg2_value == irb->codegen->invalid_instruction) + return arg2_value; return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); } diff --git a/src/parser.cpp b/src/parser.cpp index cc337471ba..579fe85f3b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -740,9 +740,21 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo return node; } else if (token->id == TokenIdAtSign) { *token_index += 1; - Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); + Token *name_tok = &pc->tokens->at(*token_index); + Buf *name_buf; + if (name_tok->id == TokenIdKeywordExport) { + name_buf = buf_create_from_str("export"); + *token_index += 1; + } else if (name_tok->id == TokenIdSymbol) { + name_buf = token_buf(name_tok); + *token_index += 1; + } else { + ast_expect_token(pc, name_tok, TokenIdSymbol); + zig_unreachable(); + } + AstNode *name_node = ast_create_node(pc, NodeTypeSymbol, name_tok); - name_node->data.symbol_expr.symbol = token_buf(name_tok); + name_node->data.symbol_expr.symbol = name_buf; AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token); node->data.fn_call_expr.fn_ref_expr = name_node; @@ -2254,12 +2266,22 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); cc = CallingConventionStdcall; } else if (first_token->id == TokenIdKeywordExtern) { + is_extern = true; *token_index += 1; - fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); + Token *next_token = &pc->tokens->at(*token_index); + if (next_token->id == TokenIdKeywordFn) { + fn_token = next_token; + *token_index += 1; + } else if (mandatory) { + ast_expect_token(pc, next_token, TokenIdKeywordFn); + zig_unreachable(); + } else { + *token_index -= 1; + return nullptr; + } cc = CallingConventionC; } else if (first_token->id == TokenIdKeywordFn) { fn_token = first_token; - is_extern = true; *token_index += 1; cc = CallingConventionUnspecified; } else if (mandatory) { diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 77afc38a51..eba594e085 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -73,6 +73,7 @@ struct Context { ImportTableEntry *import; ZigList *errors; VisibMod visib_mod; + bool want_export; AstNode *root; HashMap decl_table; HashMap macro_table; @@ -3250,8 +3251,8 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { StorageClass sc = fn_decl->getStorageClass(); if (sc == SC_None) { - // TODO add export decl proto_node->data.fn_proto.visib_mod = c->visib_mod; + proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; } else if (sc == SC_Extern || sc == SC_Static) { proto_node->data.fn_proto.visib_mod = c->visib_mod; } else if (sc == SC_PrivateExtern) { @@ -4274,8 +4275,10 @@ int parse_h_file(ImportTableEntry *import, ZigList *errors, const ch c->errors = errors; if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) { c->visib_mod = VisibModPub; + c->want_export = false; } else { c->visib_mod = VisibModPub; + c->want_export = true; } c->decl_table.init(8); c->macro_table.init(8); diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index ee63467305..177e245400 100644 --- a/std/special/bootstrap.zig +++ b/std/special/bootstrap.zig @@ -8,12 +8,13 @@ const builtin = @import("builtin"); var argc_ptr: &usize = undefined; comptime { + const strong_linkage = builtin.GlobalLinkage.Strong; if (builtin.link_libc) { - @export("main", main); + @export("main", main, strong_linkage); } else if (builtin.os == builtin.Os.windows) { - @export("WinMainCRTStartup", WinMainCRTStartup); + @export("WinMainCRTStartup", WinMainCRTStartup, strong_linkage); } else { - @export("_start", _start); + @export("_start", _start, strong_linkage); } } diff --git a/std/special/builtin.zig b/std/special/builtin.zig index 9ace9b46ca..a2455a9690 100644 --- a/std/special/builtin.zig +++ b/std/special/builtin.zig @@ -13,24 +13,10 @@ pub coldcc fn panic(msg: []const u8) -> noreturn { } } -comptime { - @export("memset", memset); - @export("memcpy", memcpy); - @export("fmodf", fmodf); - @export("fmod", fmod); - @export("floorf", floorf); - @export("ceilf", ceilf); - @export("floor", floor); - @export("ceil", ceil); - if (builtin.mode != builtin.Mode.ReleaseFast and builtin.os != builtin.Os.windows) { - @export("__stack_chk_fail", __stack_chk_fail); - } -} - // Note that memset does not return `dest`, like the libc API. // The semantics of memset is dictated by the corresponding // LLVM intrinsics, not by the libc API. -extern fn memset(dest: ?&u8, c: u8, n: usize) { +export fn memset(dest: ?&u8, c: u8, n: usize) { @setDebugSafety(this, false); var index: usize = 0; @@ -41,7 +27,7 @@ extern fn memset(dest: ?&u8, c: u8, n: usize) { // Note that memcpy does not return `dest`, like the libc API. // The semantics of memcpy is dictated by the corresponding // LLVM intrinsics, not by the libc API. -extern fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { +export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { @setDebugSafety(this, false); var index: usize = 0; @@ -49,21 +35,26 @@ extern fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { (??dest)[index] = (??src)[index]; } +comptime { + if (builtin.mode != builtin.Mode.ReleaseFast and builtin.os != builtin.Os.windows) { + @export("__stack_chk_fail", __stack_chk_fail, builtin.GlobalLinkage.Strong); + } +} extern fn __stack_chk_fail() -> noreturn { @panic("stack smashing detected"); } const math = @import("../math/index.zig"); -extern fn fmodf(x: f32, y: f32) -> f32 { generic_fmod(f32, x, y) } -extern fn fmod(x: f64, y: f64) -> f64 { generic_fmod(f64, x, y) } +export fn fmodf(x: f32, y: f32) -> f32 { generic_fmod(f32, x, y) } +export fn fmod(x: f64, y: f64) -> f64 { generic_fmod(f64, x, y) } // TODO add intrinsics for these (and probably the double version too) // and have the math stuff use the intrinsic. same as @mod and @rem -extern fn floorf(x: f32) -> f32 { math.floor(x) } -extern fn ceilf(x: f32) -> f32 { math.ceil(x) } -extern fn floor(x: f64) -> f64 { math.floor(x) } -extern fn ceil(x: f64) -> f64 { math.ceil(x) } +export fn floorf(x: f32) -> f32 { math.floor(x) } +export fn ceilf(x: f32) -> f32 { math.ceil(x) } +export fn floor(x: f64) -> f64 { math.floor(x) } +export fn ceil(x: f64) -> f64 { math.ceil(x) } fn generic_fmod(comptime T: type, x: T, y: T) -> T { @setDebugSafety(this, false); diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig index 717c6934f5..fab7b7c878 100644 --- a/std/special/compiler_rt/index.zig +++ b/std/special/compiler_rt/index.zig @@ -5,62 +5,62 @@ comptime { const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; - @exportWithLinkage("__letf2", @import("comparetf2.zig").__letf2, linkage); - @exportWithLinkage("__getf2", @import("comparetf2.zig").__getf2, linkage); + @export("__letf2", @import("comparetf2.zig").__letf2, linkage); + @export("__getf2", @import("comparetf2.zig").__getf2, linkage); if (!is_test) { // only create these aliases when not testing - @exportWithLinkage("__cmptf2", @import("comparetf2.zig").__letf2, linkage); - @exportWithLinkage("__eqtf2", @import("comparetf2.zig").__letf2, linkage); - @exportWithLinkage("__lttf2", @import("comparetf2.zig").__letf2, linkage); - @exportWithLinkage("__netf2", @import("comparetf2.zig").__letf2, linkage); - @exportWithLinkage("__gttf2", @import("comparetf2.zig").__getf2, linkage); + @export("__cmptf2", @import("comparetf2.zig").__letf2, linkage); + @export("__eqtf2", @import("comparetf2.zig").__letf2, linkage); + @export("__lttf2", @import("comparetf2.zig").__letf2, linkage); + @export("__netf2", @import("comparetf2.zig").__letf2, linkage); + @export("__gttf2", @import("comparetf2.zig").__getf2, linkage); } - @exportWithLinkage("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); + @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); - @exportWithLinkage("__fixunssfsi", @import("fixunssfsi.zig").__fixunssfsi, linkage); - @exportWithLinkage("__fixunssfdi", @import("fixunssfdi.zig").__fixunssfdi, linkage); - @exportWithLinkage("__fixunssfti", @import("fixunssfti.zig").__fixunssfti, linkage); + @export("__fixunssfsi", @import("fixunssfsi.zig").__fixunssfsi, linkage); + @export("__fixunssfdi", @import("fixunssfdi.zig").__fixunssfdi, linkage); + @export("__fixunssfti", @import("fixunssfti.zig").__fixunssfti, linkage); - @exportWithLinkage("__fixunsdfsi", @import("fixunsdfsi.zig").__fixunsdfsi, linkage); - @exportWithLinkage("__fixunsdfdi", @import("fixunsdfdi.zig").__fixunsdfdi, linkage); - @exportWithLinkage("__fixunsdfti", @import("fixunsdfti.zig").__fixunsdfti, linkage); + @export("__fixunsdfsi", @import("fixunsdfsi.zig").__fixunsdfsi, linkage); + @export("__fixunsdfdi", @import("fixunsdfdi.zig").__fixunsdfdi, linkage); + @export("__fixunsdfti", @import("fixunsdfti.zig").__fixunsdfti, linkage); - @exportWithLinkage("__fixunstfsi", @import("fixunstfsi.zig").__fixunstfsi, linkage); - @exportWithLinkage("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); - @exportWithLinkage("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); + @export("__fixunstfsi", @import("fixunstfsi.zig").__fixunstfsi, linkage); + @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); + @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); - @exportWithLinkage("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); - @exportWithLinkage("__udivmodti4", @import("udivmodti4.zig").__udivmodti4, linkage); + @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); + @export("__udivmodti4", @import("udivmodti4.zig").__udivmodti4, linkage); - @exportWithLinkage("__udivti3", @import("udivti3.zig").__udivti3, linkage); - @exportWithLinkage("__umodti3", @import("umodti3.zig").__umodti3, linkage); + @export("__udivti3", @import("udivti3.zig").__udivti3, linkage); + @export("__umodti3", @import("umodti3.zig").__umodti3, linkage); - @exportWithLinkage("__udivsi3", __udivsi3, linkage); - @exportWithLinkage("__udivdi3", __udivdi3, linkage); - @exportWithLinkage("__umoddi3", __umoddi3, linkage); - @exportWithLinkage("__udivmodsi4", __udivmodsi4, linkage); + @export("__udivsi3", __udivsi3, linkage); + @export("__udivdi3", __udivdi3, linkage); + @export("__umoddi3", __umoddi3, linkage); + @export("__udivmodsi4", __udivmodsi4, linkage); if (isArmArch()) { - @exportWithLinkage("__aeabi_uldivmod", __aeabi_uldivmod, linkage); - @exportWithLinkage("__aeabi_uidivmod", __aeabi_uidivmod, linkage); - @exportWithLinkage("__aeabi_uidiv", __udivsi3, linkage); + @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); + @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); + @export("__aeabi_uidiv", __udivsi3, linkage); } if (builtin.os == builtin.Os.windows) { switch (builtin.arch) { builtin.Arch.i386 => { if (!builtin.link_libc) { - @exportWithLinkage("_chkstk", _chkstk, strong_linkage); - @exportWithLinkage("__chkstk_ms", __chkstk_ms, linkage); + @export("_chkstk", _chkstk, strong_linkage); + @export("__chkstk_ms", __chkstk_ms, linkage); } - @exportWithLinkage("_aulldiv", @import("aulldiv.zig")._aulldiv, strong_linkage); - @exportWithLinkage("_aullrem", @import("aullrem.zig")._aullrem, strong_linkage); + @export("_aulldiv", @import("aulldiv.zig")._aulldiv, strong_linkage); + @export("_aullrem", @import("aullrem.zig")._aullrem, strong_linkage); }, builtin.Arch.x86_64 => { if (!builtin.link_libc) { - @exportWithLinkage("__chkstk", __chkstk, strong_linkage); - @exportWithLinkage("___chkstk_ms", ___chkstk_ms, linkage); + @export("__chkstk", __chkstk, strong_linkage); + @export("___chkstk_ms", ___chkstk_ms, linkage); } }, else => {}, diff --git a/test/cases/asm.zig b/test/cases/asm.zig index d7b88bd69e..8a3020fe23 100644 --- a/test/cases/asm.zig +++ b/test/cases/asm.zig @@ -2,24 +2,23 @@ const config = @import("builtin"); const assert = @import("std").debug.assert; comptime { - @export("derp", derp); if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { asm volatile ( - \\.globl my_aoeu_symbol_asdf; - \\.type my_aoeu_symbol_asdf, @function; - \\.set my_aoeu_symbol_asdf, derp; + \\.globl aoeu; + \\.type aoeu, @function; + \\.set aoeu, derp; ); } } test "module level assembly" { if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { - assert(my_aoeu_symbol_asdf() == 1234); + assert(aoeu() == 1234); } } -extern fn my_aoeu_symbol_asdf() -> i32; +extern fn aoeu() -> i32; -extern fn derp() -> i32 { +export fn derp() -> i32 { return 1234; } diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 1511c84b0c..daa7c3eb98 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -13,8 +13,9 @@ test "empty function with comments" { } comptime { - @exportWithLinkage("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal) + @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); } + extern fn disabledExternFn() { } @@ -535,10 +536,7 @@ var global_ptr = &gdt[0]; // can't really run this test but we can make sure it has no compile error // and generates code const vram = @intToPtr(&volatile u8, 0x20000000)[0..0x8000]; -comptime { - @export("writeToVRam", writeToVRam); -} -extern fn writeToVRam() { +export fn writeToVRam() { vram[0] = 'X'; } @@ -562,15 +560,3 @@ fn hereIsAnOpaqueType(ptr: &OpaqueA) -> &OpaqueA { var a = ptr; return a; } - -test "function and variable in weird section" { - if (builtin.os == builtin.Os.linux or builtin.os == builtin.Os.windows) { - // macos can't handle this - assert(fnInWeirdSection() == 1234); - } -} - -var varInWeirdSection: i32 section(".data2") = 1234; -fn fnInWeirdSection() section(".text2") -> i32 { - return varInWeirdSection; -} diff --git a/test/compare_output.zig b/test/compare_output.zig index 4829a39fb6..ad9c91ff20 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -4,8 +4,7 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompareOutputContext) { cases.addC("hello world with libc", \\const c = @cImport(@cInclude("stdio.h")); - \\comptime { @export("main", main); } - \\extern fn main(argc: c_int, argv: &&u8) -> c_int { + \\export fn main(argc: c_int, argv: &&u8) -> c_int { \\ _ = c.puts(c"Hello, world!"); \\ return 0; \\} @@ -138,8 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\ @cInclude("stdio.h"); \\}); \\ - \\comptime { @export("main", main); } - \\extern fn main(argc: c_int, argv: &&u8) -> c_int { + \\export fn main(argc: c_int, argv: &&u8) -> c_int { \\ if (is_windows) { \\ // we want actual \n, not \r\n \\ _ = c._setmode(1, c._O_BINARY); @@ -284,10 +282,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { cases.addC("expose function pointer to C land", \\const c = @cImport(@cInclude("stdlib.h")); \\ - \\comptime { - \\ @export("main", main); - \\} - \\extern fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { + \\export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { \\ const a_int = @ptrCast(&align(1) i32, a ?? unreachable); \\ const b_int = @ptrCast(&align(1) i32, b ?? unreachable); \\ if (*a_int < *b_int) { @@ -299,7 +294,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\ } \\} \\ - \\extern fn main() -> c_int { + \\export fn main() -> c_int { \\ var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; \\ \\ c.qsort(@ptrCast(&c_void, &array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); @@ -327,8 +322,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\ @cInclude("stdio.h"); \\}); \\ - \\comptime { @export("main", main); } - \\extern fn main(argc: c_int, argv: &&u8) -> c_int { + \\export fn main(argc: c_int, argv: &&u8) -> c_int { \\ if (is_windows) { \\ // we want actual \n, not \r\n \\ _ = c._setmode(1, c._O_BINARY); diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 8aa57c4468..22520802fb 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,328 +1,253 @@ const tests = @import("tests.zig"); pub fn addCases(cases: &tests.CompileErrorContext) { - cases.add("wrong return type for main", - \\pub fn main() { } - , ".tmp_source.zig:1:15: error: expected return type of main to be '%void', instead is 'void'"); - - cases.add("double ?? on main return value", - \\pub fn main() -> ??void { - \\} - , ".tmp_source.zig:1:18: error: expected return type of main to be '%void', instead is '??void'"); - - cases.add("setting a section on an extern variable", - \\extern var foo: i32 section(".text2"); - \\extern fn entry() -> i32 { - \\ return foo; - \\} - \\comptime { @export("entry", entry); } - , - ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'"); - - cases.add("setting a section on a local variable", - \\extern fn entry() -> i32 { - \\ var foo: i32 section(".text2") = 1234; - \\ return foo; - \\} - \\comptime { @export("entry", entry); } - , - ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'"); - - cases.add("setting a section on an extern fn", - \\extern fn foo() section(".text2"); - \\extern fn entry() { - \\ foo(); - \\} - \\comptime { @export("entry", entry); } - , - ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'"); - - cases.add("wrong types given to exportWithLinkage", - \\extern fn entry() { } - \\comptime { - \\ @exportWithLinkage("entry", entry, u32(1234)); - \\} - , - ".tmp_source.zig:3:43: error: expected type 'GlobalLinkage', found 'u32'"); - cases.add("implicit semicolon - block statement", - \\extern fn entry() { + \\export fn entry() { \\ {} \\ var good = {}; \\ ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - block expr", - \\extern fn entry() { + \\export fn entry() { \\ _ = {}; \\ var good = {}; \\ _ = {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - comptime statement", - \\extern fn entry() { + \\export fn entry() { \\ comptime {} \\ var good = {}; \\ comptime ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - comptime expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = comptime {}; \\ var good = {}; \\ _ = comptime {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - defer", - \\extern fn entry() { + \\export fn entry() { \\ defer {} \\ var good = {}; \\ defer ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: expected token ';', found 'var'"); cases.add("implicit semicolon - if statement", - \\extern fn entry() { + \\export fn entry() { \\ if(true) {} \\ var good = {}; \\ if(true) ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = if(true) {}; \\ var good = {}; \\ _ = if(true) {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else statement", - \\extern fn entry() { + \\export fn entry() { \\ if(true) {} else {} \\ var good = {}; \\ if(true) ({}) else ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = if(true) {} else {}; \\ var good = {}; \\ _ = if(true) {} else {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else-if statement", - \\extern fn entry() { + \\export fn entry() { \\ if(true) {} else if(true) {} \\ var good = {}; \\ if(true) ({}) else if(true) ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else-if expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = if(true) {} else if(true) {}; \\ var good = {}; \\ _ = if(true) {} else if(true) {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else-if-else statement", - \\extern fn entry() { + \\export fn entry() { \\ if(true) {} else if(true) {} else {} \\ var good = {}; \\ if(true) ({}) else if(true) ({}) else ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - if-else-if-else expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = if(true) {} else if(true) {} else {}; \\ var good = {}; \\ _ = if(true) {} else if(true) {} else {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - test statement", - \\extern fn entry() { + \\export fn entry() { \\ if (foo()) |_| {} \\ var good = {}; \\ if (foo()) |_| ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - test expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = if (foo()) |_| {}; \\ var good = {}; \\ _ = if (foo()) |_| {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - while statement", - \\extern fn entry() { + \\export fn entry() { \\ while(true) {} \\ var good = {}; \\ while(true) ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - while expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = while(true) {}; \\ var good = {}; \\ _ = while(true) {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - while-continue statement", - \\extern fn entry() { + \\export fn entry() { \\ while(true):({}) {} \\ var good = {}; \\ while(true):({}) ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - while-continue expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = while(true):({}) {}; \\ var good = {}; \\ _ = while(true):({}) {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - for statement", - \\extern fn entry() { + \\export fn entry() { \\ for(foo()) {} \\ var good = {}; \\ for(foo()) ({}) \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("implicit semicolon - for expression", - \\extern fn entry() { + \\export fn entry() { \\ _ = for(foo()) {}; \\ var good = {}; \\ _ = for(foo()) {} \\ var bad = {}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: invalid token: 'var'"); cases.add("multiple function definitions", \\fn a() {} \\fn a() {} - \\comptime {@export("entry", entry);} - \\extern fn entry() { a(); } + \\export fn entry() { a(); } , ".tmp_source.zig:2:1: error: redefinition of 'a'"); cases.add("unreachable with return", \\fn a() -> noreturn {return;} - \\comptime {@export("entry", entry);} - \\extern fn entry() { a(); } + \\export fn entry() { a(); } , ".tmp_source.zig:1:21: error: expected type 'noreturn', found 'void'"); cases.add("control reaches end of non-void function", \\fn a() -> i32 {} - \\comptime {@export("entry", entry);} - \\extern fn entry() { _ = a(); } + \\export fn entry() { _ = a(); } , ".tmp_source.zig:1:15: error: expected type 'i32', found 'void'"); cases.add("undefined function call", - \\extern fn a() { + \\export fn a() { \\ b(); \\} - \\comptime {@export("a", a);} , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); cases.add("wrong number of arguments", - \\extern fn a() { + \\export fn a() { \\ b(1); \\} \\fn b(a: i32, b: i32, c: i32) { } - \\comptime {@export("a", a);} , ".tmp_source.zig:2:6: error: expected 3 arguments, found 1"); cases.add("invalid type", \\fn a() -> bogus {} - \\comptime {@export("entry", entry);} - \\extern fn entry() { _ = a(); } + \\export fn entry() { _ = a(); } , ".tmp_source.zig:1:11: error: use of undeclared identifier 'bogus'"); cases.add("pointer to unreachable", \\fn a() -> &noreturn {} - \\comptime {@export("entry", entry);} - \\extern fn entry() { _ = a(); } + \\export fn entry() { _ = a(); } , ".tmp_source.zig:1:12: error: pointer to unreachable not allowed"); cases.add("unreachable code", - \\extern fn a() { + \\export fn a() { \\ return; \\ b(); \\} \\ \\fn b() {} - \\comptime {@export("a", a);} , ".tmp_source.zig:3:5: error: unreachable code"); cases.add("bad import", \\const bogus = @import("bogus-does-not-exist.zig"); - \\comptime {@export("entry", entry);} - \\extern fn entry() { bogus.bogo(); } + \\export fn entry() { bogus.bogo(); } , ".tmp_source.zig:1:15: error: unable to find 'bogus-does-not-exist.zig'"); cases.add("undeclared identifier", - \\extern fn a() { + \\export fn a() { \\ b + \\ c \\} - \\comptime {@export("a", a);} , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'", ".tmp_source.zig:3:5: error: use of undeclared identifier 'c'"); @@ -330,114 +255,99 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("parameter redeclaration", \\fn f(a : i32, a : i32) { \\} - \\comptime {@export("entry", entry);} - \\extern fn entry() { f(1, 2); } + \\export fn entry() { f(1, 2); } , ".tmp_source.zig:1:15: error: redeclaration of variable 'a'"); cases.add("local variable redeclaration", - \\extern fn f() { + \\export fn f() { \\ const a : i32 = 0; \\ const a = 0; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); cases.add("local variable redeclares parameter", \\fn f(a : i32) { \\ const a = 0; \\} - \\comptime {@export("entry", entry);} - \\extern fn entry() { f(1); } + \\export fn entry() { f(1); } , ".tmp_source.zig:2:5: error: redeclaration of variable 'a'"); cases.add("variable has wrong type", - \\extern fn f() -> i32 { + \\export fn f() -> i32 { \\ const a = c"a"; \\ a \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:5: error: expected type 'i32', found '&const u8'"); cases.add("if condition is bool, not int", - \\extern fn f() { + \\export fn f() { \\ if (0) {} \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:9: error: integer value 0 cannot be implicitly casted to type 'bool'"); cases.add("assign unreachable", - \\extern fn f() { + \\export fn f() { \\ const a = return; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: unreachable code"); cases.add("unreachable variable", - \\extern fn f() { + \\export fn f() { \\ const a: noreturn = {}; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:14: error: variable of type 'noreturn' not allowed"); cases.add("unreachable parameter", \\fn f(a: noreturn) {} - \\comptime {@export("entry", entry);} - \\extern fn entry() { f(); } + \\export fn entry() { f(); } , ".tmp_source.zig:1:9: error: parameter of type 'noreturn' not allowed"); cases.add("bad assignment target", - \\extern fn f() { + \\export fn f() { \\ 3 = 3; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:7: error: cannot assign to constant"); cases.add("assign to constant variable", - \\extern fn f() { + \\export fn f() { \\ const a = 3; \\ a = 4; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:7: error: cannot assign to constant"); cases.add("use of undeclared identifier", - \\extern fn f() { + \\export fn f() { \\ b = 3; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: use of undeclared identifier 'b'"); cases.add("const is a statement, not an expression", - \\extern fn f() { + \\export fn f() { \\ (const a = 0); \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:6: error: invalid token: 'const'"); cases.add("array access of undeclared identifier", - \\extern fn f() { + \\export fn f() { \\ i[i] = i[i]; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: use of undeclared identifier 'i'", ".tmp_source.zig:2:12: error: use of undeclared identifier 'i'"); cases.add("array access of non array", - \\extern fn f() { + \\export fn f() { \\ var bad : bool = undefined; \\ bad[bad] = bad[bad]; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:8: error: array access of non-array type 'bool'", ".tmp_source.zig:3:19: error: array access of non-array type 'bool'"); cases.add("array access with non integer index", - \\extern fn f() { + \\export fn f() { \\ var array = "aoeu"; \\ var bad = false; \\ array[bad] = array[bad]; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:4:11: error: expected type 'usize', found 'bool'", ".tmp_source.zig:4:24: error: expected type 'usize', found 'bool'"); @@ -446,8 +356,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn f() { \\ x = 1; \\} - \\extern fn entry() { f(); } - \\comptime {@export("entry", entry);} + \\export fn entry() { f(); } , ".tmp_source.zig:3:7: error: cannot assign to constant"); @@ -456,33 +365,29 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ const x : i32 = if (b) { 1 }; \\ const y = if (b) { i32(1) }; \\} - \\extern fn entry() { f(true); } - \\comptime {@export("entry", entry);} + \\export fn entry() { f(true); } , ".tmp_source.zig:2:30: error: integer value 1 cannot be implicitly casted to type 'void'", ".tmp_source.zig:3:15: error: incompatible types: 'i32' and 'void'"); cases.add("direct struct loop", \\const A = struct { a : A, }; - \\extern fn entry() -> usize { @sizeOf(A) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(A) } , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); cases.add("indirect struct loop", \\const A = struct { b : B, }; \\const B = struct { c : C, }; \\const C = struct { a : A, }; - \\extern fn entry() -> usize { @sizeOf(A) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(A) } , ".tmp_source.zig:1:11: error: struct 'A' contains itself"); cases.add("invalid struct field", \\const A = struct { x : i32, }; - \\extern fn f() { + \\export fn f() { \\ var a : A = undefined; \\ a.foo = 1; \\ const y = a.bar; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:4:6: error: no member named 'foo' in struct 'A'", ".tmp_source.zig:5:16: error: no member named 'bar' in struct 'A'"); @@ -510,7 +415,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ y : i32, \\ z : i32, \\}; - \\extern fn f() { + \\export fn f() { \\ const a = A { \\ .z = 1, \\ .y = 2, @@ -518,7 +423,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ .z = 4, \\ }; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:11:9: error: duplicate field"); cases.add("missing field in struct value expression", @@ -527,7 +431,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ y : i32, \\ z : i32, \\}; - \\extern fn f() { + \\export fn f() { \\ // we want the error on the '{' not the 'A' because \\ // the A could be a complicated expression \\ const a = A { @@ -535,7 +439,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ .y = 2, \\ }; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:9:17: error: missing field: 'x'"); cases.add("invalid field in struct value expression", @@ -544,79 +447,69 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ y : i32, \\ z : i32, \\}; - \\extern fn f() { + \\export fn f() { \\ const a = A { \\ .z = 4, \\ .y = 2, \\ .foo = 42, \\ }; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:10:9: error: no member named 'foo' in struct 'A'"); cases.add("invalid break expression", - \\extern fn f() { + \\export fn f() { \\ break; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: break expression outside loop"); cases.add("invalid continue expression", - \\extern fn f() { + \\export fn f() { \\ continue; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: continue expression outside loop"); cases.add("invalid maybe type", - \\extern fn f() { + \\export fn f() { \\ if (true) |x| { } \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:9: error: expected nullable type, found 'bool'"); cases.add("cast unreachable", \\fn f() -> i32 { \\ i32(return 1) \\} - \\extern fn entry() { _ = f(); } - \\comptime {@export("entry", entry);} + \\export fn entry() { _ = f(); } , ".tmp_source.zig:2:8: error: unreachable code"); cases.add("invalid builtin fn", \\fn f() -> @bogus(foo) { \\} - \\extern fn entry() { _ = f(); } - \\comptime {@export("entry", entry);} + \\export fn entry() { _ = f(); } , ".tmp_source.zig:1:11: error: invalid builtin function: 'bogus'"); cases.add("top level decl dependency loop", \\const a : @typeOf(b) = 0; \\const b : @typeOf(a) = 0; - \\extern fn entry() { + \\export fn entry() { \\ const c = a + b; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:1: error: 'a' depends on itself"); cases.add("noalias on non pointer param", \\fn f(noalias x: i32) {} - \\extern fn entry() { f(1234); } - \\comptime {@export("entry", entry);} + \\export fn entry() { f(1234); } , ".tmp_source.zig:1:6: error: noalias on non-pointer parameter"); cases.add("struct init syntax for array", \\const foo = []u16{.x = 1024,}; - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:1:18: error: type '[]u16' does not support struct initialization syntax"); cases.add("type variables must be constant", \\var foo = u8; - \\extern fn entry() -> foo { + \\export fn entry() -> foo { \\ return 1; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:1: error: variable of type 'type' must be constant"); @@ -628,10 +521,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ var Bar : i32 = undefined; \\} \\ - \\extern fn entry() { + \\export fn entry() { \\ f(1234); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:4:6: error: redefinition of 'Foo'", ".tmp_source.zig:1:1: note: previous definition is here", @@ -653,8 +545,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:8:5: error: enumeration value 'Number.Four' not handled in switch"); cases.add("switch expression - duplicate enumeration prong", @@ -674,8 +565,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:13:15: error: duplicate switch value", ".tmp_source.zig:10:15: note: other value is here"); @@ -697,8 +587,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:13:15: error: duplicate switch value", ".tmp_source.zig:10:15: note: other value is here"); @@ -710,10 +599,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ else => true, \\ }; \\} - \\extern fn entry() { + \\export fn entry() { \\ f(1234); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:9: error: multiple else prongs in switch expression"); cases.add("switch expression - non exhaustive integer prongs", @@ -722,8 +610,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ 0 => {}, \\ } \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:2:5: error: switch must handle all possibilities"); @@ -736,8 +623,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ 206 ... 255 => 3, \\ } \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:6:9: error: duplicate switch value", ".tmp_source.zig:5:14: note: previous value is here"); @@ -749,16 +635,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\const y: u8 = 100; - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:2:5: error: else prong required when switching on type '&u8'"); cases.add("global variable initializer must be constant expression", \\extern fn foo() -> i32; \\const x = foo(); - \\extern fn entry() -> i32 { x } - \\comptime {@export("entry", entry);} + \\export fn entry() -> i32 { x } , ".tmp_source.zig:2:11: error: unable to evaluate constant expression"); cases.add("array concatenation with wrong type", @@ -766,8 +650,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const derp = usize(1234); \\const a = derp ++ "foo"; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(a)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(a)) } , ".tmp_source.zig:3:11: error: expected array or C string literal, found 'usize'"); cases.add("non compile time array concatenation", @@ -775,14 +658,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ s ++ "foo" \\} \\var s: [10]u8 = undefined; - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:2:5: error: unable to evaluate constant expression"); cases.add("@cImport with bogus include", \\const c = @cImport(@cInclude("bogus.h")); - \\extern fn entry() -> usize { @sizeOf(@typeOf(c.bogo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(c.bogo)) } , ".tmp_source.zig:1:11: error: C import failed", ".h:1:10: note: 'bogus.h' file not found"); @@ -790,20 +671,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const x = 3; \\const y = &x; \\fn foo() -> &const i32 { y } - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:3:26: error: expected type '&const i32', found '&const (integer literal)'"); cases.add("integer overflow error", \\const x : u8 = 300; - \\extern fn entry() -> usize { @sizeOf(@typeOf(x)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(x)) } , ".tmp_source.zig:1:16: error: integer value 300 cannot be implicitly casted to type 'u8'"); cases.add("incompatible number literals", \\const x = 2 == 2.0; - \\extern fn entry() -> usize { @sizeOf(@typeOf(x)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(x)) } , ".tmp_source.zig:1:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'"); cases.add("missing function call param", @@ -829,15 +707,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ const result = members[index](); \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:20:34: error: expected 1 arguments, found 0"); cases.add("missing function name and param name", \\fn () {} \\fn f(i32) {} - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:1:1: error: missing function name", ".tmp_source.zig:2:6: error: missing parameter name"); @@ -847,20 +723,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn a() -> i32 {0} \\fn b() -> i32 {1} \\fn c() -> i32 {2} - \\extern fn entry() -> usize { @sizeOf(@typeOf(fns)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(fns)) } , ".tmp_source.zig:1:21: error: expected type 'fn()', found 'fn() -> i32'"); cases.add("extern function pointer mismatch", \\const fns = [](fn(i32)->i32){ a, b, c }; \\pub fn a(x: i32) -> i32 {x + 0} \\pub fn b(x: i32) -> i32 {x + 1} - \\extern fn c(x: i32) -> i32 {x + 2} - \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(fns)) } + \\export fn c(x: i32) -> i32 {x + 2} \\ - \\comptime {@export("entry", entry);} - \\comptime {@export("c", c);} + \\export fn entry() -> usize { @sizeOf(@typeOf(fns)) } , ".tmp_source.zig:1:37: error: expected type 'fn(i32) -> i32', found 'extern fn(i32) -> i32'"); @@ -868,16 +740,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const x : f64 = 1.0; \\const y : f32 = x; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:2:17: error: expected type 'f32', found 'f64'"); cases.add("colliding invalid top level functions", \\fn func() -> bogus {} \\fn func() -> bogus {} - \\extern fn entry() -> usize { @sizeOf(@typeOf(func)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(func)) } , ".tmp_source.zig:2:1: error: redefinition of 'func'", ".tmp_source.zig:1:14: error: use of undeclared identifier 'bogus'"); @@ -885,8 +755,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("bogus compile var", \\const x = @import("builtin").bogus; - \\extern fn entry() -> usize { @sizeOf(@typeOf(x)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(x)) } , ".tmp_source.zig:1:29: error: no member named 'bogus' in '"); @@ -897,8 +766,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\var global_var: usize = 1; \\fn get() -> usize { global_var } \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(Foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(Foo)) } , ".tmp_source.zig:5:21: error: unable to evaluate constant expression", ".tmp_source.zig:2:12: note: called from here", @@ -911,8 +779,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\}; \\const x = Foo {.field = 1} + Foo {.field = 2}; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(x)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(x)) } , ".tmp_source.zig:4:28: error: invalid operands to binary expression: 'Foo' and 'Foo'"); @@ -922,14 +789,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const int_x = u32(1) / u32(0); \\const float_x = f32(1.0) / f32(0.0); \\ - \\extern fn entry1() -> usize { @sizeOf(@typeOf(lit_int_x)) } - \\extern fn entry2() -> usize { @sizeOf(@typeOf(lit_float_x)) } - \\extern fn entry3() -> usize { @sizeOf(@typeOf(int_x)) } - \\extern fn entry4() -> usize { @sizeOf(@typeOf(float_x)) } - \\comptime {@export("entry1", entry1);} - \\comptime {@export("entry2", entry2);} - \\comptime {@export("entry3", entry3);} - \\comptime {@export("entry4", entry4);} + \\export fn entry1() -> usize { @sizeOf(@typeOf(lit_int_x)) } + \\export fn entry2() -> usize { @sizeOf(@typeOf(lit_float_x)) } + \\export fn entry3() -> usize { @sizeOf(@typeOf(int_x)) } + \\export fn entry4() -> usize { @sizeOf(@typeOf(float_x)) } , ".tmp_source.zig:1:21: error: division by zero is undefined", ".tmp_source.zig:2:25: error: division by zero is undefined", @@ -941,16 +804,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const foo = "a \\b"; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:1:13: error: newline not allowed in string literal"); cases.add("invalid comparison for function pointers", \\fn foo() {} \\const invalid = foo > foo; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(invalid)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(invalid)) } , ".tmp_source.zig:2:21: error: operator not allowed for type 'fn()'"); cases.add("generic function instance with non-constant expression", @@ -959,18 +820,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return foo(a, b); \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(test1)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(test1)) } , ".tmp_source.zig:3:16: error: unable to evaluate constant expression"); cases.add("goto jumping into block", - \\extern fn f() { + \\export fn f() { \\ { \\a_label: \\ } \\ goto a_label; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:5:5: error: no label in scope named 'a_label'"); cases.add("goto jumping past a defer", @@ -981,23 +840,20 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} \\fn derp(){} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:2:12: error: no label in scope named 'label'"); cases.add("assign null to non-nullable pointer", \\const a: &u8 = null; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(a)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(a)) } , ".tmp_source.zig:1:16: error: expected type '&u8', found '(null)'"); cases.add("indexing an array of size zero", \\const array = []u8{}; - \\extern fn foo() { + \\export fn foo() { \\ const pointer = &array[0]; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:27: error: index 0 outside array of size 0"); cases.add("compile time division by zero", @@ -1006,8 +862,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ 1 / x \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:3:7: error: division by zero is undefined", ".tmp_source.zig:1:14: note: called from here"); @@ -1015,8 +870,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("branch on undefined value", \\const x = if (undefined) true else false; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(x)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(x)) } , ".tmp_source.zig:1:15: error: use of undefined value"); @@ -1026,8 +880,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return fibbonaci(x - 1) + fibbonaci(x - 2); \\} \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(seventh_fib_number)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(seventh_fib_number)) } , ".tmp_source.zig:3:21: error: evaluation exceeded 1000 backwards branches", ".tmp_source.zig:3:21: note: called from here"); @@ -1035,8 +888,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("@embedFile with bogus file", \\const resource = @embedFile("bogus.txt"); \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(resource)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(resource)) } , ".tmp_source.zig:1:29: error: unable to find '", "bogus.txt'"); cases.add("non-const expression in struct literal outside function", @@ -1046,8 +898,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const a = Foo {.x = get_it()}; \\extern fn get_it() -> i32; \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(a)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(a)) } , ".tmp_source.zig:4:21: error: unable to evaluate constant expression"); cases.add("non-const expression function call with struct return value outside function", @@ -1061,20 +912,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} \\var global_side_effect = false; \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(a)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(a)) } , ".tmp_source.zig:6:24: error: unable to evaluate constant expression", ".tmp_source.zig:4:17: note: called from here"); cases.add("undeclared identifier error should mark fn as impure", - \\extern fn foo() { + \\export fn foo() { \\ test_a_thing(); \\} \\fn test_a_thing() { \\ bad_fn_call(); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:5: error: use of undeclared identifier 'bad_fn_call'"); cases.add("illegal comparison of types", @@ -1089,16 +938,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ *a == *b \\} \\ - \\extern fn entry1() -> usize { @sizeOf(@typeOf(bad_eql_1)) } - \\extern fn entry2() -> usize { @sizeOf(@typeOf(bad_eql_2)) } - \\comptime {@export("entry1", entry1);} - \\comptime {@export("entry2", entry2);} + \\export fn entry1() -> usize { @sizeOf(@typeOf(bad_eql_1)) } + \\export fn entry2() -> usize { @sizeOf(@typeOf(bad_eql_2)) } , ".tmp_source.zig:2:7: error: operator not allowed for type '[]u8'", ".tmp_source.zig:9:8: error: operator not allowed for type 'EnumWithData'"); cases.add("non-const switch number literal", - \\extern fn foo() { + \\export fn foo() { \\ const x = switch (bar()) { \\ 1, 2 => 1, \\ 3, 4 => 2, @@ -1108,25 +955,22 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn bar() -> i32 { \\ 2 \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: unable to infer expression type"); cases.add("atomic orderings of cmpxchg - failure stricter than success", \\const AtomicOrder = @import("builtin").AtomicOrder; - \\extern fn f() { + \\export fn f() { \\ var x: i32 = 1234; \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success"); cases.add("atomic orderings of cmpxchg - success Monotonic or stricter", \\const AtomicOrder = @import("builtin").AtomicOrder; - \\extern fn f() { + \\export fn f() { \\ var x: i32 = 1234; \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:4:49: error: success atomic ordering must be Monotonic or stricter"); cases.add("negation overflow in function evaluation", @@ -1135,8 +979,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ -x \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:3:5: error: negation caused overflow", ".tmp_source.zig:1:14: note: called from here"); @@ -1147,8 +990,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ a + b \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:3:7: error: operation caused overflow", ".tmp_source.zig:1:14: note: called from here"); @@ -1160,8 +1002,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ a - b \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:3:7: error: operation caused overflow", ".tmp_source.zig:1:14: note: called from here"); @@ -1172,8 +1013,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ a * b \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(y)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(y)) } , ".tmp_source.zig:3:7: error: operation caused overflow", ".tmp_source.zig:1:14: note: called from here"); @@ -1184,35 +1024,40 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ @truncate(i8, x) \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:3:19: error: expected signed integer type, found 'u32'"); cases.add("%return in function with non error return type", - \\extern fn f() { + \\export fn f() { \\ %return something(); \\} \\fn something() -> %void { } - \\comptime {@export("f", f);} , ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); + cases.add("wrong return type for main", + \\pub fn main() { } + , ".tmp_source.zig:1:15: error: expected return type of main to be '%void', instead is 'void'"); + + cases.add("double ?? on main return value", + \\pub fn main() -> ??void { + \\} + , ".tmp_source.zig:1:18: error: expected return type of main to be '%void', instead is '??void'"); + cases.add("invalid pointer for var type", \\extern fn ext() -> usize; \\var bytes: [ext()]u8 = undefined; - \\extern fn f() { + \\export fn f() { \\ for (bytes) |*b, i| { \\ *b = u8(i); \\ } \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:2:13: error: unable to evaluate constant expression"); cases.add("export function with comptime parameter", - \\extern fn foo(comptime x: i32, y: i32) -> i32{ + \\export fn foo(comptime x: i32, y: i32) -> i32{ \\ x + y \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); cases.add("extern function with comptime parameter", @@ -1220,16 +1065,14 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn f() -> i32 { \\ foo(1, 2) \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'"); cases.add("convert fixed size array to slice with invalid size", - \\extern fn f() { + \\export fn f() { \\ var array: [5]u8 = undefined; \\ var foo = ([]const u32)(array)[0]; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:28: error: unable to convert [5]u8 to []const u32: size mismatch"); cases.add("non-pure function returns type", @@ -1247,11 +1090,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\ - \\extern fn function_with_return_type_type() { + \\export fn function_with_return_type_type() { \\ var list: List(i32) = undefined; \\ list.length = 10; \\} - \\comptime {@export("function_with_return_type_type", function_with_return_type_type);} , ".tmp_source.zig:3:7: error: unable to evaluate constant expression", ".tmp_source.zig:16:19: note: called from here"); @@ -1260,8 +1102,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn f(m: []const u8) { \\ m.copy(u8, self[0..], m); \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:3:6: error: no member named 'copy' in '[]const u8'"); cases.add("wrong number of arguments for method fn call", @@ -1272,24 +1113,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ \\ foo.method(1, 2); \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(f)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(f)) } , ".tmp_source.zig:6:15: error: expected 2 arguments, found 3"); cases.add("assign through constant pointer", - \\extern fn f() { + \\export fn f() { \\ var cstr = c"Hat"; \\ cstr[0] = 'W'; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:11: error: cannot assign to constant"); cases.add("assign through constant slice", - \\extern fn f() { + \\export fn f() { \\ var cstr: []const u8 = "Hat"; \\ cstr[0] = 'W'; \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:3:11: error: cannot assign to constant"); cases.add("main function with bogus args type", @@ -1300,8 +1138,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn foo(blah: []u8) { \\ for (blah) { } \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:2:5: error: for loop expression missing element parameter"); cases.add("misspelled type with pointer only reference", @@ -1334,8 +1171,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ var jd = JsonNode {.kind = JsonType.JSONArray , .jobject = JsonOA.JSONArray {jll} }; \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:5:16: error: use of undeclared identifier 'JsonList'"); cases.add("method call with first arg type primitive", @@ -1349,12 +1185,11 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\}; \\ - \\extern fn f() { + \\export fn f() { \\ const derp = Foo.init(3); \\ \\ derp.init(); \\} - \\comptime {@export("f", f);} , ".tmp_source.zig:14:5: error: expected type 'i32', found '&const Foo'"); cases.add("method call with first arg type wrong container", @@ -1378,11 +1213,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ field: i32, \\}; \\ - \\extern fn foo() { + \\export fn foo() { \\ var x = List.init(&global_allocator); \\ x.init(); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:23:5: error: expected type '&Allocator', found '&List'"); cases.add("binary not on number literal", @@ -1390,18 +1224,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; \\var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(block_aligned_stuff)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(block_aligned_stuff)) } , ".tmp_source.zig:3:60: error: unable to perform binary not operation on type '(integer literal)'"); cases.addCase({ const tc = cases.create("multiple files with private function error", \\const foo = @import("foo.zig"); \\ - \\extern fn callPrivFunction() { + \\export fn callPrivFunction() { \\ foo.privateFunction(); \\} - \\comptime {@export("callPrivFunction", callPrivFunction);} , ".tmp_source.zig:4:8: error: 'privateFunction' is private", "foo.zig:1:1: note: declared here"); @@ -1417,19 +1249,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const zero: i32 = 0; \\const a = zero{1}; \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(a)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(a)) } , ".tmp_source.zig:2:11: error: expected type, found 'i32'"); cases.add("assign to constant field", \\const Foo = struct { \\ field: i32, \\}; - \\extern fn derp() { + \\export fn derp() { \\ const f = Foo {.field = 1234,}; \\ f.field = 0; \\} - \\comptime {@export("derp", derp);} , ".tmp_source.zig:6:13: error: cannot assign to constant"); cases.add("return from defer expression", @@ -1447,8 +1277,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return 0; \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(testTrickyDefer)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(testTrickyDefer)) } , ".tmp_source.zig:4:11: error: cannot return from defer expression"); cases.add("attempt to access var args out of bounds", @@ -1460,8 +1289,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ add(i32(1234)) \\} \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:2:19: error: index 1 outside argument list of size 1", ".tmp_source.zig:6:8: note: called from here"); @@ -1479,31 +1307,27 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ add(1, 2, 3, 4) \\} \\ - \\comptime {@export("entry", entry);} - \\extern fn entry() -> usize { @sizeOf(@typeOf(bar)) } + \\export fn entry() -> usize { @sizeOf(@typeOf(bar)) } , ".tmp_source.zig:10:9: error: parameter of type '(integer literal)' requires comptime"); cases.add("assign too big number to u16", - \\extern fn foo() { + \\export fn foo() { \\ var vga_mem: u16 = 0xB8000; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); cases.add("global variable alignment non power of 2", \\const some_data: [100]u8 align(3) = undefined; - \\extern fn entry() -> usize { @sizeOf(@typeOf(some_data)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(some_data)) } , ".tmp_source.zig:1:32: error: alignment value 3 is not a power of 2"); cases.add("function alignment non power of 2", \\extern fn foo() align(3); - \\extern fn entry() { foo() } - \\comptime {@export("entry", entry);} + \\export fn entry() { foo() } , ".tmp_source.zig:1:23: error: alignment value 3 is not a power of 2"); cases.add("compile log", - \\extern fn foo() { + \\export fn foo() { \\ comptime bar(12, "hi"); \\} \\fn bar(a: i32, b: []const u8) { @@ -1511,7 +1335,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ @compileLog("a", a, "b", b); \\ @compileLog("end"); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:5: error: found compile log statement", ".tmp_source.zig:2:17: note: called from here", @@ -1535,8 +1358,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return *x; \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:8:26: error: expected type '&const u3', found '&align(1:3:6) const u3'"); cases.add("referring to a struct that is invalid", @@ -1544,20 +1366,19 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Type: u8, \\}; \\ - \\extern fn foo() { + \\export fn foo() { \\ comptime assert(@sizeOf(UsbDeviceRequest) == 0x8); \\} \\ \\fn assert(ok: bool) { \\ if (!ok) unreachable; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:10:14: error: unable to evaluate constant expression", ".tmp_source.zig:6:20: note: called from here"); cases.add("control flow uses comptime var at runtime", - \\extern fn foo() { + \\export fn foo() { \\ comptime var i = 0; \\ while (i < 5) : (i += 1) { \\ bar(); @@ -1565,61 +1386,53 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\} \\ \\fn bar() { } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:5: error: control flow attempts to use compile-time variable at runtime", ".tmp_source.zig:3:24: note: compile-time variable assigned here"); cases.add("ignored return value", - \\extern fn foo() { + \\export fn foo() { \\ bar(); \\} \\fn bar() -> i32 { 0 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:8: error: expression value is ignored"); cases.add("ignored assert-err-ok return value", - \\extern fn foo() { + \\export fn foo() { \\ %%bar(); \\} \\fn bar() -> %i32 { 0 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:5: error: expression value is ignored"); cases.add("ignored statement value", - \\extern fn foo() { + \\export fn foo() { \\ 1; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:5: error: expression value is ignored"); cases.add("ignored comptime statement value", - \\extern fn foo() { + \\export fn foo() { \\ comptime {1;} \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expression value is ignored"); cases.add("ignored comptime value", - \\extern fn foo() { + \\export fn foo() { \\ comptime 1; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:5: error: expression value is ignored"); cases.add("ignored defered statement value", - \\extern fn foo() { + \\export fn foo() { \\ defer {1;} \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:12: error: expression value is ignored"); cases.add("ignored defered statement value", - \\extern fn foo() { + \\export fn foo() { \\ defer bar(); \\} \\fn bar() -> %i32 { 0 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:14: error: expression value is ignored"); cases.add("dereference an array", @@ -1630,8 +1443,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return (*out)[0..1]; \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(pass)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(pass)) } , ".tmp_source.zig:4:5: error: attempt to dereference non pointer type '[10]u8'"); cases.add("pass const ptr to mutable ptr fn", @@ -1644,31 +1456,46 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ return true; \\} \\ - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:4:19: error: expected type '&[]const u8', found '&const []const u8'"); + cases.addCase({ + const tc = cases.create("export collision", + \\const foo = @import("foo.zig"); + \\ + \\export fn bar() -> usize { + \\ return foo.baz; + \\} + , + "foo.zig:1:8: error: exported symbol collision: 'bar'", + ".tmp_source.zig:3:8: note: other symbol here"); + + tc.addSourceFile("foo.zig", + \\export fn bar() {} + \\pub const baz = 1234; + ); + + tc + }); + cases.add("pass non-copyable type by value to function", \\const Point = struct { x: i32, y: i32, }; \\fn foo(p: Point) { } - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:2:11: error: type 'Point' is not copyable; cannot pass by value"); cases.add("implicit cast from array to mutable slice", \\var global_array: [10]i32 = undefined; \\fn foo(param: []i32) {} - \\extern fn entry() { + \\export fn entry() { \\ foo(global_array); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:4:9: error: expected type '[]i32', found '[10]i32'"); cases.add("ptrcast to non-pointer", - \\extern fn entry(a: &i32) -> usize { + \\export fn entry(a: &i32) -> usize { \\ return @ptrCast(usize, a); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:21: error: expected pointer, found 'usize'"); cases.add("too many error values to cast to small integer", @@ -1677,8 +1504,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn foo(e: error) -> u2 { \\ return u2(e); \\} - \\extern fn entry() -> usize { @sizeOf(@typeOf(foo)) } - \\comptime {@export("entry", entry);} + \\export fn entry() -> usize { @sizeOf(@typeOf(foo)) } , ".tmp_source.zig:4:14: error: too many error values to fit in 'u2'"); cases.add("asm at compile time", @@ -1697,46 +1523,41 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("invalid member of builtin enum", \\const builtin = @import("builtin"); - \\extern fn entry() { + \\export fn entry() { \\ const foo = builtin.Arch.x86; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:3:29: error: container 'Arch' has no member called 'x86'"); cases.add("int to ptr of 0 bits", - \\extern fn foo() { + \\export fn foo() { \\ var x: usize = 0x1000; \\ var y: &void = @intToPtr(&void, x); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:31: error: type '&void' has 0 bits and cannot store information"); cases.add("@fieldParentPtr - non struct", \\const Foo = i32; - \\extern fn foo(a: &i32) -> &Foo { + \\export fn foo(a: &i32) -> &Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:28: error: expected struct type, found 'i32'"); cases.add("@fieldParentPtr - bad field name", \\const Foo = struct { \\ derp: i32, \\}; - \\extern fn foo(a: &i32) -> &Foo { + \\export fn foo(a: &i32) -> &Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:33: error: struct 'Foo' has no field 'a'"); cases.add("@fieldParentPtr - field pointer is not pointer", \\const Foo = struct { \\ a: i32, \\}; - \\extern fn foo(a: i32) -> &Foo { + \\export fn foo(a: i32) -> &Foo { \\ return @fieldParentPtr(Foo, "a", a); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:38: error: expected pointer, found 'i32'"); cases.add("@fieldParentPtr - comptime field ptr not based on struct", @@ -1766,20 +1587,18 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("@offsetOf - non struct", \\const Foo = i32; - \\extern fn foo() -> usize { + \\export fn foo() -> usize { \\ return @offsetOf(Foo, "a"); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:22: error: expected struct type, found 'i32'"); cases.add("@offsetOf - bad field name", \\const Foo = struct { \\ derp: i32, \\}; - \\extern fn foo() -> usize { + \\export fn foo() -> usize { \\ return @offsetOf(Foo, "a"); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:27: error: struct 'Foo' has no field 'a'"); cases.addExe("missing main fn in executable", @@ -1792,22 +1611,44 @@ pub fn addCases(cases: &tests.CompileErrorContext) { "error: 'main' is private", ".tmp_source.zig:1:1: note: declared here"); + cases.add("setting a section on an extern variable", + \\extern var foo: i32 section(".text2"); + \\export fn entry() -> i32 { + \\ return foo; + \\} + , + ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'"); + + cases.add("setting a section on a local variable", + \\export fn entry() -> i32 { + \\ var foo: i32 section(".text2") = 1234; + \\ return foo; + \\} + , + ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'"); + + cases.add("setting a section on an extern fn", + \\extern fn foo() section(".text2"); + \\export fn entry() { + \\ foo(); + \\} + , + ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'"); + cases.add("returning address of local variable - simple", - \\extern fn foo() -> &i32 { + \\export fn foo() -> &i32 { \\ var a: i32 = undefined; \\ return &a; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:13: error: function returns address of local variable"); cases.add("returning address of local variable - phi", - \\extern fn foo(c: bool) -> &i32 { + \\export fn foo(c: bool) -> &i32 { \\ var a: i32 = undefined; \\ var b: i32 = undefined; \\ return if (c) &a else &b; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:4:12: error: function returns address of local variable"); @@ -1836,61 +1677,55 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:5:9: note: previous definition is here"); cases.add("while expected bool, got nullable", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) {} \\} \\fn bar() -> ?i32 { 1 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected type 'bool', found '?i32'"); cases.add("while expected bool, got error union", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) {} \\} \\fn bar() -> %i32 { 1 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected type 'bool', found '%i32'"); cases.add("while expected nullable, got bool", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) |x| {} \\} \\fn bar() -> bool { true } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected nullable type, found 'bool'"); cases.add("while expected nullable, got error union", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) |x| {} \\} \\fn bar() -> %i32 { 1 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected nullable type, found '%i32'"); cases.add("while expected error union, got bool", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) |x| {} else |err| {} \\} \\fn bar() -> bool { true } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected error union type, found 'bool'"); cases.add("while expected error union, got nullable", - \\extern fn foo() { + \\export fn foo() { \\ while (bar()) |x| {} else |err| {} \\} \\fn bar() -> ?i32 { 1 } - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:15: error: expected error union type, found '?i32'"); cases.add("inline fn calls itself indirectly", - \\extern fn foo() { + \\export fn foo() { \\ bar(); \\} \\inline fn bar() { @@ -1902,33 +1737,29 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ quux(); \\} \\extern fn quux(); - \\comptime {@export("foo", foo);} , ".tmp_source.zig:4:8: error: unable to inline function"); cases.add("save reference to inline function", - \\extern fn foo() { + \\export fn foo() { \\ quux(@ptrToInt(bar)); \\} \\inline fn bar() { } \\extern fn quux(usize); - \\comptime {@export("foo", foo);} , ".tmp_source.zig:4:8: error: unable to inline function"); cases.add("signed integer division", - \\extern fn foo(a: i32, b: i32) -> i32 { + \\export fn foo(a: i32, b: i32) -> i32 { \\ a / b \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:7: error: division with 'i32' and 'i32': signed integers must use @divTrunc, @divFloor, or @divExact"); cases.add("signed integer remainder division", - \\extern fn foo(a: i32, b: i32) -> i32 { + \\export fn foo(a: i32, b: i32) -> i32 { \\ a % b \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:7: error: remainder division with 'i32' and 'i32': signed integers and floats must use @rem or @mod"); @@ -1967,65 +1798,59 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits"); cases.add("@setDebugSafety twice for same scope", - \\extern fn foo() { + \\export fn foo() { \\ @setDebugSafety(this, false); \\ @setDebugSafety(this, false); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:5: error: debug safety set twice for same scope", ".tmp_source.zig:2:5: note: first set here"); cases.add("@setFloatMode twice for same scope", - \\extern fn foo() { + \\export fn foo() { \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); \\ @setFloatMode(this, @import("builtin").FloatMode.Optimized); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:5: error: float mode set twice for same scope", ".tmp_source.zig:2:5: note: first set here"); cases.add("array access of type", - \\extern fn foo() { + \\export fn foo() { \\ var b: u8[40] = undefined; \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:2:14: error: array access of non-array type 'type'"); cases.add("cannot break out of defer expression", - \\extern fn foo() { + \\export fn foo() { \\ while (true) { \\ defer { \\ break; \\ } \\ } \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:4:13: error: cannot break out of defer expression"); cases.add("cannot continue out of defer expression", - \\extern fn foo() { + \\export fn foo() { \\ while (true) { \\ defer { \\ continue; \\ } \\ } \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:4:13: error: cannot continue out of defer expression"); cases.add("cannot goto out of defer expression", - \\extern fn foo() { + \\export fn foo() { \\ defer { \\ goto label; \\ }; \\label: \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:3:9: error: cannot goto out of defer expression"); @@ -2059,10 +1884,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const bar = baz + foo; \\const baz = 1; \\ - \\extern fn entry() -> i32 { + \\export fn entry() -> i32 { \\ return bar; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:13: error: aoeu", ".tmp_source.zig:3:19: note: referenced here", @@ -2075,10 +1899,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ \\var foo: Foo = undefined; \\ - \\extern fn entry() -> usize { + \\export fn entry() -> usize { \\ return @sizeOf(@typeOf(foo.x)); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:13: error: struct 'Foo' contains itself"); @@ -2097,18 +1920,16 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:2:15: error: float literal out of range of any type"); cases.add("explicit cast float literal to integer when there is a fraction component", - \\extern fn entry() -> i32 { + \\export fn entry() -> i32 { \\ i32(12.34) \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:9: error: fractional component prevents float value 12.340000 from being casted to type 'i32'"); cases.add("non pointer given to @ptrToInt", - \\extern fn entry(x: i32) -> usize { + \\export fn entry(x: i32) -> usize { \\ @ptrToInt(x) \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:15: error: expected pointer, found 'i32'"); @@ -2127,27 +1948,24 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:2:15: error: exact shift shifted out 1 bits"); cases.add("shifting without int type or comptime known", - \\extern fn entry(x: u8) -> u8 { + \\export fn entry(x: u8) -> u8 { \\ return 0x11 << x; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:17: error: LHS of shift must be an integer type, or RHS must be compile-time known"); cases.add("shifting RHS is log2 of LHS int bit width", - \\extern fn entry(x: u8, y: u8) -> u8 { + \\export fn entry(x: u8, y: u8) -> u8 { \\ return x << y; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:17: error: expected type 'u3', found 'u8'"); cases.add("globally shadowing a primitive type", \\const u16 = @intType(false, 8); - \\extern fn entry() { + \\export fn entry() { \\ const a: u16 = 300; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:1: error: declaration shadows type 'u16'"); @@ -2157,7 +1975,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ b: u32, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var foo = Foo { .a = 1, .b = 10 }; \\ bar(&foo.b); \\} @@ -2165,7 +1983,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn bar(x: &u32) { \\ *x += 1; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:8:13: error: expected type '&u32', found '&align(1) u32'"); @@ -2175,7 +1992,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ b: u32, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var foo = Foo { .a = 1, .b = 10 }; \\ foo.b += 1; \\ bar((&foo.b)[0..1]); @@ -2184,61 +2001,55 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn bar(x: []u32) { \\ x[0] += 1; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:9:17: error: expected type '[]u32', found '[]align(1) u32'"); cases.add("increase pointer alignment in @ptrCast", - \\extern fn entry() -> u32 { + \\export fn entry() -> u32 { \\ var bytes: [4]u8 = []u8{0x01, 0x02, 0x03, 0x04}; \\ const ptr = @ptrCast(&u32, &bytes[0]); \\ return *ptr; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:3:17: error: cast increases pointer alignment", ".tmp_source.zig:3:38: note: '&u8' has alignment 1", ".tmp_source.zig:3:27: note: '&u32' has alignment 4"); cases.add("increase pointer alignment in slice resize", - \\extern fn entry() -> u32 { + \\export fn entry() -> u32 { \\ var bytes = []u8{0x01, 0x02, 0x03, 0x04}; \\ return ([]u32)(bytes[0..])[0]; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:3:19: error: cast increases pointer alignment", ".tmp_source.zig:3:19: note: '[]u8' has alignment 1", ".tmp_source.zig:3:19: note: '[]u32' has alignment 4"); cases.add("@alignCast expects pointer or slice", - \\extern fn entry() { + \\export fn entry() { \\ @alignCast(4, u32(3)) \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:22: error: expected pointer or slice, found 'u32'"); cases.add("passing an under-aligned function pointer", - \\extern fn entry() { + \\export fn entry() { \\ testImplicitlyDecreaseFnAlign(alignedSmall, 1234); \\} \\fn testImplicitlyDecreaseFnAlign(ptr: fn () align(8) -> i32, answer: i32) { \\ if (ptr() != answer) unreachable; \\} \\fn alignedSmall() align(4) -> i32 { 1234 } - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:35: error: expected type 'fn() align(8) -> i32', found 'fn() align(4) -> i32'"); cases.add("passing a not-aligned-enough pointer to cmpxchg", \\const AtomicOrder = @import("builtin").AtomicOrder; - \\extern fn entry() -> bool { + \\export fn entry() -> bool { \\ var x: i32 align(1) = 1234; \\ while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} \\ return x == 5678; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:4:23: error: expected pointer alignment of at least 4, found 1"); @@ -2264,18 +2075,17 @@ pub fn addCases(cases: &tests.CompileErrorContext) { cases.add("wrong pointer implicitly casted to pointer to @OpaqueType()", \\const Derp = @OpaqueType(); \\extern fn bar(d: &Derp); - \\extern fn foo() { + \\export fn foo() { \\ const x = u8(1); \\ bar(@ptrCast(&c_void, &x)); \\} - \\comptime {@export("foo", foo);} , ".tmp_source.zig:5:9: error: expected type '&Derp', found '&c_void'"); cases.add("non-const variables of things that require const variables", \\const Opaque = @OpaqueType(); \\ - \\extern fn entry(opaque: &Opaque) { + \\export fn entry(opaque: &Opaque) { \\ var m2 = &2; \\ const y: u32 = *m2; \\ @@ -2295,7 +2105,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Foo = struct { \\ fn bar(self: &const Foo) {} \\}; - \\comptime {@export("entry", entry);} , ".tmp_source.zig:4:4: error: variable of type '&const (integer literal)' must be const or comptime", ".tmp_source.zig:7:4: error: variable of type '(undefined)' must be const or comptime", @@ -2310,14 +2119,21 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:17:4: error: unreachable code"); cases.add("wrong types given to atomic order args in cmpxchg", - \\extern fn entry() { + \\export fn entry() { \\ var x: i32 = 1234; \\ while (!@cmpxchg(&x, 1234, 5678, u32(1234), u32(1234))) {} \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:3:41: error: expected type 'AtomicOrder', found 'u32'"); + cases.add("wrong types given to @export", + \\extern fn entry() { } + \\comptime { + \\ @export("entry", entry, u32(1234)); + \\} + , + ".tmp_source.zig:3:32: error: expected type 'GlobalLinkage', found 'u32'"); + cases.add("struct with invalid field", \\const std = @import("std"); \\const Allocator = std.mem.Allocator; @@ -2336,13 +2152,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ }, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ const a = MdNode.Header { \\ .text = MdText.init(&std.debug.global_allocator), \\ .weight = HeaderWeight.H1, \\ }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:14:17: error: use of undeclared identifier 'HeaderValue'"); @@ -2354,39 +2169,35 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:2:5: error: @setAlignStack outside function"); cases.add("@setAlignStack in naked function", - \\nakedcc fn entry() { + \\export nakedcc fn entry() { \\ @setAlignStack(16); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:5: error: @setAlignStack in naked function"); cases.add("@setAlignStack in inline function", - \\extern fn entry() { + \\export fn entry() { \\ foo(); \\} \\inline fn foo() { \\ @setAlignStack(16); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:5: error: @setAlignStack in inline function"); cases.add("@setAlignStack set twice", - \\extern fn entry() { + \\export fn entry() { \\ @setAlignStack(16); \\ @setAlignStack(16); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:3:5: error: alignstack set twice", ".tmp_source.zig:2:5: note: first set here"); cases.add("@setAlignStack too big", - \\extern fn entry() { + \\export fn entry() { \\ @setAlignStack(511 + 1); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:5: error: attempt to @setAlignStack(512); maximum is 256"); @@ -2417,7 +2228,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ LinkLibC, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ const tests = []TestCase { \\ Free("001"), \\ Free("002"), @@ -2432,14 +2243,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\ } \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:37:16: error: cannot store runtime value in compile time variable"); cases.add("field access of opaque type", \\const MyType = @OpaqueType(); \\ - \\extern fn entry() -> bool { + \\export fn entry() -> bool { \\ var x: i32 = 1; \\ return bar(@ptrCast(&MyType, &x)); \\} @@ -2447,7 +2257,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\fn bar(x: &MyType) -> bool { \\ return x.blah; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:9:13: error: type '&MyType' does not support field access"); @@ -2551,11 +2360,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { ".tmp_source.zig:2:26: error: member index 1 out of bounds; 'Foo' has 1 members"); cases.add("calling var args extern function, passing array instead of pointer", - \\extern fn entry() { + \\export fn entry() { \\ foo("hello"); \\} \\pub extern fn foo(format: &const u8, ...); - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:9: error: expected type '&const u8', found '[5]u8'"); @@ -2570,10 +2378,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ } \\} \\ - \\extern fn entry() { + \\export fn entry() { \\ var allocator: ContextAllocator = undefined; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:4:25: error: aoeu", ".tmp_source.zig:1:36: note: called from here", @@ -2588,10 +2395,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Five, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var x = Small.One; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:20: error: 'u2' too small to hold all bits; must be at least 'u3'"); @@ -2602,10 +2408,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Three, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var x = Small.One; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:20: error: expected integer, found 'f32'"); @@ -2617,10 +2422,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Four, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var x: u2 = Small.Two; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'"); @@ -2632,10 +2436,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Four, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var x = u3(Small.Two); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'"); @@ -2647,11 +2450,10 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Four, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var y = u3(3); \\ var x = Small(y); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'"); @@ -2663,10 +2465,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ Four, \\}; \\ - \\extern fn entry() { + \\export fn entry() { \\ var y = Small.Two; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:19: error: expected unsigned integer, found 'i2'"); @@ -2674,10 +2475,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const MultipleChoice = struct { \\ A: i32 = 20, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x: MultipleChoice = undefined; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:14: error: enums, not structs, support field assignment"); @@ -2685,29 +2485,26 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const MultipleChoice = union { \\ A: i32 = 20, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x: MultipleChoice = undefined; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:14: error: non-enum union field assignment", ".tmp_source.zig:1:24: note: consider 'union(enum)' here"); cases.add("enum with 0 fields", \\const Foo = enum {}; - \\extern fn entry() -> usize { + \\export fn entry() -> usize { \\ return @sizeOf(Foo); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:13: error: enums must have 1 or more fields"); cases.add("union with 0 fields", \\const Foo = union {}; - \\extern fn entry() -> usize { + \\export fn entry() -> usize { \\ return @sizeOf(Foo); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:13: error: unions must have 1 or more fields"); @@ -2719,10 +2516,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ D = 1000, \\ E = 60, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x = MultipleChoice.C; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:9: error: enum tag value 60 already taken", ".tmp_source.zig:4:9: note: other occurrence here"); @@ -2737,10 +2533,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ A: i32, \\ B: f64, \\}; - \\extern fn entry() -> usize { + \\export fn entry() -> usize { \\ return @sizeOf(Payload); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:17: error: enum field missing: 'C'", ".tmp_source.zig:4:5: note: declared here"); @@ -2749,10 +2544,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Foo = union { \\ A: i32, \\}; - \\extern fn entry() { + \\export fn entry() { \\ const x = @TagType(Foo); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:5:24: error: union 'Foo' has no tag", ".tmp_source.zig:1:13: note: consider 'union(enum)' here"); @@ -2761,10 +2555,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Foo = union(enum(f32)) { \\ A: i32, \\}; - \\extern fn entry() { + \\export fn entry() { \\ const x = @TagType(Foo); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:23: error: expected integer tag type, found 'f32'"); @@ -2772,10 +2565,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Foo = union(u32) { \\ A: i32, \\}; - \\extern fn entry() { + \\export fn entry() { \\ const x = @TagType(Foo); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:1:18: error: expected enum tag type, found 'u32'"); @@ -2787,10 +2579,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ D = 1000, \\ E = 60, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x = MultipleChoice { .C = {} }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:9: error: enum tag value 60 already taken", ".tmp_source.zig:4:9: note: other occurrence here"); @@ -2807,10 +2598,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ C: bool, \\ D: bool, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var a = Payload {.A = 1234}; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:10:5: error: enum field not found: 'D'", ".tmp_source.zig:1:16: note: enum declared here"); @@ -2821,10 +2611,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B, \\ C, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var b = Letter.B; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:8: error: structs and unions, not enums, support field types", ".tmp_source.zig:1:16: note: consider 'union(enum)' here"); @@ -2833,10 +2622,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Letter = struct { \\ A, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var a = Letter { .A = {} }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:5: error: struct field missing type"); @@ -2844,10 +2632,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const Letter = extern union { \\ A, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var a = Letter { .A = {} }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:2:5: error: union field missing type"); @@ -2862,10 +2649,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B: f64, \\ C: bool, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var a = Payload { .A = { 1234 } }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:29: error: extern union does not support enum tag type"); @@ -2880,10 +2666,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B: f64, \\ C: bool, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var a = Payload { .A = { 1234 } }; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:29: error: packed union does not support enum tag type"); @@ -2893,7 +2678,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B: f64, \\ C: bool, \\}; - \\extern fn entry() { + \\export fn entry() { \\ const a = Payload { .A = { 1234 } }; \\ foo(a); \\} @@ -2903,7 +2688,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ else => unreachable, \\ } \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:11:13: error: switch on union which has no attached enum", ".tmp_source.zig:1:17: note: consider 'union(enum)' here"); @@ -2913,10 +2697,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ A = 10, \\ B = 11, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x = Foo(0); \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0", ".tmp_source.zig:1:13: note: 'Foo' declared here"); @@ -2928,10 +2711,9 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B, \\ C, \\}; - \\extern fn entry() { + \\export fn entry() { \\ var x: Value = Letter.A; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:8:26: error: cast to union 'Value' must initialize 'i32' field 'A'", ".tmp_source.zig:3:5: note: field 'A' declared here"); @@ -2943,36 +2725,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\ B, \\ C, \\}; - \\extern fn entry() { + \\export fn entry() { \\ foo(Letter.A); \\} \\fn foo(l: Letter) { \\ var x: Value = l; \\} - \\comptime {@export("entry", entry);} , ".tmp_source.zig:11:20: error: runtime cast to union 'Value' which has non-void fields", ".tmp_source.zig:3:5: note: field 'A' has type 'i32'"); - - cases.addCase({ - const tc = cases.create("export collision", - \\const foo = @import("foo.zig"); - \\ - \\comptime {@export("bar", bar);} - \\extern fn bar() -> usize { - \\ return foo.baz; - \\} - , - "foo.zig:2:11: error: exported symbol collision: 'bar'", - ".tmp_source.zig:3:11: note: other symbol is here"); - - tc.addSourceFile("foo.zig", - \\extern fn bar() {} - \\comptime {@export("bar", bar);} - \\pub const baz = 1234; - ); - - tc - }); - } diff --git a/test/standalone/issue_339/test.zig b/test/standalone/issue_339/test.zig index a3058e58ed..c1faa015c6 100644 --- a/test/standalone/issue_339/test.zig +++ b/test/standalone/issue_339/test.zig @@ -2,9 +2,6 @@ pub fn panic(msg: []const u8) -> noreturn { @breakpoint(); while (true) {} } fn bar() -> %void {} -comptime { - @export("foo", foo); -} -extern fn foo() { +export fn foo() { %%bar(); } diff --git a/test/translate_c.zig b/test/translate_c.zig index 01f6622a71..aff2140f8d 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -26,7 +26,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return a < 0 ? -a : a; \\} , - \\pub fn abs(a: c_int) -> c_int { + \\export fn abs(a: c_int) -> c_int { \\ return if (a < 0) -a else a; \\} ); @@ -325,12 +325,12 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return a; \\} , - \\pub fn foo1(_arg_a: c_uint) -> c_uint { + \\pub export fn foo1(_arg_a: c_uint) -> c_uint { \\ var a = _arg_a; \\ a +%= 1; \\ return a; \\} - \\pub fn foo2(_arg_a: c_int) -> c_int { + \\pub export fn foo2(_arg_a: c_int) -> c_int { \\ var a = _arg_a; \\ a += 1; \\ return a; @@ -346,7 +346,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return i; \\} , - \\pub fn log2(_arg_a: c_uint) -> c_int { + \\pub export fn log2(_arg_a: c_uint) -> c_int { \\ var a = _arg_a; \\ var i: c_int = 0; \\ while (a > c_uint(0)) { @@ -367,7 +367,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return a; \\} , - \\pub fn max(a: c_int, b: c_int) -> c_int { + \\pub export fn max(a: c_int, b: c_int) -> c_int { \\ if (a < b) return b; \\ if (a < b) return b else return a; \\} @@ -382,7 +382,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return a; \\} , - \\pub fn max(a: c_int, b: c_int) -> c_int { + \\pub export fn max(a: c_int, b: c_int) -> c_int { \\ if (a == b) return a; \\ if (a != b) return b; \\ return a; @@ -407,7 +407,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ c = a % b; \\} , - \\pub fn s(a: c_int, b: c_int) -> c_int { + \\pub export fn s(a: c_int, b: c_int) -> c_int { \\ var c: c_int; \\ c = (a + b); \\ c = (a - b); @@ -415,7 +415,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ c = @divTrunc(a, b); \\ c = @rem(a, b); \\} - \\pub fn u(a: c_uint, b: c_uint) -> c_uint { + \\pub export fn u(a: c_uint, b: c_uint) -> c_uint { \\ var c: c_uint; \\ c = (a +% b); \\ c = (a -% b); @@ -430,7 +430,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return (a & b) ^ (a | b); \\} , - \\pub fn max(a: c_int, b: c_int) -> c_int { + \\pub export fn max(a: c_int, b: c_int) -> c_int { \\ return (a & b) ^ (a | b); \\} ); @@ -444,7 +444,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return a; \\} , - \\pub fn max(a: c_int, b: c_int) -> c_int { + \\pub export fn max(a: c_int, b: c_int) -> c_int { \\ if ((a < b) or (a == b)) return b; \\ if ((a >= b) and (a == b)) return a; \\ return a; @@ -458,7 +458,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ a = tmp; \\} , - \\pub fn max(_arg_a: c_int) -> c_int { + \\pub export fn max(_arg_a: c_int) -> c_int { \\ var a = _arg_a; \\ var tmp: c_int; \\ tmp = a; @@ -472,7 +472,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ c = b = a; \\} , - \\pub fn max(a: c_int) { + \\pub export fn max(a: c_int) { \\ var b: c_int; \\ var c: c_int; \\ c = { @@ -493,7 +493,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return i; \\} , - \\pub fn log2(_arg_a: u32) -> c_int { + \\pub export fn log2(_arg_a: u32) -> c_int { \\ var a = _arg_a; \\ var i: c_int = 0; \\ while (a > c_uint(0)) { @@ -518,7 +518,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\void foo(void) { bar(); } , \\pub fn bar() {} - \\pub fn foo() { + \\pub export fn foo() { \\ bar(); \\} ); @@ -534,7 +534,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\pub const struct_Foo = extern struct { \\ field: c_int, \\}; - \\pub fn read_field(foo: ?&struct_Foo) -> c_int { + \\pub export fn read_field(foo: ?&struct_Foo) -> c_int { \\ return (??foo).field; \\} ); @@ -544,7 +544,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ ;;;;; \\} , - \\pub fn foo() {} + \\pub export fn foo() {} ); cases.add("undefined array global", @@ -560,7 +560,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\} , \\pub var array: [100]c_int = undefined; - \\pub fn foo(index: c_int) -> c_int { + \\pub export fn foo(index: c_int) -> c_int { \\ return array[index]; \\} ); @@ -571,7 +571,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return (int)a; \\} , - \\pub fn float_to_int(a: f32) -> c_int { + \\pub export fn float_to_int(a: f32) -> c_int { \\ return c_int(a); \\} ); @@ -581,7 +581,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return x; \\} , - \\pub fn foo(x: ?&c_ushort) -> ?&c_void { + \\pub export fn foo(x: ?&c_ushort) -> ?&c_void { \\ return @ptrCast(?&c_void, x); \\} ); @@ -592,7 +592,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return sizeof(int); \\} , - \\pub fn size_of() -> usize { + \\pub export fn size_of() -> usize { \\ return @sizeOf(c_int); \\} ); @@ -602,7 +602,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return 0; \\} , - \\pub fn foo() -> ?&c_int { + \\pub export fn foo() -> ?&c_int { \\ return null; \\} ); @@ -612,7 +612,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return 1, 2; \\} , - \\pub fn foo() -> c_int { + \\pub export fn foo() -> c_int { \\ return { \\ _ = 1; \\ 2 @@ -625,7 +625,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ return (1 << 2) >> 1; \\} , - \\pub fn foo() -> c_int { + \\pub export fn foo() -> c_int { \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1); \\} ); @@ -643,7 +643,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ a <<= (a <<= 1); \\} , - \\pub fn foo() { + \\pub export fn foo() { \\ var a: c_int = 0; \\ a += { \\ const _ref = &a; @@ -701,7 +701,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ a <<= (a <<= 1); \\} , - \\pub fn foo() { + \\pub export fn foo() { \\ var a: c_uint = c_uint(0); \\ a +%= { \\ const _ref = &a; @@ -771,7 +771,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ u = u--; \\} , - \\pub fn foo() { + \\pub export fn foo() { \\ var i: c_int = 0; \\ var u: c_uint = c_uint(0); \\ i += 1; @@ -819,7 +819,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ u = --u; \\} , - \\pub fn foo() { + \\pub export fn foo() { \\ var i: c_int = 0; \\ var u: c_uint = c_uint(0); \\ i += 1; @@ -862,7 +862,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ while (b != 0); \\} , - \\pub fn foo() { + \\pub export fn foo() { \\ var a: c_int = 2; \\ while (true) { \\ a -= 1; @@ -886,9 +886,9 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ baz(); \\} , - \\pub fn foo() {} - \\pub fn baz() {} - \\pub fn bar() { + \\pub export fn foo() {} + \\pub export fn baz() {} + \\pub export fn bar() { \\ var f: ?extern fn() = foo; \\ (??f)(); \\ (??f)(); @@ -901,7 +901,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { \\ *x = 1; \\} , - \\pub fn foo(x: ?&c_int) { + \\pub export fn foo(x: ?&c_int) { \\ (*??x) = 1; \\} ); -- cgit v1.2.3