authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-15 20:44:21-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-15 20:44:21-05:00
log92fc5947fc18ea077f0e02bc4758e9050270e4bb
tree7f3967aa4372250330911b3b6d64ddb03bf05575
parent5a4968484b1ff761766180204151e77a701cff68

fix compiler crash related to @alignOf


5 files changed, 267 insertions(+), 2 deletions(-)

src/analyze.cpp+1
......@@ -2231,6 +2231,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
22312231 // is a pointer to this very struct, or a function pointer with parameters that
22322232 // reference such a type.
22332233 union_type->data.unionation.zero_bits_known = true;
2234 union_type->data.unionation.zero_bits_loop_flag = false;
22342235 if (union_type->data.unionation.abi_alignment == 0) {
22352236 if (union_type->data.unionation.layout == ContainerLayoutPacked) {
22362237 union_type->data.unionation.abi_alignment = 1;
src/ir.cpp+2-2
......@@ -9858,7 +9858,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
98589858
98599859 if (fn_proto_node->data.fn_proto.is_var_args) {
98609860 ir_add_error(ira, &call_instruction->base,
9861 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/andrewrk/zig/issues/313"));
9861 buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/zig-lang/zig/issues/313"));
98629862 return ira->codegen->builtin_types.entry_invalid;
98639863 }
98649864
......@@ -14011,7 +14011,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc
1401114011 return ira->codegen->builtin_types.entry_invalid;
1401214012 TypeTableEntry *type_entry = ir_resolve_type(ira, type_value);
1401314013
14014 ensure_complete_type(ira->codegen, type_entry);
14014 type_ensure_zero_bits_known(ira->codegen, type_entry);
1401514015 if (type_is_invalid(type_entry))
1401614016 return ira->codegen->builtin_types.entry_invalid;
1401714017
test/build_examples.zig+1
......@@ -16,4 +16,5 @@ pub fn addCases(cases: &tests.BuildExamplesContext) {
1616 cases.addBuildFile("test/standalone/issue_339/build.zig");
1717 cases.addBuildFile("test/standalone/pkg_import/build.zig");
1818 cases.addBuildFile("test/standalone/use_alias/build.zig");
19 cases.addBuildFile("test/standalone/brace_expansion/build.zig");
1920}
test/standalone/brace_expansion/build.zig created+9
......@@ -0,0 +1,9 @@
1const Builder = @import("std").build.Builder;
2
3pub fn build(b: &Builder) -> %void {
4 const main = b.addTest("main.zig");
5 main.setBuildMode(b.standardReleaseOptions());
6
7 const test_step = b.step("test", "Test it");
8 test_step.dependOn(&main.step);
9}
test/standalone/brace_expansion/main.zig created+254
......@@ -0,0 +1,254 @@
1const std = @import("std");
2const io = std.io;
3const mem = std.mem;
4const debug = std.debug;
5const assert = debug.assert;
6const Buffer = std.Buffer;
7const ArrayList = std.ArrayList;
8
9error InvalidInput;
10error OutOfMem;
11
12const Token = union(enum) {
13 Word: []const u8,
14 OpenBrace,
15 CloseBrace,
16 Comma,
17 Eof,
18};
19
20var global_allocator: &mem.Allocator = undefined;
21
22fn tokenize(input:[] const u8) -> %ArrayList(Token) {
23 const State = enum {
24 Start,
25 Word,
26 };
27
28 var token_list = ArrayList(Token).init(global_allocator);
29 var tok_begin: usize = undefined;
30 var state = State.Start;
31
32 for (input) |b, i| {
33 switch (state) {
34 State.Start => switch (b) {
35 'a'...'z', 'A'...'Z' => {
36 state = State.Word;
37 tok_begin = i;
38 },
39 '{' => try token_list.append(Token.OpenBrace),
40 '}' => try token_list.append(Token.CloseBrace),
41 ',' => try token_list.append(Token.Comma),
42 else => return error.InvalidInput,
43 },
44 State.Word => switch (b) {
45 'a'...'z', 'A'...'Z' => {},
46 '{', '}', ',' => {
47 try token_list.append(Token { .Word = input[tok_begin..i] });
48 switch (b) {
49 '{' => try token_list.append(Token.OpenBrace),
50 '}' => try token_list.append(Token.CloseBrace),
51 ',' => try token_list.append(Token.Comma),
52 else => unreachable,
53 }
54 state = State.Start;
55 },
56 else => return error.InvalidInput,
57 },
58 }
59 }
60 switch (state) {
61 State.Start => {},
62 State.Word => try token_list.append(Token {.Word = input[tok_begin..] }),
63 }
64 try token_list.append(Token.Eof);
65 return token_list;
66}
67
68const Node = union(enum) {
69 Scalar: []const u8,
70 List: ArrayList(Node),
71 Combine: []Node,
72};
73
74fn parse(tokens: &const ArrayList(Token), token_index: &usize) -> %Node {
75 const first_token = tokens.items[*token_index];
76 *token_index += 1;
77
78 const result_node = switch (first_token) {
79 Token.Word => |word| Node { .Scalar = word },
80 Token.OpenBrace => blk: {
81 var list = ArrayList(Node).init(global_allocator);
82 while (true) {
83 try list.append(try parse(tokens, token_index));
84
85 const token = tokens.items[*token_index];
86 *token_index += 1;
87
88 switch (token) {
89 Token.CloseBrace => break,
90 Token.Comma => continue,
91 else => return error.InvalidInput,
92 }
93 }
94 break :blk Node { .List = list };
95 },
96 else => return error.InvalidInput,
97 };
98
99 switch (tokens.items[*token_index]) {
100 Token.Word, Token.OpenBrace => {
101 const pair = try global_allocator.alloc(Node, 2);
102 pair[0] = result_node;
103 pair[1] = try parse(tokens, token_index);
104 return Node { .Combine = pair };
105 },
106 else => return result_node,
107 }
108}
109
110fn expandString(input: []const u8, output: &Buffer) -> %void {
111 const tokens = try tokenize(input);
112 if (tokens.len == 1) {
113 return output.resize(0);
114 }
115
116 var token_index: usize = 0;
117 const root = try parse(tokens, &token_index);
118 const last_token = tokens.items[token_index];
119 switch (last_token) {
120 Token.Eof => {},
121 else => return error.InvalidInput,
122 }
123
124 var result_list = ArrayList(Buffer).init(global_allocator);
125 defer result_list.deinit();
126
127 try expandNode(root, &result_list);
128
129 try output.resize(0);
130 for (result_list.toSliceConst()) |buf, i| {
131 if (i != 0) {
132 try output.appendByte(' ');
133 }
134 try output.append(buf.toSliceConst());
135 }
136}
137
138const ListOfBuffer0 = ArrayList(Buffer); // TODO this is working around a compiler bug, fix and delete this
139
140fn expandNode(node: &const Node, output: &ListOfBuffer0) -> %void {
141 assert(output.len == 0);
142 switch (*node) {
143 Node.Scalar => |scalar| {
144 try output.append(try Buffer.init(global_allocator, scalar));
145 },
146 Node.Combine => |pair| {
147 const a_node = pair[0];
148 const b_node = pair[1];
149
150 var child_list_a = ArrayList(Buffer).init(global_allocator);
151 try expandNode(a_node, &child_list_a);
152
153 var child_list_b = ArrayList(Buffer).init(global_allocator);
154 try expandNode(b_node, &child_list_b);
155
156 for (child_list_a.toSliceConst()) |buf_a| {
157 for (child_list_b.toSliceConst()) |buf_b| {
158 var combined_buf = try Buffer.initFromBuffer(buf_a);
159 try combined_buf.append(buf_b.toSliceConst());
160 try output.append(combined_buf);
161 }
162 }
163 },
164 Node.List => |list| {
165 for (list.toSliceConst()) |child_node| {
166 var child_list = ArrayList(Buffer).init(global_allocator);
167 try expandNode(child_node, &child_list);
168
169 for (child_list.toSliceConst()) |buf| {
170 try output.append(buf);
171 }
172 }
173 },
174 }
175}
176
177pub fn main() -> %void {
178 var stdin_file = try io.getStdIn();
179 var stdout_file = try io.getStdOut();
180
181 var inc_allocator = try std.heap.IncrementingAllocator.init(2 * 1024 * 1024);
182 defer inc_allocator.deinit();
183
184 global_allocator = &inc_allocator.allocator;
185
186 var stdin_buf = try Buffer.initSize(global_allocator, 0);
187 defer stdin_buf.deinit();
188
189 var stdin_adapter = io.FileInStream.init(&stdin_file);
190 try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize));
191
192 var result_buf = try Buffer.initSize(global_allocator, 0);
193 defer result_buf.deinit();
194
195 try expandString(stdin_buf.toSlice(), &result_buf);
196 try stdout_file.write(result_buf.toSliceConst());
197}
198
199test "invalid inputs" {
200 global_allocator = std.debug.global_allocator;
201
202 expectError("}ABC", error.InvalidInput);
203 expectError("{ABC", error.InvalidInput);
204 expectError("}{", error.InvalidInput);
205 expectError("{}", error.InvalidInput);
206 expectError("A,B,C", error.InvalidInput);
207 expectError("{A{B,C}", error.InvalidInput);
208 expectError("{A,}", error.InvalidInput);
209
210 expectError("\n", error.InvalidInput);
211}
212
213fn expectError(test_input: []const u8, expected_err: error) {
214 var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable;
215 defer output_buf.deinit();
216
217 if (expandString("}ABC", &output_buf)) {
218 unreachable;
219 } else |err| {
220 assert(expected_err == err);
221 }
222}
223
224test "valid inputs" {
225 global_allocator = std.debug.global_allocator;
226
227 expectExpansion("{x,y,z}", "x y z");
228 expectExpansion("{A,B}{x,y}", "Ax Ay Bx By");
229 expectExpansion("{A,B{x,y}}", "A Bx By");
230
231 expectExpansion("{ABC}", "ABC");
232 expectExpansion("{A,B,C}", "A B C");
233 expectExpansion("ABC", "ABC");
234
235 expectExpansion("", "");
236 expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh");
237 expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh");
238 expectExpansion("{A,B}a", "Aa Ba");
239 expectExpansion("{C,{x,y}}", "C x y");
240 expectExpansion("z{C,{x,y}}", "zC zx zy");
241 expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg");
242 expectExpansion("a{x,y}b", "axb ayb");
243 expectExpansion("z{{a,b}}", "za zb");
244 expectExpansion("a{b}", "ab");
245}
246
247fn expectExpansion(test_input: []const u8, expected_result: []const u8) {
248 var result = Buffer.initSize(global_allocator, 0) catch unreachable;
249 defer result.deinit();
250
251 expandString(test_input, &result) catch unreachable;
252
253 assert(mem.eql(u8, result.toSlice(), expected_result));
254}