authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-16 00:07:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-16 00:07:34-07:00
log5f7685336f2b0bd5e14765d885b0cf87ebe1f578
tree84218637c6dcf91efde85759c5f4f0efdf6af2ed
parentca8d8f114f0db4f3ed51c410c0e9f93aaf03e14d

better main symbol prototype

closes #64

8 files changed, 242 insertions(+), 166 deletions(-)

example/cat/main.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1export executable "cat";1export executable "cat";
22
3pub main(argv: [][]u8) -> i32 {3pub fn main(argv: [][]u8) i32 => {
44
55
6 return 0;6 return 0;
example/guess_number/main.zig+1-1
...@@ -3,7 +3,7 @@ export executable "guess_number";...@@ -3,7 +3,7 @@ export executable "guess_number";
3import "std.zig";3import "std.zig";
4import "rand.zig";4import "rand.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {6pub fn main(args: [][]u8) i32 => {
7 print_str("Welcome to the Guess Number Game in Zig.\n");7 print_str("Welcome to the Guess Number Game in Zig.\n");
88
9 var seed : u32;9 var seed : u32;
example/hello_world/hello.zig+1-1
...@@ -2,7 +2,7 @@ export executable "hello";...@@ -2,7 +2,7 @@ export executable "hello";
22
3import "std.zig";3import "std.zig";
44
5pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {5pub fn main(args: [][]u8) i32 => {
6 print_str("Hello, world!\n");6 print_str("Hello, world!\n");
7 return 0;7 return 0;
8}8}
example/multiple_files/main.zig+1-1
...@@ -3,7 +3,7 @@ export executable "test-multiple-files";...@@ -3,7 +3,7 @@ export executable "test-multiple-files";
3import "std.zig";3import "std.zig";
4import "foo.zig";4import "foo.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {6pub fn main(args: [][]u8) i32 => {
7 private_function();7 private_function();
8 print_str("OK 2\n");8 print_str("OK 2\n");
9 return 0;9 return 0;
src/analyze.cpp+35-86
...@@ -64,7 +64,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -64,7 +64,7 @@ static AstNode *first_executing_node(AstNode *node) {
64 case NodeTypeArrayType:64 case NodeTypeArrayType:
65 return node;65 return node;
66 }66 }
67 zig_panic("unreachable");67 zig_unreachable();
68}68}
6969
70void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {70void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
...@@ -81,29 +81,6 @@ 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 g->errors.append(err);81 g->errors.append(err);
82}82}
8383
84static 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
99static 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
107TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {84TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
108 TypeTableEntry *entry = allocate<TypeTableEntry>(1);85 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
109 entry->arrays_by_size.init(2);86 entry->arrays_by_size.init(2);
...@@ -258,9 +235,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui...@@ -258,9 +235,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui
258 }235 }
259}236}
260237
261static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import,238static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
262 TypeTableEntry *child_type, bool is_const)
263{
264 assert(child_type->id != TypeTableEntryIdInvalid);239 assert(child_type->id != TypeTableEntryIdInvalid);
265 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];240 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
266 if (*parent_pointer) {241 if (*parent_pointer) {
...@@ -268,8 +243,9 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry...@@ -268,8 +243,9 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
268 } else {243 } else {
269 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);244 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
270245
246 const char *const_str = is_const ? "const " : "";
271 buf_resize(&entry->name, 0);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 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));249 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
274250
275 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);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,47 +794,7 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
818 preview_fn_proto(g, import, node);794 preview_fn_proto(g, import, node);
819 break;795 break;
820 case NodeTypeRootExportDecl:796 case NodeTypeRootExportDecl:
821 if (import == g->root_import) {797 // handled earlier
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 }
862 break;798 break;
863 case NodeTypeStructDecl:799 case NodeTypeStructDecl:
864 {800 {
...@@ -1126,7 +1062,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1126,7 +1062,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1126 if (expected_type->id == TypeTableEntryIdInt &&1062 if (expected_type->id == TypeTableEntryIdInt &&
1127 actual_type->id == TypeTableEntryIdInt &&1063 actual_type->id == TypeTableEntryIdInt &&
1128 expected_type->data.integral.is_signed == actual_type->data.integral.is_signed &&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 Expr *expr = get_resolved_expr(node);1067 Expr *expr = get_resolved_expr(node);
1132 expr->implicit_cast.after_type = expected_type;1068 expr->implicit_cast.after_type = expected_type;
...@@ -1149,7 +1085,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont...@@ -1149,7 +1085,7 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1149 return expected_type;1085 return expected_type;
1150 }1086 }
11511087
1152 // implicit non-const to const and ignore noalias1088 // implicit non-const to const for pointers
1153 if (expected_type->id == TypeTableEntryIdPointer &&1089 if (expected_type->id == TypeTableEntryIdPointer &&
1154 actual_type->id == TypeTableEntryIdPointer &&1090 actual_type->id == TypeTableEntryIdPointer &&
1155 (!actual_type->data.pointer.is_const || expected_type->data.pointer.is_const))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,6 +1099,23 @@ static TypeTableEntry *resolve_type_compatibility(CodeGen *g, BlockContext *cont
1163 return expected_type;1099 return expected_type;
1164 }1100 }
11651101
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 add_node_error(g, first_executing_node(node),1119 add_node_error(g, first_executing_node(node),
1167 buf_sprintf("expected type '%s', got '%s'",1120 buf_sprintf("expected type '%s', got '%s'",
1168 buf_ptr(&expected_type->name),1121 buf_ptr(&expected_type->name),
...@@ -1511,15 +1464,15 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,...@@ -1511,15 +1464,15 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
1511 if (array_type->id == TypeTableEntryIdInvalid) {1464 if (array_type->id == TypeTableEntryIdInvalid) {
1512 return_type = g->builtin_types.entry_invalid;1465 return_type = g->builtin_types.entry_invalid;
1513 } else if (array_type->id == TypeTableEntryIdArray) {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 node->data.slice_expr.is_const);1468 node->data.slice_expr.is_const);
1516 } else if (array_type->id == TypeTableEntryIdPointer) {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 node->data.slice_expr.is_const);1471 node->data.slice_expr.is_const);
1519 } else if (array_type->id == TypeTableEntryIdStruct &&1472 } else if (array_type->id == TypeTableEntryIdStruct &&
1520 array_type->data.structure.is_unknown_size_array)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 array_type->data.structure.fields[0].type_entry->data.pointer.child_type,1476 array_type->data.structure.fields[0].type_entry->data.pointer.child_type,
1524 node->data.slice_expr.is_const);1477 node->data.slice_expr.is_const);
1525 } else {1478 } else {
...@@ -2045,6 +1998,11 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -2045,6 +1998,11 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
2045 add_node_error(g, source_node,1998 add_node_error(g, source_node,
2046 buf_sprintf("unable to infer variable type"));1999 buf_sprintf("unable to infer variable type"));
2047 implicit_type = g->builtin_types.entry_invalid;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 }
20502008
...@@ -2175,12 +2133,12 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,...@@ -2175,12 +2133,12 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import,
2175 return resolve_expr_const_val_as_type(g, node,2133 return resolve_expr_const_val_as_type(g, node,
2176 get_array_type(g, child_type, const_val->data.x_uint));2134 get_array_type(g, child_type, const_val->data.x_uint));
2177 } else {2135 } else {
2178 add_node_error(g, size_node, buf_create_from_str("unable to resolve constant expression"));2136 return resolve_expr_const_val_as_type(g, node,
2179 return g->builtin_types.entry_invalid;2137 get_unknown_size_array_type(g, child_type, node->data.array_type.is_const));
2180 }2138 }
2181 } else {2139 } else {
2182 return resolve_expr_const_val_as_type(g, node,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}
21862144
...@@ -2587,7 +2545,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -2587,7 +2545,6 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
2587 return resolve_expr_const_val_as_type(g, node, type_entry);2545 return resolve_expr_const_val_as_type(g, node, type_entry);
2588 }2546 }
2589 }2547 }
2590
2591 }2548 }
2592 zig_unreachable();2549 zig_unreachable();
2593}2550}
...@@ -3677,14 +3634,6 @@ void semantic_analyze(CodeGen *g) {...@@ -3677,14 +3634,6 @@ void semantic_analyze(CodeGen *g) {
3677 analyze_top_level_decls_root(g, import, import->root);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}
36893638
3690Expr *get_resolved_expr(AstNode *node) {3639Expr *get_resolved_expr(AstNode *node) {
src/codegen.cpp+145-21
...@@ -636,7 +636,19 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {...@@ -636,7 +636,19 @@ static LLVMValueRef gen_slice_expr(CodeGen *g, AstNode *node) {
636636
637 return tmp_struct_ptr;637 return tmp_struct_ptr;
638 } else if (array_type->id == TypeTableEntryIdPointer) {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 } else if (array_type->id == TypeTableEntryIdStruct) {652 } else if (array_type->id == TypeTableEntryIdStruct) {
641 assert(array_type->data.structure.is_unknown_size_array);653 assert(array_type->data.structure.is_unknown_size_array);
642 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);654 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind);
...@@ -1767,25 +1779,62 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa...@@ -1767,25 +1779,62 @@ static LLVMValueRef gen_var_decl_raw(CodeGen *g, AstNode *source_node, AstNodeVa
1767 }1779 }
1768 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,1780 gen_assign_raw(g, var_decl->expr, BinOpTypeAssign, variable->value_ref,
1769 value, variable->type, expr_type);1781 value, variable->type, expr_type);
1770 } else if (g->build_type != CodeGenBuildTypeRelease) {1782 } else {
1771 // memset uninitialized memory to 0xa1783 bool ignore_uninit = false;
1772 add_debug_source_node(g, source_node);1784 TypeTableEntry *var_type = get_type_for_type_node(var_decl->type);
1773 LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);1785 if (var_type->id == TypeTableEntryIdStruct &&
1774 LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);1786 var_type->data.structure.is_unknown_size_array)
1775 LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, variable->value_ref, ptr_u8, "");1787 {
1776 LLVMValueRef byte_count = LLVMConstInt(LLVMIntType(g->pointer_size_bytes * 8),1788 assert(var_decl->type->type == NodeTypeArrayType);
1777 variable->type->size_in_bits / 8, false);1789 AstNode *size_node = var_decl->type->data.array_type.size;
1778 LLVMValueRef align_in_bytes = LLVMConstInt(LLVMInt32Type(),1790 if (size_node) {
1779 variable->type->align_in_bits / 8, false);1791 ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val;
1780 LLVMValueRef params[] = {1792 if (!const_val->ok) {
1781 dest_ptr,1793 TypeTableEntry *ptr_type = var_type->data.structure.fields[0].type_entry;
1782 fill_char,1794 assert(ptr_type->id == TypeTableEntryIdPointer);
1783 byte_count,1795 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
1784 align_in_bytes,1796
1785 LLVMConstNull(LLVMInt1Type()), // is volatile1797 LLVMValueRef size_val = gen_expr(g, size_node);
1786 };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 };
17871835
1788 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");1836 LLVMBuildCall(g->builder, g->memset_fn_val, params, 5, "");
1837 }
1789 }1838 }
17901839
1791 LLVMZigDILocation *debug_loc = LLVMZigGetDebugLoc(source_node->line + 1, source_node->column + 1,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,6 +2641,30 @@ static bool directives_contains_link_libc(ZigList<AstNode*> *directives) {
2592 return false;2641 return false;
2593}2642}
25942643
2644static 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
2659static 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
2595static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,2668static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2596 Buf *src_dirname, Buf *src_basename, Buf *source_code)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,7 +2730,50 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2657 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {2730 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
2658 AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);2731 AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
26592732
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 Buf *import_target_path = &top_level_decl->data.use.path;2777 Buf *import_target_path = &top_level_decl->data.use.path;
2662 Buf full_path = BUF_INIT;2778 Buf full_path = BUF_INIT;
2663 Buf *import_code = buf_alloc();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,8 +2872,16 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
27562872
2757 g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);2873 g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);
27582874
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 if (!g->link_libc) {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 g->bootstrap_import = add_special_code(g, "bootstrap.zig");2885 g->bootstrap_import = add_special_code(g, "bootstrap.zig");
2762 }2886 }
27632887
std/bootstrap.zig+15-16
...@@ -3,18 +3,28 @@ import "syscall.zig";...@@ -3,18 +3,28 @@ import "syscall.zig";
3// The compiler treats this file special by implicitly importing the function `main`3// The compiler treats this file special by implicitly importing the function `main`
4// from the root source file.4// from the root source file.
55
6var argc: usize;
7var argv: &&u8;
6var env: &&u8;8var env: &&u8;
79
8#attribute("naked")10#attribute("naked")
9export fn _start() unreachable => {11export fn _start() unreachable => {
10 const argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> isize));12 argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> usize));
11 const argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));13 argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));
12 env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]": [env] "=r" (-> &&u8));14 env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]": [env] "=r" (-> &&u8));
15 call_main()
16}
1317
14 exit(main(argc, argv, env));18fn strlen(ptr: &u8) usize => {
19 var count: usize = 0;
20 while (ptr[count] != 0) {
21 count += 1;
22 }
23 return count;
24}
1525
16/*26fn call_main() unreachable => {
17 var args = @alloca_array([]u8, argc);27 var args: [argc][]u8;
18 var i : @typeof(argc) = 0;28 var i : @typeof(argc) = 0;
19 // TODO for in loop over the array29 // TODO for in loop over the array
20 while (i < argc) {30 while (i < argc) {
...@@ -23,15 +33,4 @@ export fn _start() unreachable => {...@@ -23,15 +33,4 @@ export fn _start() unreachable => {
23 i += 1;33 i += 1;
24 }34 }
25 exit(main(args))35 exit(main(args))
26 */
27}
28
29/*
30fn 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,7 +101,7 @@ extern {
101 fn puts(s: &const u8) i32;101 fn puts(s: &const u8) i32;
102}102}
103103
104export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {104export fn main(argc: i32, argv: &&u8) i32 => {
105 puts(c"Hello, world!");105 puts(c"Hello, world!");
106 return 0;106 return 0;
107}107}
...@@ -114,7 +114,7 @@ import "syscall.zig";...@@ -114,7 +114,7 @@ import "syscall.zig";
114fn empty_function_1() => {}114fn empty_function_1() => {}
115fn empty_function_2() => { return; }115fn empty_function_2() => { return; }
116116
117pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {117pub fn main(args: [][]u8) i32 => {
118 empty_function_1();118 empty_function_1();
119 empty_function_2();119 empty_function_2();
120 this_is_a_function();120 this_is_a_function();
...@@ -136,7 +136,7 @@ fn another_function() => {}...@@ -136,7 +136,7 @@ fn another_function() => {}
136136
137/// this is a documentation comment137/// this is a documentation comment
138/// doc comment line 2138/// doc comment line 2
139pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {139pub fn main(args: [][]u8) i32 => {
140 print_str(/* mid-line comment /* nested */ */ "OK\n");140 print_str(/* mid-line comment /* nested */ */ "OK\n");
141 return 0;141 return 0;
142}142}
...@@ -147,7 +147,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -147,7 +147,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
147import "std.zig";147import "std.zig";
148import "foo.zig";148import "foo.zig";
149149
150pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {150pub fn main(args: [][]u8) i32 => {
151 private_function();151 private_function();
152 print_str("OK 2\n");152 print_str("OK 2\n");
153 return 0;153 return 0;
...@@ -178,7 +178,7 @@ pub fn print_text() => {...@@ -178,7 +178,7 @@ pub fn print_text() => {
178import "foo.zig";178import "foo.zig";
179import "bar.zig";179import "bar.zig";
180180
181pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {181pub fn main(args: [][]u8) i32 => {
182 foo_function();182 foo_function();
183 bar_function();183 bar_function();
184 return 0;184 return 0;
...@@ -214,7 +214,7 @@ pub fn foo_function() bool => {...@@ -214,7 +214,7 @@ pub fn foo_function() bool => {
214 add_simple_case("if statements", R"SOURCE(214 add_simple_case("if statements", R"SOURCE(
215import "std.zig";215import "std.zig";
216216
217pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {217pub fn main(args: [][]u8) i32 => {
218 if (1 != 0) {218 if (1 != 0) {
219 print_str("1 is true\n");219 print_str("1 is true\n");
220 } else {220 } else {
...@@ -239,7 +239,7 @@ fn add(a: i32, b: i32) i32 => {...@@ -239,7 +239,7 @@ fn add(a: i32, b: i32) i32 => {
239 a + b239 a + b
240}240}
241241
242pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {242pub fn main(args: [][]u8) i32 => {
243 if (add(22, 11) == 33) {243 if (add(22, 11) == 33) {
244 print_str("pass\n");244 print_str("pass\n");
245 }245 }
...@@ -261,7 +261,7 @@ done:...@@ -261,7 +261,7 @@ done:
261 return;261 return;
262}262}
263263
264pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {264pub fn main(args: [][]u8) i32 => {
265 loop(3);265 loop(3);
266 return 0;266 return 0;
267}267}
...@@ -270,7 +270,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -270,7 +270,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
270 add_simple_case("local variables", R"SOURCE(270 add_simple_case("local variables", R"SOURCE(
271import "std.zig";271import "std.zig";
272272
273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {273pub fn main(args: [][]u8) i32 => {
274 const a : i32 = 1;274 const a : i32 = 1;
275 const b = i32(2);275 const b = i32(2);
276 if (a + b == 3) {276 if (a + b == 3) {
...@@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
283 add_simple_case("bool literals", R"SOURCE(283 add_simple_case("bool literals", R"SOURCE(
284import "std.zig";284import "std.zig";
285285
286pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {286pub fn main(args: [][]u8) i32 => {
287 if (true) { print_str("OK 1\n"); }287 if (true) { print_str("OK 1\n"); }
288 if (false) { print_str("BAD 1\n"); }288 if (false) { print_str("BAD 1\n"); }
289 if (!true) { print_str("BAD 2\n"); }289 if (!true) { print_str("BAD 2\n"); }
...@@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
295 add_simple_case("separate block scopes", R"SOURCE(295 add_simple_case("separate block scopes", R"SOURCE(
296import "std.zig";296import "std.zig";
297297
298pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {298pub fn main(args: [][]u8) i32 => {
299 if (true) {299 if (true) {
300 const no_conflict : i32 = 5;300 const no_conflict : i32 = 5;
301 if (no_conflict == 5) { print_str("OK 1\n"); }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,7 +313,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
313 add_simple_case("void parameters", R"SOURCE(313 add_simple_case("void parameters", R"SOURCE(
314import "std.zig";314import "std.zig";
315315
316pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {316pub fn main(args: [][]u8) i32 => {
317 void_fun(1, void{}, 2);317 void_fun(1, void{}, 2);
318 return 0;318 return 0;
319}319}
...@@ -333,7 +333,7 @@ struct Foo {...@@ -333,7 +333,7 @@ struct Foo {
333 b : i32,333 b : i32,
334 c : void,334 c : void,
335}335}
336pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {336pub fn main(args: [][]u8) i32 => {
337 const foo = Foo {337 const foo = Foo {
338 .a = void{},338 .a = void{},
339 .b = 1,339 .b = 1,
...@@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
354 add_simple_case("void arrays", R"SOURCE(354 add_simple_case("void arrays", R"SOURCE(
355import "std.zig";355import "std.zig";
356356
357pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {357pub fn main(args: [][]u8) i32 => {
358 var array: [4]void;358 var array: [4]void;
359 array[0] = void{};359 array[0] = void{};
360 array[1] = array[2];360 array[1] = array[2];
...@@ -373,7 +373,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -373,7 +373,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
373 add_simple_case("mutable local variables", R"SOURCE(373 add_simple_case("mutable local variables", R"SOURCE(
374import "std.zig";374import "std.zig";
375375
376pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {376pub fn main(args: [][]u8) i32 => {
377 var zero : i32 = 0;377 var zero : i32 = 0;
378 if (zero == 0) { print_str("zero\n"); }378 if (zero == 0) { print_str("zero\n"); }
379379
...@@ -393,7 +393,7 @@ done:...@@ -393,7 +393,7 @@ done:
393 add_simple_case("arrays", R"SOURCE(393 add_simple_case("arrays", R"SOURCE(
394import "std.zig";394import "std.zig";
395395
396pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {396pub fn main(args: [][]u8) i32 => {
397 var array : [5]u32;397 var array : [5]u32;
398398
399 var i : u32 = 0;399 var i : u32 = 0;
...@@ -429,7 +429,7 @@ fn get_array_len(a: []u32) usize => {...@@ -429,7 +429,7 @@ fn get_array_len(a: []u32) usize => {
429 add_simple_case("hello world without libc", R"SOURCE(429 add_simple_case("hello world without libc", R"SOURCE(
430import "std.zig";430import "std.zig";
431431
432pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {432pub fn main(args: [][]u8) i32 => {
433 print_str("Hello, world!\n");433 print_str("Hello, world!\n");
434 return 0;434 return 0;
435}435}
...@@ -439,7 +439,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -439,7 +439,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
439 add_simple_case("a + b + c", R"SOURCE(439 add_simple_case("a + b + c", R"SOURCE(
440import "std.zig";440import "std.zig";
441441
442pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {442pub fn main(args: [][]u8) i32 => {
443 if (false || false || false) { print_str("BAD 1\n"); }443 if (false || false || false) { print_str("BAD 1\n"); }
444 if (true && true && false) { print_str("BAD 2\n"); }444 if (true && true && false) { print_str("BAD 2\n"); }
445 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }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,7 +461,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
461 add_simple_case("short circuit", R"SOURCE(461 add_simple_case("short circuit", R"SOURCE(
462import "std.zig";462import "std.zig";
463463
464pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {464pub fn main(args: [][]u8) i32 => {
465 if (true || { print_str("BAD 1\n"); false }) {465 if (true || { print_str("BAD 1\n"); false }) {
466 print_str("OK 1\n");466 print_str("OK 1\n");
467 }467 }
...@@ -484,7 +484,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -484,7 +484,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
484 add_simple_case("modify operators", R"SOURCE(484 add_simple_case("modify operators", R"SOURCE(
485import "std.zig";485import "std.zig";
486486
487pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {487pub fn main(args: [][]u8) i32 => {
488 var i : i32 = 0;488 var i : i32 = 0;
489 i += 5; if (i != 5) { print_str("BAD +=\n"); }489 i += 5; if (i != 5) { print_str("BAD +=\n"); }
490 i -= 2; if (i != 3) { print_str("BAD -=\n"); }490 i -= 2; if (i != 3) { print_str("BAD -=\n"); }
...@@ -510,7 +510,7 @@ extern {...@@ -510,7 +510,7 @@ extern {
510 fn printf(__format: &const u8, ...) i32;510 fn printf(__format: &const u8, ...) i32;
511}511}
512512
513export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {513export fn main(argc: i32, argv: &&u8) i32 => {
514 printf(c"\n");514 printf(c"\n");
515515
516 printf(c"0: %llu\n",516 printf(c"0: %llu\n",
...@@ -636,7 +636,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -636,7 +636,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
636 add_simple_case("structs", R"SOURCE(636 add_simple_case("structs", R"SOURCE(
637import "std.zig";637import "std.zig";
638638
639pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {639pub fn main(args: [][]u8) i32 => {
640 var foo : Foo;640 var foo : Foo;
641 @memset(&foo, 0, @sizeof(Foo));641 @memset(&foo, 0, @sizeof(Foo));
642 foo.a += 1;642 foo.a += 1;
...@@ -711,7 +711,7 @@ import "std.zig";...@@ -711,7 +711,7 @@ import "std.zig";
711const g1 : i32 = 1233 + 1;711const g1 : i32 = 1233 + 1;
712var g2 : i32 = 0;712var g2 : i32 = 0;
713713
714pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {714pub fn main(args: [][]u8) i32 => {
715 if (g2 != 0) { print_str("BAD\n"); }715 if (g2 != 0) { print_str("BAD\n"); }
716 g2 = g1;716 g2 = g1;
717 if (g2 != 1234) { print_str("BAD\n"); }717 if (g2 != 1234) { print_str("BAD\n"); }
...@@ -722,7 +722,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -722,7 +722,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
722722
723 add_simple_case("while loop", R"SOURCE(723 add_simple_case("while loop", R"SOURCE(
724import "std.zig";724import "std.zig";
725pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {725pub fn main(args: [][]u8) i32 => {
726 var i : i32 = 0;726 var i : i32 = 0;
727 while (i < 4) {727 while (i < 4) {
728 print_str("loop\n");728 print_str("loop\n");
...@@ -739,7 +739,7 @@ fn f() i32 => {...@@ -739,7 +739,7 @@ fn f() i32 => {
739739
740 add_simple_case("continue and break", R"SOURCE(740 add_simple_case("continue and break", R"SOURCE(
741import "std.zig";741import "std.zig";
742pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {742pub fn main(args: [][]u8) i32 => {
743 var i : i32 = 0;743 var i : i32 = 0;
744 while (true) {744 while (true) {
745 print_str("loop\n");745 print_str("loop\n");
...@@ -755,7 +755,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -755,7 +755,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
755755
756 add_simple_case("maybe type", R"SOURCE(756 add_simple_case("maybe type", R"SOURCE(
757import "std.zig";757import "std.zig";
758pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {758pub fn main(args: [][]u8) i32 => {
759 const x : ?bool = true;759 const x : ?bool = true;
760760
761 if (const y ?= x) {761 if (const y ?= x) {
...@@ -790,7 +790,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -790,7 +790,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
790790
791 add_simple_case("implicit cast after unreachable", R"SOURCE(791 add_simple_case("implicit cast after unreachable", R"SOURCE(
792import "std.zig";792import "std.zig";
793pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {793pub fn main(args: [][]u8) i32 => {
794 const x = outer();794 const x = outer();
795 if (x == 1234) {795 if (x == 1234) {
796 print_str("OK\n");796 print_str("OK\n");
...@@ -807,7 +807,7 @@ fn outer() isize => {...@@ -807,7 +807,7 @@ fn outer() isize => {
807import "std.zig";807import "std.zig";
808const x: u16 = 13;808const x: u16 = 13;
809const z: @typeof(x) = 19;809const z: @typeof(x) = 19;
810pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {810pub fn main(args: [][]u8) i32 => {
811 const y: @typeof(x) = 120;811 const y: @typeof(x) = 120;
812 print_u64(@sizeof(@typeof(y)));812 print_u64(@sizeof(@typeof(y)));
813 print_str("\n");813 print_str("\n");
...@@ -823,7 +823,7 @@ struct Rand {...@@ -823,7 +823,7 @@ struct Rand {
823 r.seed823 r.seed
824 }824 }
825}825}
826pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {826pub fn main(args: [][]u8) i32 => {
827 const r = Rand {.seed = 1234};827 const r = Rand {.seed = 1234};
828 if (r.get_seed() != 1234) {828 if (r.get_seed() != 1234) {
829 print_str("BAD seed\n");829 print_str("BAD seed\n");
...@@ -836,7 +836,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {...@@ -836,7 +836,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
836 add_simple_case("pointer dereferencing", R"SOURCE(836 add_simple_case("pointer dereferencing", R"SOURCE(
837import "std.zig";837import "std.zig";
838838
839pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {839pub fn main(args: [][]u8) i32 => {
840 var x = i32(3);840 var x = i32(3);
841 const y = &x;841 const y = &x;
842842
...@@ -858,7 +858,7 @@ import "std.zig";...@@ -858,7 +858,7 @@ import "std.zig";
858858
859const ARRAY_SIZE : u8 = 20;859const ARRAY_SIZE : u8 = 20;
860860
861pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {861pub fn main(args: [][]u8) i32 => {
862 var array : [ARRAY_SIZE]u8;862 var array : [ARRAY_SIZE]u8;
863 print_u64(@sizeof(@typeof(array)));863 print_u64(@sizeof(@typeof(array)));
864 print_str("\n");864 print_str("\n");
...@@ -868,7 +868,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -868,7 +868,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
868868
869 add_simple_case("#min_value() and #max_value()", R"SOURCE(869 add_simple_case("#min_value() and #max_value()", R"SOURCE(
870import "std.zig";870import "std.zig";
871pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {871pub fn main(args: [][]u8) i32 => {
872 print_str("max u8: ");872 print_str("max u8: ");
873 print_u64(@max_value(u8));873 print_u64(@max_value(u8));
874 print_str("\n");874 print_str("\n");
...@@ -956,7 +956,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -956,7 +956,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
956956
957 add_simple_case("slicing", R"SOURCE(957 add_simple_case("slicing", R"SOURCE(
958import "std.zig";958import "std.zig";
959pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {959pub fn main(args: [][]u8) i32 => {
960 var array : [20]i32;960 var array : [20]i32;
961961
962 array[5] = 1234;962 array[5] = 1234;
...@@ -984,7 +984,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -984,7 +984,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
984984
985 add_simple_case("else if expression", R"SOURCE(985 add_simple_case("else if expression", R"SOURCE(
986import "std.zig";986import "std.zig";
987pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {987pub fn main(args: [][]u8) i32 => {
988 if (f(1) == 1) {988 if (f(1) == 1) {
989 print_str("OK\n");989 print_str("OK\n");
990 }990 }
...@@ -1003,7 +1003,7 @@ fn f(c: u8) u8 => {...@@ -1003,7 +1003,7 @@ fn f(c: u8) u8 => {
10031003
1004 add_simple_case("overflow intrinsics", R"SOURCE(1004 add_simple_case("overflow intrinsics", R"SOURCE(
1005import "std.zig";1005import "std.zig";
1006pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {1006pub fn main(args: [][]u8) i32 => {
1007 var result: u8;1007 var result: u8;
1008 if (!@add_with_overflow(u8, 250, 100, &result)) {1008 if (!@add_with_overflow(u8, 250, 100, &result)) {
1009 print_str("BAD\n");1009 print_str("BAD\n");
...@@ -1021,7 +1021,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -1021,7 +1021,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
10211021
1022 add_simple_case("memcpy and memset intrinsics", R"SOURCE(1022 add_simple_case("memcpy and memset intrinsics", R"SOURCE(
1023import "std.zig";1023import "std.zig";
1024pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {1024pub fn main(args: [][]u8) i32 => {
1025 var foo : [20]u8;1025 var foo : [20]u8;
1026 var bar : [20]u8;1026 var bar : [20]u8;
10271027
...@@ -1042,7 +1042,7 @@ import "std.zig";...@@ -1042,7 +1042,7 @@ import "std.zig";
1042const z : @typeof(stdin_fileno) = 0;1042const z : @typeof(stdin_fileno) = 0;
1043const x : @typeof(y) = 1234;1043const x : @typeof(y) = 1234;
1044const y : u16 = 5678;1044const y : u16 = 5678;
1045pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {1045pub fn main(args: [][]u8) i32 => {
1046 print_ok(x)1046 print_ok(x)
1047}1047}
1048fn print_ok(val: @typeof(x)) @typeof(foo) => {1048fn print_ok(val: @typeof(x)) @typeof(foo) => {
...@@ -1073,7 +1073,7 @@ enum Bar {...@@ -1073,7 +1073,7 @@ enum Bar {
1073 D,1073 D,
1074}1074}
10751075
1076pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {1076pub fn main(args: [][]u8) i32 => {
1077 const foo1 = Foo.One(13);1077 const foo1 = Foo.One(13);
1078 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });1078 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
1079 const bar = Bar.B;1079 const bar = Bar.B;
...@@ -1106,7 +1106,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {...@@ -1106,7 +1106,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
1106 add_simple_case("array literal", R"SOURCE(1106 add_simple_case("array literal", R"SOURCE(
1107import "std.zig";1107import "std.zig";
11081108
1109pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {1109pub fn main(args: [][]u8) i32 => {
1110 const HEX_MULT = []u16{4096, 256, 16, 1};1110 const HEX_MULT = []u16{4096, 256, 16, 1};
11111111
1112 if (HEX_MULT.len != 4) {1112 if (HEX_MULT.len != 4) {
...@@ -1442,6 +1442,10 @@ fn f(noalias x: i32) => {}...@@ -1442,6 +1442,10 @@ fn f(noalias x: i32) => {}
1442 add_compile_fail_case("struct init syntax for array", R"SOURCE(1442 add_compile_fail_case("struct init syntax for array", R"SOURCE(
1443const foo = []u16{.x = 1024,};1443const foo = []u16{.x = 1024,};
1444 )SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax");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(
1447var foo = u8;
1448 )SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant");
1445}1449}
14461450
1447static void print_compiler_invocation(TestCase *test_case) {1451static void print_compiler_invocation(TestCase *test_case) {