| author | |
| committer | |
| log | 5f7685336f2b0bd5e14765d885b0cf87ebe1f578 |
| tree | 84218637c6dcf91efde85759c5f4f0efdf6af2ed |
| parent | ca8d8f114f0db4f3ed51c410c0e9f93aaf03e14d |
closes #648 files changed, 242 insertions(+), 166 deletions(-)
example/cat/main.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | export executable "cat"; |
| 2 | 2 | |
| 3 | pub main(argv: [][]u8) -> i32 { | |
| 3 | pub fn main(argv: [][]u8) i32 => { | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | return 0; |
example/guess_number/main.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ export executable "guess_number"; |
| 3 | 3 | import "std.zig"; |
| 4 | 4 | import "rand.zig"; |
| 5 | 5 | |
| 6 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 6 | pub fn main(args: [][]u8) i32 => { | |
| 7 | 7 | print_str("Welcome to the Guess Number Game in Zig.\n"); |
| 8 | 8 | |
| 9 | 9 | var seed : u32; |
example/hello_world/hello.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ export executable "hello"; |
| 2 | 2 | |
| 3 | 3 | import "std.zig"; |
| 4 | 4 | |
| 5 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 5 | pub fn main(args: [][]u8) i32 => { | |
| 6 | 6 | print_str("Hello, world!\n"); |
| 7 | 7 | return 0; |
| 8 | 8 | } |
example/multiple_files/main.zig+1-1| ... | ... | @@ -3,7 +3,7 @@ export executable "test-multiple-files"; |
| 3 | 3 | import "std.zig"; |
| 4 | 4 | import "foo.zig"; |
| 5 | 5 | |
| 6 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 6 | pub fn main(args: [][]u8) i32 => { | |
| 7 | 7 | private_function(); |
| 8 | 8 | print_str("OK 2\n"); |
| 9 | 9 | return 0; |
src/analyze.cpp+35-86| ... | ... | @@ -64,7 +64,7 @@ static AstNode *first_executing_node(AstNode *node) { |
| 64 | 64 | case NodeTypeArrayType: |
| 65 | 65 | return node; |
| 66 | 66 | } |
| 67 | zig_panic("unreachable"); | |
| 67 | zig_unreachable(); | |
| 68 | 68 | } |
| 69 | 69 | |
| 70 | 70 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| ... | ... | @@ -81,29 +81,6 @@ void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 81 | 81 | g->errors.append(err); |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) { | |
| 85 | char *dot1 = strstr(buf_ptr(buf), "."); | |
| 86 | if (!dot1) | |
| 87 | return ErrorInvalidFormat; | |
| 88 | char *dot2 = strstr(dot1 + 1, "."); | |
| 89 | if (!dot2) | |
| 90 | return ErrorInvalidFormat; | |
| 91 | ||
| 92 | *major = (int)strtol(buf_ptr(buf), nullptr, 10); | |
| 93 | *minor = (int)strtol(dot1 + 1, nullptr, 10); | |
| 94 | *patch = (int)strtol(dot2 + 1, nullptr, 10); | |
| 95 | ||
| 96 | return ErrorNone; | |
| 97 | } | |
| 98 | ||
| 99 | static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) { | |
| 100 | int err; | |
| 101 | if ((err = parse_version_string(version_buf, &g->version_major, &g->version_minor, &g->version_patch))) { | |
| 102 | add_node_error(g, node, | |
| 103 | buf_sprintf("invalid version string")); | |
| 104 | } | |
| 105 | } | |
| 106 | ||
| 107 | 84 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id) { |
| 108 | 85 | TypeTableEntry *entry = allocate<TypeTableEntry>(1); |
| 109 | 86 | entry->arrays_by_size.init(2); |
| ... | ... | @@ -258,9 +235,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui |
| 258 | 235 | } |
| 259 | 236 | } |
| 260 | 237 | |
| 261 | static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import, | |
| 262 | TypeTableEntry *child_type, bool is_const) | |
| 263 | { | |
| 238 | static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) { | |
| 264 | 239 | assert(child_type->id != TypeTableEntryIdInvalid); |
| 265 | 240 | TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)]; |
| 266 | 241 | if (*parent_pointer) { |
| ... | ... | @@ -268,8 +243,9 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry |
| 268 | 243 | } else { |
| 269 | 244 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct); |
| 270 | 245 | |
| 246 | const char *const_str = is_const ? "const " : ""; | |
| 271 | 247 | buf_resize(&entry->name, 0); |
| 272 | buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name)); | |
| 248 | buf_appendf(&entry->name, "[]%s%s", const_str, buf_ptr(&child_type->name)); | |
| 273 | 249 | entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); |
| 274 | 250 | |
| 275 | 251 | TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const); |
| ... | ... | @@ -818,47 +794,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 818 | 794 | preview_fn_proto(g, import, node); |
| 819 | 795 | break; |
| 820 | 796 | case NodeTypeRootExportDecl: |
| 821 | if (import == g->root_import) { | |
| 822 | for (int i = 0; i < node->data.root_export_decl.directives->length; i += 1) { | |
| 823 | AstNode *directive_node = node->data.root_export_decl.directives->at(i); | |
| 824 | Buf *name = &directive_node->data.directive.name; | |
| 825 | Buf *param = &directive_node->data.directive.param; | |
| 826 | if (buf_eql_str(name, "version")) { | |
| 827 | set_root_export_version(g, param, directive_node); | |
| 828 | } else { | |
| 829 | add_node_error(g, directive_node, | |
| 830 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | |
| 831 | } | |
| 832 | } | |
| 833 | ||
| 834 | if (g->root_export_decl) { | |
| 835 | add_node_error(g, node, | |
| 836 | buf_sprintf("only one root export declaration allowed")); | |
| 837 | } else { | |
| 838 | g->root_export_decl = node; | |
| 839 | ||
| 840 | if (!g->root_out_name) | |
| 841 | g->root_out_name = &node->data.root_export_decl.name; | |
| 842 | ||
| 843 | Buf *out_type = &node->data.root_export_decl.type; | |
| 844 | OutType export_out_type; | |
| 845 | if (buf_eql_str(out_type, "executable")) { | |
| 846 | export_out_type = OutTypeExe; | |
| 847 | } else if (buf_eql_str(out_type, "library")) { | |
| 848 | export_out_type = OutTypeLib; | |
| 849 | } else if (buf_eql_str(out_type, "object")) { | |
| 850 | export_out_type = OutTypeObj; | |
| 851 | } else { | |
| 852 | add_node_error(g, node, | |
| 853 | buf_sprintf("invalid export type: '%s'", buf_ptr(out_type))); | |
| 854 | } | |
| 855 | if (g->out_type == OutTypeUnknown) | |
| 856 | g->out_type = export_out_type; | |
| 857 | } | |
| 858 | } else { | |
| 859 | add_node_error(g, node, | |
| 860 | buf_sprintf("root export declaration only valid in root source file")); | |
| 861 | } | |
| 797 | // handled earlier | |
| 862 | 798 | break; |
| 863 | 799 | case NodeTypeStructDecl: |
| 864 | 800 | { |
| ... | ... | @@ -1126,7 +1062,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1126 | 1062 | if (expected_type->id == TypeTableEntryIdInt && |
| 1127 | 1063 | actual_type->id == TypeTableEntryIdInt && |
| 1128 | 1064 | expected_type->data.integral.is_signed == actual_type->data.integral.is_signed && |
| 1129 | expected_type->size_in_bits > actual_type->size_in_bits) | |
| 1065 | expected_type->size_in_bits >= actual_type->size_in_bits) | |
| 1130 | 1066 | { |
| 1131 | 1067 | Expr *expr = get_resolved_expr(node); |
| 1132 | 1068 | expr->implicit_cast.after_type = expected_type; |
| ... | ... | @@ -1149,7 +1085,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1149 | 1085 | return expected_type; |
| 1150 | 1086 | } |
| 1151 | 1087 | |
| 1152 | // implicit non-const to const and ignore noalias | |
| 1088 | // implicit non-const to const for pointers | |
| 1153 | 1089 | if (expected_type->id == TypeTableEntryIdPointer && |
| 1154 | 1090 | actual_type->id == TypeTableEntryIdPointer && |
| 1155 | 1091 | (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const)) |
| ... | ... | @@ -1163,6 +1099,23 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont |
| 1163 | 1099 | return expected_type; |
| 1164 | 1100 | } |
| 1165 | 1101 | |
| 1102 | // implicit non-const to const for unknown size arrays | |
| 1103 | if (expected_type->id == TypeTableEntryIdStruct && | |
| 1104 | actual_type->id == TypeTableEntryIdStruct && | |
| 1105 | expected_type->data.structure.is_unknown_size_array && | |
| 1106 | actual_type->data.structure.is_unknown_size_array && | |
| 1107 | (!actual_type->data.structure.fields[0].type_entry->data.pointer.is_const || | |
| 1108 | expected_type->data.structure.fields[0].type_entry->data.pointer.is_const)) | |
| 1109 | { | |
| 1110 | TypeTableEntry *resolved_type = resolve_type_compatibility(g, context, node, | |
| 1111 | expected_type->data.structure.fields[0].type_entry->data.pointer.child_type, | |
| 1112 | actual_type->data.structure.fields[0].type_entry->data.pointer.child_type); | |
| 1113 | if (resolved_type->id == TypeTableEntryIdInvalid) { | |
| 1114 | return resolved_type; | |
| 1115 | } | |
| 1116 | return expected_type; | |
| 1117 | } | |
| 1118 | ||
| 1166 | 1119 | add_node_error(g, first_executing_node(node), |
| 1167 | 1120 | buf_sprintf("expected type '%s', got '%s'", |
| 1168 | 1121 | buf_ptr(&expected_type->name), |
| ... | ... | @@ -1511,15 +1464,15 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import, |
| 1511 | 1464 | if (array_type->id == TypeTableEntryIdInvalid) { |
| 1512 | 1465 | return_type = g->builtin_types.entry_invalid; |
| 1513 | 1466 | } else if (array_type->id == TypeTableEntryIdArray) { |
| 1514 | return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type, | |
| 1467 | return_type = get_unknown_size_array_type(g, array_type->data.array.child_type, | |
| 1515 | 1468 | node->data.slice_expr.is_const); |
| 1516 | 1469 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 1517 | return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type, | |
| 1470 | return_type = get_unknown_size_array_type(g, array_type->data.pointer.child_type, | |
| 1518 | 1471 | node->data.slice_expr.is_const); |
| 1519 | 1472 | } else if (array_type->id == TypeTableEntryIdStruct && |
| 1520 | 1473 | array_type->data.structure.is_unknown_size_array) |
| 1521 | 1474 | { |
| 1522 | return_type = get_unknown_size_array_type(g, import, | |
| 1475 | return_type = get_unknown_size_array_type(g, | |
| 1523 | 1476 | array_type->data.structure.fields[0].type_entry->data.pointer.child_type, |
| 1524 | 1477 | node->data.slice_expr.is_const); |
| 1525 | 1478 | } else { |
| ... | ... | @@ -2045,6 +1998,11 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 2045 | 1998 | add_node_error(g, source_node, |
| 2046 | 1999 | buf_sprintf("unable to infer variable type")); |
| 2047 | 2000 | implicit_type = g->builtin_types.entry_invalid; |
| 2001 | } else if (implicit_type->id == TypeTableEntryIdMetaType && | |
| 2002 | !variable_declaration->is_const) | |
| 2003 | { | |
| 2004 | add_node_error(g, source_node, buf_sprintf("variable of type 'type' must be constant")); | |
| 2005 | implicit_type = g->builtin_types.entry_invalid; | |
| 2048 | 2006 | } |
| 2049 | 2007 | } |
| 2050 | 2008 | |
| ... | ... | @@ -2175,12 +2133,12 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, |
| 2175 | 2133 | return resolve_expr_const_val_as_type(g, node, |
| 2176 | 2134 | get_array_type(g, child_type, const_val->data.x_uint)); |
| 2177 | 2135 | } else { |
| 2178 | add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression")); | |
| 2179 | return g->builtin_types.entry_invalid; | |
| 2136 | return resolve_expr_const_val_as_type(g, node, | |
| 2137 | get_unknown_size_array_type(g, child_type, node->data.array_type.is_const)); | |
| 2180 | 2138 | } |
| 2181 | 2139 | } else { |
| 2182 | 2140 | return resolve_expr_const_val_as_type(g, node, |
| 2183 | get_unknown_size_array_type(g, import, child_type, node->data.array_type.is_const)); | |
| 2141 | get_unknown_size_array_type(g, child_type, node->data.array_type.is_const)); | |
| 2184 | 2142 | } |
| 2185 | 2143 | } |
| 2186 | 2144 | |
| ... | ... | @@ -2587,7 +2545,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 2587 | 2545 | return resolve_expr_const_val_as_type(g, node, type_entry); |
| 2588 | 2546 | } |
| 2589 | 2547 | } |
| 2590 | ||
| 2591 | 2548 | } |
| 2592 | 2549 | zig_unreachable(); |
| 2593 | 2550 | } |
| ... | ... | @@ -3677,14 +3634,6 @@ void semantic_analyze(CodeGen *g) { |
| 3677 | 3634 | analyze_top_level_decls_root(g, import, import->root); |
| 3678 | 3635 | } |
| 3679 | 3636 | } |
| 3680 | ||
| 3681 | if (!g->root_out_name) { | |
| 3682 | add_node_error(g, g->root_import->root, | |
| 3683 | buf_sprintf("missing export declaration and output name not provided")); | |
| 3684 | } else if (g->out_type == OutTypeUnknown) { | |
| 3685 | add_node_error(g, g->root_import->root, | |
| 3686 | buf_sprintf("missing export declaration and export type not provided")); | |
| 3687 | } | |
| 3688 | 3637 | } |
| 3689 | 3638 | |
| 3690 | 3639 | Expr *get_resolved_expr(AstNode *node) { |
src/codegen.cpp+145-21| ... | ... | @@ -636,7 +636,19 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) { |
| 636 | 636 | |
| 637 | 637 | return tmp_struct_ptr; |
| 638 | 638 | } else if (array_type->id == TypeTableEntryIdPointer) { |
| 639 | zig_panic("TODO gen_slice_expr pointer"); | |
| 639 | LLVMValueRef start_val = gen_expr(g, node->data.slice_expr.start); | |
| 640 | LLVMValueRef end_val = gen_expr(g, node->data.slice_expr.end); | |
| 641 | ||
| 642 | add_debug_source_node(g, node); | |
| 643 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 0, ""); | |
| 644 | LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); | |
| 645 | LLVMBuildStore(g->builder, slice_start_ptr, ptr_field_ptr); | |
| 646 | ||
| 647 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, 1, ""); | |
| 648 | LLVMValueRef len_value = LLVMBuildSub(g->builder, end_val, start_val, ""); | |
| 649 | LLVMBuildStore(g->builder, len_value, len_field_ptr); | |
| 650 | ||
| 651 | return tmp_struct_ptr; | |
| 640 | 652 | } else if (array_type->id == TypeTableEntryIdStruct) { |
| 641 | 653 | assert(array_type->data.structure.is_unknown_size_array); |
| 642 | 654 | assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); |
| ... | ... | @@ -1767,25 +1779,62 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa |
| 1767 | 1779 | } |
| 1768 | 1780 | gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref, |
| 1769 | 1781 | value, variable->type, expr_type); |
| 1770 | } else if (g->build_type != CodeGenBuildTypeRelease) { | |
| 1771 | // memset uninitialized memory to 0xa | |
| 1772 | add_debug_source_node(g, source_node); | |
| 1773 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 1774 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | |
| 1775 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, ""); | |
| 1776 | LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), | |
| 1777 | variable->type->size_in_bits / 8, false); | |
| 1778 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), | |
| 1779 | variable->type->align_in_bits / 8, false); | |
| 1780 | LLVMValueRef params[] = { | |
| 1781 | dest_ptr, | |
| 1782 | fill_char, | |
| 1783 | byte_count, | |
| 1784 | align_in_bytes, | |
| 1785 | LLVMConstNull(LLVMInt1Type()), // is volatile | |
| 1786 | }; | |
| 1782 | } else { | |
| 1783 | bool ignore_uninit = false; | |
| 1784 | TypeTableEntry *var_type = get_type_for_type_node(var_decl->type); | |
| 1785 | if (var_type->id == TypeTableEntryIdStruct && | |
| 1786 | var_type->data.structure.is_unknown_size_array) | |
| 1787 | { | |
| 1788 | assert(var_decl->type->type == NodeTypeArrayType); | |
| 1789 | AstNode *size_node = var_decl->type->data.array_type.size; | |
| 1790 | if (size_node) { | |
| 1791 | ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; | |
| 1792 | if (!const_val->ok) { | |
| 1793 | TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry; | |
| 1794 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 1795 | TypeTableEntry *child_type = ptr_type->data.pointer.child_type; | |
| 1796 | ||
| 1797 | LLVMValueRef size_val = gen_expr(g, size_node); | |
| 1798 | ||
| 1799 | add_debug_source_node(g, source_node); | |
| 1800 | LLVMValueRef ptr_val = LLVMBuildArrayAlloca(g->builder, child_type->type_ref, | |
| 1801 | size_val, ""); | |
| 1802 | ||
| 1803 | // store the freshly allocated pointer in the unknown size array struct | |
| 1804 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, | |
| 1805 | variable->value_ref, 0, ""); | |
| 1806 | LLVMBuildStore(g->builder, ptr_val, ptr_field_ptr); | |
| 1807 | ||
| 1808 | // store the size in the len field | |
| 1809 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, | |
| 1810 | variable->value_ref, 1, ""); | |
| 1811 | LLVMBuildStore(g->builder, size_val, len_field_ptr); | |
| 1812 | ||
| 1813 | // don't clobber what we just did with debug initialization | |
| 1814 | ignore_uninit = true; | |
| 1815 | } | |
| 1816 | } | |
| 1817 | } | |
| 1818 | if (!ignore_uninit && g->build_type != CodeGenBuildTypeRelease) { | |
| 1819 | // memset uninitialized memory to 0xa | |
| 1820 | add_debug_source_node(g, source_node); | |
| 1821 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | |
| 1822 | LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); | |
| 1823 | LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, ""); | |
| 1824 | LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8), | |
| 1825 | variable->type->size_in_bits / 8, false); | |
| 1826 | LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(), | |
| 1827 | variable->type->align_in_bits / 8, false); | |
| 1828 | LLVMValueRef params[] = { | |
| 1829 | dest_ptr, | |
| 1830 | fill_char, | |
| 1831 | byte_count, | |
| 1832 | align_in_bytes, | |
| 1833 | LLVMConstNull(LLVMInt1Type()), // is volatile | |
| 1834 | }; | |
| 1787 | 1835 | |
| 1788 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); | |
| 1836 | LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, ""); | |
| 1837 | } | |
| 1789 | 1838 | } |
| 1790 | 1839 | |
| 1791 | 1840 | LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1, |
| ... | ... | @@ -2592,6 +2641,30 @@ static bool directives_contains_link_libc(ZigList<AstNode*> *directives) { |
| 2592 | 2641 | return false; |
| 2593 | 2642 | } |
| 2594 | 2643 | |
| 2644 | static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) { | |
| 2645 | char *dot1 = strstr(buf_ptr(buf), "."); | |
| 2646 | if (!dot1) | |
| 2647 | return ErrorInvalidFormat; | |
| 2648 | char *dot2 = strstr(dot1 + 1, "."); | |
| 2649 | if (!dot2) | |
| 2650 | return ErrorInvalidFormat; | |
| 2651 | ||
| 2652 | *major = (int)strtol(buf_ptr(buf), nullptr, 10); | |
| 2653 | *minor = (int)strtol(dot1 + 1, nullptr, 10); | |
| 2654 | *patch = (int)strtol(dot2 + 1, nullptr, 10); | |
| 2655 | ||
| 2656 | return ErrorNone; | |
| 2657 | } | |
| 2658 | ||
| 2659 | static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) { | |
| 2660 | int err; | |
| 2661 | if ((err = parse_version_string(version_buf, &g->version_major, &g->version_minor, &g->version_patch))) { | |
| 2662 | add_node_error(g, node, | |
| 2663 | buf_sprintf("invalid version string")); | |
| 2664 | } | |
| 2665 | } | |
| 2666 | ||
| 2667 | ||
| 2595 | 2668 | static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2596 | 2669 | Buf *src_dirname, Buf *src_basename, Buf *source_code) |
| 2597 | 2670 | { |
| ... | ... | @@ -2657,7 +2730,50 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 2657 | 2730 | for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) { |
| 2658 | 2731 | AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i); |
| 2659 | 2732 | |
| 2660 | if (top_level_decl->type == NodeTypeUse) { | |
| 2733 | if (top_level_decl->type == NodeTypeRootExportDecl) { | |
| 2734 | if (g->root_import) { | |
| 2735 | add_node_error(g, top_level_decl, | |
| 2736 | buf_sprintf("root export declaration only valid in root source file")); | |
| 2737 | } else { | |
| 2738 | for (int i = 0; i < top_level_decl->data.root_export_decl.directives->length; i += 1) { | |
| 2739 | AstNode *directive_node = top_level_decl->data.root_export_decl.directives->at(i); | |
| 2740 | Buf *name = &directive_node->data.directive.name; | |
| 2741 | Buf *param = &directive_node->data.directive.param; | |
| 2742 | if (buf_eql_str(name, "version")) { | |
| 2743 | set_root_export_version(g, param, directive_node); | |
| 2744 | } else { | |
| 2745 | add_node_error(g, directive_node, | |
| 2746 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | |
| 2747 | } | |
| 2748 | } | |
| 2749 | ||
| 2750 | if (g->root_export_decl) { | |
| 2751 | add_node_error(g, top_level_decl, | |
| 2752 | buf_sprintf("only one root export declaration allowed")); | |
| 2753 | } else { | |
| 2754 | g->root_export_decl = top_level_decl; | |
| 2755 | ||
| 2756 | if (!g->root_out_name) | |
| 2757 | g->root_out_name = &top_level_decl->data.root_export_decl.name; | |
| 2758 | ||
| 2759 | Buf *out_type = &top_level_decl->data.root_export_decl.type; | |
| 2760 | OutType export_out_type; | |
| 2761 | if (buf_eql_str(out_type, "executable")) { | |
| 2762 | export_out_type = OutTypeExe; | |
| 2763 | } else if (buf_eql_str(out_type, "library")) { | |
| 2764 | export_out_type = OutTypeLib; | |
| 2765 | } else if (buf_eql_str(out_type, "object")) { | |
| 2766 | export_out_type = OutTypeObj; | |
| 2767 | } else { | |
| 2768 | add_node_error(g, top_level_decl, | |
| 2769 | buf_sprintf("invalid export type: '%s'", buf_ptr(out_type))); | |
| 2770 | } | |
| 2771 | if (g->out_type == OutTypeUnknown) { | |
| 2772 | g->out_type = export_out_type; | |
| 2773 | } | |
| 2774 | } | |
| 2775 | } | |
| 2776 | } else if (top_level_decl->type == NodeTypeUse) { | |
| 2661 | 2777 | Buf *import_target_path = &top_level_decl->data.use.path; |
| 2662 | 2778 | Buf full_path = BUF_INIT; |
| 2663 | 2779 | Buf *import_code = buf_alloc(); |
| ... | ... | @@ -2756,8 +2872,16 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou |
| 2756 | 2872 | |
| 2757 | 2873 | g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code); |
| 2758 | 2874 | |
| 2875 | if (!g->root_out_name) { | |
| 2876 | add_node_error(g, g->root_import->root, | |
| 2877 | buf_sprintf("missing export declaration and output name not provided")); | |
| 2878 | } else if (g->out_type == OutTypeUnknown) { | |
| 2879 | add_node_error(g, g->root_import->root, | |
| 2880 | buf_sprintf("missing export declaration and export type not provided")); | |
| 2881 | } | |
| 2882 | ||
| 2759 | 2883 | if (!g->link_libc) { |
| 2760 | if (g->have_exported_main && g->out_type != OutTypeLib) { | |
| 2884 | if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) { | |
| 2761 | 2885 | g->bootstrap_import = add_special_code(g, "bootstrap.zig"); |
| 2762 | 2886 | } |
| 2763 | 2887 |
std/bootstrap.zig+15-16| ... | ... | @@ -3,18 +3,28 @@ import "syscall.zig"; |
| 3 | 3 | // The compiler treats this file special by implicitly importing the function `main` |
| 4 | 4 | // from the root source file. |
| 5 | 5 | |
| 6 | var argc: usize; | |
| 7 | var argv: &&u8; | |
| 6 | 8 | var env: &&u8; |
| 7 | 9 | |
| 8 | 10 | #attribute("naked") |
| 9 | 11 | export fn _start() unreachable => { |
| 10 | const argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> isize)); | |
| 11 | const argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8)); | |
| 12 | argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize)); | |
| 13 | argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8)); | |
| 12 | 14 | env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]": [env] "=r" (-> &&u8)); |
| 15 | call_main() | |
| 16 | } | |
| 13 | 17 | |
| 14 | exit(main(argc, argv, env)); | |
| 18 | fn strlen(ptr: &u8) usize => { | |
| 19 | var count: usize = 0; | |
| 20 | while (ptr[count] != 0) { | |
| 21 | count += 1; | |
| 22 | } | |
| 23 | return count; | |
| 24 | } | |
| 15 | 25 | |
| 16 | /* | |
| 17 | var args = @alloca_array([]u8, argc); | |
| 26 | fn call_main() unreachable => { | |
| 27 | var args: [argc][]u8; | |
| 18 | 28 | var i : @typeof(argc) = 0; |
| 19 | 29 | // TODO for in loop over the array |
| 20 | 30 | while (i < argc) { |
| ... | ... | @@ -23,15 +33,4 @@ export fn _start() unreachable => { |
| 23 | 33 | i += 1; |
| 24 | 34 | } |
| 25 | 35 | exit(main(args)) |
| 26 | */ | |
| 27 | } | |
| 28 | ||
| 29 | /* | |
| 30 | fn strlen(ptr: &u8) isize => { | |
| 31 | var count: isize = 0; | |
| 32 | while (ptr[count]) { | |
| 33 | count += 1; | |
| 34 | } | |
| 35 | return count; | |
| 36 | 36 | } |
| 37 | */ |
test/run_tests.cpp+43-39| ... | ... | @@ -101,7 +101,7 @@ extern { |
| 101 | 101 | fn puts(s: &const u8) i32; |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => { | |
| 104 | export fn main(argc: i32, argv: &&u8) i32 => { | |
| 105 | 105 | puts(c"Hello, world!"); |
| 106 | 106 | return 0; |
| 107 | 107 | } |
| ... | ... | @@ -114,7 +114,7 @@ import "syscall.zig"; |
| 114 | 114 | fn empty_function_1() => {} |
| 115 | 115 | fn empty_function_2() => { return; } |
| 116 | 116 | |
| 117 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 117 | pub fn main(args: [][]u8) i32 => { | |
| 118 | 118 | empty_function_1(); |
| 119 | 119 | empty_function_2(); |
| 120 | 120 | this_is_a_function(); |
| ... | ... | @@ -136,7 +136,7 @@ fn another_function() => {} |
| 136 | 136 | |
| 137 | 137 | /// this is a documentation comment |
| 138 | 138 | /// doc comment line 2 |
| 139 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 139 | pub fn main(args: [][]u8) i32 => { | |
| 140 | 140 | print_str(/* mid-line comment /* nested */ */ "OK\n"); |
| 141 | 141 | return 0; |
| 142 | 142 | } |
| ... | ... | @@ -147,7 +147,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 147 | 147 | import "std.zig"; |
| 148 | 148 | import "foo.zig"; |
| 149 | 149 | |
| 150 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 150 | pub fn main(args: [][]u8) i32 => { | |
| 151 | 151 | private_function(); |
| 152 | 152 | print_str("OK 2\n"); |
| 153 | 153 | return 0; |
| ... | ... | @@ -178,7 +178,7 @@ pub fn print_text() => { |
| 178 | 178 | import "foo.zig"; |
| 179 | 179 | import "bar.zig"; |
| 180 | 180 | |
| 181 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 181 | pub fn main(args: [][]u8) i32 => { | |
| 182 | 182 | foo_function(); |
| 183 | 183 | bar_function(); |
| 184 | 184 | return 0; |
| ... | ... | @@ -214,7 +214,7 @@ pub fn foo_function() bool => { |
| 214 | 214 | add_simple_case("if statements", R"SOURCE( |
| 215 | 215 | import "std.zig"; |
| 216 | 216 | |
| 217 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 217 | pub fn main(args: [][]u8) i32 => { | |
| 218 | 218 | if (1 != 0) { |
| 219 | 219 | print_str("1 is true\n"); |
| 220 | 220 | } else { |
| ... | ... | @@ -239,7 +239,7 @@ fn add(a: i32, b: i32) i32 => { |
| 239 | 239 | a + b |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 242 | pub fn main(args: [][]u8) i32 => { | |
| 243 | 243 | if (add(22, 11) == 33) { |
| 244 | 244 | print_str("pass\n"); |
| 245 | 245 | } |
| ... | ... | @@ -261,7 +261,7 @@ done: |
| 261 | 261 | return; |
| 262 | 262 | } |
| 263 | 263 | |
| 264 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 264 | pub fn main(args: [][]u8) i32 => { | |
| 265 | 265 | loop(3); |
| 266 | 266 | return 0; |
| 267 | 267 | } |
| ... | ... | @@ -270,7 +270,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 270 | 270 | add_simple_case("local variables", R"SOURCE( |
| 271 | 271 | import "std.zig"; |
| 272 | 272 | |
| 273 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 273 | pub fn main(args: [][]u8) i32 => { | |
| 274 | 274 | const a : i32 = 1; |
| 275 | 275 | const b = i32(2); |
| 276 | 276 | if (a + b == 3) { |
| ... | ... | @@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 283 | 283 | add_simple_case("bool literals", R"SOURCE( |
| 284 | 284 | import "std.zig"; |
| 285 | 285 | |
| 286 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 286 | pub fn main(args: [][]u8) i32 => { | |
| 287 | 287 | if (true) { print_str("OK 1\n"); } |
| 288 | 288 | if (false) { print_str("BAD 1\n"); } |
| 289 | 289 | if (!true) { print_str("BAD 2\n"); } |
| ... | ... | @@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 295 | 295 | add_simple_case("separate block scopes", R"SOURCE( |
| 296 | 296 | import "std.zig"; |
| 297 | 297 | |
| 298 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 298 | pub fn main(args: [][]u8) i32 => { | |
| 299 | 299 | if (true) { |
| 300 | 300 | const no_conflict : i32 = 5; |
| 301 | 301 | if (no_conflict == 5) { print_str("OK 1\n"); } |
| ... | ... | @@ -313,7 +313,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 313 | 313 | add_simple_case("void parameters", R"SOURCE( |
| 314 | 314 | import "std.zig"; |
| 315 | 315 | |
| 316 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 316 | pub fn main(args: [][]u8) i32 => { | |
| 317 | 317 | void_fun(1, void{}, 2); |
| 318 | 318 | return 0; |
| 319 | 319 | } |
| ... | ... | @@ -333,7 +333,7 @@ struct Foo { |
| 333 | 333 | b : i32, |
| 334 | 334 | c : void, |
| 335 | 335 | } |
| 336 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 336 | pub fn main(args: [][]u8) i32 => { | |
| 337 | 337 | const foo = Foo { |
| 338 | 338 | .a = void{}, |
| 339 | 339 | .b = 1, |
| ... | ... | @@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 354 | 354 | add_simple_case("void arrays", R"SOURCE( |
| 355 | 355 | import "std.zig"; |
| 356 | 356 | |
| 357 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 357 | pub fn main(args: [][]u8) i32 => { | |
| 358 | 358 | var array: [4]void; |
| 359 | 359 | array[0] = void{}; |
| 360 | 360 | array[1] = array[2]; |
| ... | ... | @@ -373,7 +373,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 373 | 373 | add_simple_case("mutable local variables", R"SOURCE( |
| 374 | 374 | import "std.zig"; |
| 375 | 375 | |
| 376 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 376 | pub fn main(args: [][]u8) i32 => { | |
| 377 | 377 | var zero : i32 = 0; |
| 378 | 378 | if (zero == 0) { print_str("zero\n"); } |
| 379 | 379 | |
| ... | ... | @@ -393,7 +393,7 @@ done: |
| 393 | 393 | add_simple_case("arrays", R"SOURCE( |
| 394 | 394 | import "std.zig"; |
| 395 | 395 | |
| 396 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 396 | pub fn main(args: [][]u8) i32 => { | |
| 397 | 397 | var array : [5]u32; |
| 398 | 398 | |
| 399 | 399 | var i : u32 = 0; |
| ... | ... | @@ -429,7 +429,7 @@ fn get_array_len(a: []u32) usize => { |
| 429 | 429 | add_simple_case("hello world without libc", R"SOURCE( |
| 430 | 430 | import "std.zig"; |
| 431 | 431 | |
| 432 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 432 | pub fn main(args: [][]u8) i32 => { | |
| 433 | 433 | print_str("Hello, world!\n"); |
| 434 | 434 | return 0; |
| 435 | 435 | } |
| ... | ... | @@ -439,7 +439,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 439 | 439 | add_simple_case("a + b + c", R"SOURCE( |
| 440 | 440 | import "std.zig"; |
| 441 | 441 | |
| 442 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 442 | pub fn main(args: [][]u8) i32 => { | |
| 443 | 443 | if (false || false || false) { print_str("BAD 1\n"); } |
| 444 | 444 | if (true && true && false) { print_str("BAD 2\n"); } |
| 445 | 445 | if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); } |
| ... | ... | @@ -461,7 +461,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 461 | 461 | add_simple_case("short circuit", R"SOURCE( |
| 462 | 462 | import "std.zig"; |
| 463 | 463 | |
| 464 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 464 | pub fn main(args: [][]u8) i32 => { | |
| 465 | 465 | if (true || { print_str("BAD 1\n"); false }) { |
| 466 | 466 | print_str("OK 1\n"); |
| 467 | 467 | } |
| ... | ... | @@ -484,7 +484,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 484 | 484 | add_simple_case("modify operators", R"SOURCE( |
| 485 | 485 | import "std.zig"; |
| 486 | 486 | |
| 487 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 487 | pub fn main(args: [][]u8) i32 => { | |
| 488 | 488 | var i : i32 = 0; |
| 489 | 489 | i += 5; if (i != 5) { print_str("BAD +=\n"); } |
| 490 | 490 | i -= 2; if (i != 3) { print_str("BAD -=\n"); } |
| ... | ... | @@ -510,7 +510,7 @@ extern { |
| 510 | 510 | fn printf(__format: &const u8, ...) i32; |
| 511 | 511 | } |
| 512 | 512 | |
| 513 | export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 513 | export fn main(argc: i32, argv: &&u8) i32 => { | |
| 514 | 514 | printf(c"\n"); |
| 515 | 515 | |
| 516 | 516 | printf(c"0: %llu\n", |
| ... | ... | @@ -636,7 +636,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 636 | 636 | add_simple_case("structs", R"SOURCE( |
| 637 | 637 | import "std.zig"; |
| 638 | 638 | |
| 639 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 639 | pub fn main(args: [][]u8) i32 => { | |
| 640 | 640 | var foo : Foo; |
| 641 | 641 | @memset(&foo, 0, @sizeof(Foo)); |
| 642 | 642 | foo.a += 1; |
| ... | ... | @@ -711,7 +711,7 @@ import "std.zig"; |
| 711 | 711 | const g1 : i32 = 1233 + 1; |
| 712 | 712 | var g2 : i32 = 0; |
| 713 | 713 | |
| 714 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 714 | pub fn main(args: [][]u8) i32 => { | |
| 715 | 715 | if (g2 != 0) { print_str("BAD\n"); } |
| 716 | 716 | g2 = g1; |
| 717 | 717 | if (g2 != 1234) { print_str("BAD\n"); } |
| ... | ... | @@ -722,7 +722,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 722 | 722 | |
| 723 | 723 | add_simple_case("while loop", R"SOURCE( |
| 724 | 724 | import "std.zig"; |
| 725 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 725 | pub fn main(args: [][]u8) i32 => { | |
| 726 | 726 | var i : i32 = 0; |
| 727 | 727 | while (i < 4) { |
| 728 | 728 | print_str("loop\n"); |
| ... | ... | @@ -739,7 +739,7 @@ fn f() i32 => { |
| 739 | 739 | |
| 740 | 740 | add_simple_case("continue and break", R"SOURCE( |
| 741 | 741 | import "std.zig"; |
| 742 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 742 | pub fn main(args: [][]u8) i32 => { | |
| 743 | 743 | var i : i32 = 0; |
| 744 | 744 | while (true) { |
| 745 | 745 | print_str("loop\n"); |
| ... | ... | @@ -755,7 +755,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 755 | 755 | |
| 756 | 756 | add_simple_case("maybe type", R"SOURCE( |
| 757 | 757 | import "std.zig"; |
| 758 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 758 | pub fn main(args: [][]u8) i32 => { | |
| 759 | 759 | const x : ?bool = true; |
| 760 | 760 | |
| 761 | 761 | if (const y ?= x) { |
| ... | ... | @@ -790,7 +790,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 790 | 790 | |
| 791 | 791 | add_simple_case("implicit cast after unreachable", R"SOURCE( |
| 792 | 792 | import "std.zig"; |
| 793 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 793 | pub fn main(args: [][]u8) i32 => { | |
| 794 | 794 | const x = outer(); |
| 795 | 795 | if (x == 1234) { |
| 796 | 796 | print_str("OK\n"); |
| ... | ... | @@ -807,7 +807,7 @@ fn outer() isize => { |
| 807 | 807 | import "std.zig"; |
| 808 | 808 | const x: u16 = 13; |
| 809 | 809 | const z: @typeof(x) = 19; |
| 810 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 810 | pub fn main(args: [][]u8) i32 => { | |
| 811 | 811 | const y: @typeof(x) = 120; |
| 812 | 812 | print_u64(@sizeof(@typeof(y))); |
| 813 | 813 | print_str("\n"); |
| ... | ... | @@ -823,7 +823,7 @@ struct Rand { |
| 823 | 823 | r.seed |
| 824 | 824 | } |
| 825 | 825 | } |
| 826 | pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { | |
| 826 | pub fn main(args: [][]u8) i32 => { | |
| 827 | 827 | const r = Rand {.seed = 1234}; |
| 828 | 828 | if (r.get_seed() != 1234) { |
| 829 | 829 | print_str("BAD seed\n"); |
| ... | ... | @@ -836,7 +836,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => { |
| 836 | 836 | add_simple_case("pointer dereferencing", R"SOURCE( |
| 837 | 837 | import "std.zig"; |
| 838 | 838 | |
| 839 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 839 | pub fn main(args: [][]u8) i32 => { | |
| 840 | 840 | var x = i32(3); |
| 841 | 841 | const y = &x; |
| 842 | 842 | |
| ... | ... | @@ -858,7 +858,7 @@ import "std.zig"; |
| 858 | 858 | |
| 859 | 859 | const ARRAY_SIZE : u8 = 20; |
| 860 | 860 | |
| 861 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 861 | pub fn main(args: [][]u8) i32 => { | |
| 862 | 862 | var array : [ARRAY_SIZE]u8; |
| 863 | 863 | print_u64(@sizeof(@typeof(array))); |
| 864 | 864 | print_str("\n"); |
| ... | ... | @@ -868,7 +868,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 868 | 868 | |
| 869 | 869 | add_simple_case("#min_value() and #max_value()", R"SOURCE( |
| 870 | 870 | import "std.zig"; |
| 871 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 871 | pub fn main(args: [][]u8) i32 => { | |
| 872 | 872 | print_str("max u8: "); |
| 873 | 873 | print_u64(@max_value(u8)); |
| 874 | 874 | print_str("\n"); |
| ... | ... | @@ -956,7 +956,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 956 | 956 | |
| 957 | 957 | add_simple_case("slicing", R"SOURCE( |
| 958 | 958 | import "std.zig"; |
| 959 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 959 | pub fn main(args: [][]u8) i32 => { | |
| 960 | 960 | var array : [20]i32; |
| 961 | 961 | |
| 962 | 962 | array[5] = 1234; |
| ... | ... | @@ -984,7 +984,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 984 | 984 | |
| 985 | 985 | add_simple_case("else if expression", R"SOURCE( |
| 986 | 986 | import "std.zig"; |
| 987 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 987 | pub fn main(args: [][]u8) i32 => { | |
| 988 | 988 | if (f(1) == 1) { |
| 989 | 989 | print_str("OK\n"); |
| 990 | 990 | } |
| ... | ... | @@ -1003,7 +1003,7 @@ fn f(c: u8) u8 => { |
| 1003 | 1003 | |
| 1004 | 1004 | add_simple_case("overflow intrinsics", R"SOURCE( |
| 1005 | 1005 | import "std.zig"; |
| 1006 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1006 | pub fn main(args: [][]u8) i32 => { | |
| 1007 | 1007 | var result: u8; |
| 1008 | 1008 | if (!@add_with_overflow(u8, 250, 100, &result)) { |
| 1009 | 1009 | print_str("BAD\n"); |
| ... | ... | @@ -1021,7 +1021,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 1021 | 1021 | |
| 1022 | 1022 | add_simple_case("memcpy and memset intrinsics", R"SOURCE( |
| 1023 | 1023 | import "std.zig"; |
| 1024 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1024 | pub fn main(args: [][]u8) i32 => { | |
| 1025 | 1025 | var foo : [20]u8; |
| 1026 | 1026 | var bar : [20]u8; |
| 1027 | 1027 | |
| ... | ... | @@ -1042,7 +1042,7 @@ import "std.zig"; |
| 1042 | 1042 | const z : @typeof(stdin_fileno) = 0; |
| 1043 | 1043 | const x : @typeof(y) = 1234; |
| 1044 | 1044 | const y : u16 = 5678; |
| 1045 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1045 | pub fn main(args: [][]u8) i32 => { | |
| 1046 | 1046 | print_ok(x) |
| 1047 | 1047 | } |
| 1048 | 1048 | fn print_ok(val: @typeof(x)) @typeof(foo) => { |
| ... | ... | @@ -1073,7 +1073,7 @@ enum Bar { |
| 1073 | 1073 | D, |
| 1074 | 1074 | } |
| 1075 | 1075 | |
| 1076 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1076 | pub fn main(args: [][]u8) i32 => { | |
| 1077 | 1077 | const foo1 = Foo.One(13); |
| 1078 | 1078 | const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, }); |
| 1079 | 1079 | const bar = Bar.B; |
| ... | ... | @@ -1106,7 +1106,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { |
| 1106 | 1106 | add_simple_case("array literal", R"SOURCE( |
| 1107 | 1107 | import "std.zig"; |
| 1108 | 1108 | |
| 1109 | pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => { | |
| 1109 | pub fn main(args: [][]u8) i32 => { | |
| 1110 | 1110 | const HEX_MULT = []u16{4096, 256, 16, 1}; |
| 1111 | 1111 | |
| 1112 | 1112 | if (HEX_MULT.len != 4) { |
| ... | ... | @@ -1442,6 +1442,10 @@ fn f(noalias x: i32) => {} |
| 1442 | 1442 | add_compile_fail_case("struct init syntax for array", R"SOURCE( |
| 1443 | 1443 | const foo = []u16{.x = 1024,}; |
| 1444 | 1444 | )SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax"); |
| 1445 | ||
| 1446 | add_compile_fail_case("type variables must be constant", R"SOURCE( | |
| 1447 | var foo = u8; | |
| 1448 | )SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant"); | |
| 1445 | 1449 | } |
| 1446 | 1450 | |
| 1447 | 1451 | static void print_compiler_invocation(TestCase *test_case) { |