authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-25 19:22:00+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-26 19:50:56-07:00
logb1aa2857ffc631041a36e26b606c060eec1aa6bb
treee89b2036de2fc8193024c15f35dae72b033593b0
parent7d0bb0774e957e81fee7240d410944a0a56c303d

stage2: astgen for loops


2 files changed, 212 insertions(+), 13 deletions(-)

src-self-hosted/astgen.zig+183-6
......@@ -273,6 +273,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
273273 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
274274 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
275275 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
276 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
276277
277278 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
278279 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
......@@ -288,7 +289,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
288289 .StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}),
289290 .StructInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializerDot", .{}),
290291 .Switch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Switch", .{}),
291 .For => return mod.failNode(scope, node, "TODO implement astgen.expr for .For", .{}),
292292 .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}),
293293 .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}),
294294 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
......@@ -497,7 +497,7 @@ fn varDecl(
497497 const var_data: struct { result_loc: ResultLoc, alloc: *zir.Inst } = if (node.getTrailer("type_node")) |type_node| a: {
498498 const type_inst = try typeExpr(mod, scope, type_node);
499499 const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst);
500 break :a .{ .alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst), .result_loc = .{ .ptr = alloc } };
500 break :a .{ .alloc = alloc, .result_loc = .{ .ptr = alloc } };
501501 } else a: {
502502 const alloc = try addZIRNoOp(mod, scope, name_src, .alloc_inferred);
503503 break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc.castTag(.alloc_inferred).? } };
......@@ -624,7 +624,7 @@ fn ptrSliceType(mod: *Module, scope: *Scope, src: usize, ptr_info: *ast.PtrInfo,
624624 .One => if (mutable) T.single_mut_ptr_type else T.single_const_ptr_type,
625625 .Many => if (mutable) T.many_mut_ptr_type else T.many_const_ptr_type,
626626 .C => if (mutable) T.c_mut_ptr_type else T.c_const_ptr_type,
627 .Slice => if (mutable) T.mut_slice_type else T.mut_slice_type,
627 .Slice => if (mutable) T.mut_slice_type else T.const_slice_type,
628628 }, child_type);
629629 }
630630
......@@ -794,9 +794,7 @@ fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfix
794794 const lhs = try expr(mod, scope, .ref, node.lhs);
795795 const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);
796796
797 const pointer = try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{});
798 if (rl == .ref) return pointer;
799 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, src, .deref, pointer));
797 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));
800798}
801799
802800fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
......@@ -1080,6 +1078,12 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
10801078 }
10811079 }
10821080
1081 if (while_node.label) |tok|
1082 return mod.failTok(scope, tok, "TODO labeled while", .{});
1083
1084 if (while_node.inline_token) |tok|
1085 return mod.failTok(scope, tok, "TODO inline while", .{});
1086
10831087 var expr_scope: Scope.GenZIR = .{
10841088 .parent = scope,
10851089 .decl = scope.decl().?,
......@@ -1198,6 +1202,179 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
11981202 return &while_block.base;
11991203}
12001204
1205fn forExpr(mod: *Module, scope: *Scope, rl: ResultLoc, for_node: *ast.Node.For) InnerError!*zir.Inst {
1206 if (for_node.label) |tok|
1207 return mod.failTok(scope, tok, "TODO labeled for", .{});
1208
1209 if (for_node.inline_token) |tok|
1210 return mod.failTok(scope, tok, "TODO inline for", .{});
1211
1212 var for_scope: Scope.GenZIR = .{
1213 .parent = scope,
1214 .decl = scope.decl().?,
1215 .arena = scope.arena(),
1216 .instructions = .{},
1217 };
1218 defer for_scope.instructions.deinit(mod.gpa);
1219
1220 // setup variables and constants
1221 const tree = scope.tree();
1222 const for_src = tree.token_locs[for_node.for_token].start;
1223 const index_ptr = blk: {
1224 const usize_type = try addZIRInstConst(mod, &for_scope.base, for_src, .{
1225 .ty = Type.initTag(.type),
1226 .val = Value.initTag(.usize_type),
1227 });
1228 const index_ptr = try addZIRUnOp(mod, &for_scope.base, for_src, .alloc, usize_type);
1229 // initialize to zero
1230 const zero = try addZIRInstConst(mod, &for_scope.base, for_src, .{
1231 .ty = Type.initTag(.usize),
1232 .val = Value.initTag(.zero),
1233 });
1234 _ = try addZIRBinOp(mod, &for_scope.base, for_src, .store, index_ptr, zero);
1235 break :blk index_ptr;
1236 };
1237 const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);
1238 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
1239 const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{
1240 .object_ptr = array_ptr,
1241 .field_name = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.Str, .{ .bytes = "len" }, .{}),
1242 }, .{});
1243
1244 var loop_scope: Scope.GenZIR = .{
1245 .parent = &for_scope.base,
1246 .decl = for_scope.decl,
1247 .arena = for_scope.arena,
1248 .instructions = .{},
1249 };
1250 defer loop_scope.instructions.deinit(mod.gpa);
1251
1252 var cond_scope: Scope.GenZIR = .{
1253 .parent = &loop_scope.base,
1254 .decl = loop_scope.decl,
1255 .arena = loop_scope.arena,
1256 .instructions = .{},
1257 };
1258 defer cond_scope.instructions.deinit(mod.gpa);
1259
1260 // check condition i < array_expr.len
1261 const index = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, index_ptr);
1262 const len = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, len_ptr);
1263 const cond = try addZIRBinOp(mod, &cond_scope.base, cond_src, .cmp_lt, index, len);
1264
1265 const condbr = try addZIRInstSpecial(mod, &cond_scope.base, for_src, zir.Inst.CondBr, .{
1266 .condition = cond,
1267 .then_body = undefined, // populated below
1268 .else_body = undefined, // populated below
1269 }, .{});
1270 const cond_block = try addZIRInstBlock(mod, &loop_scope.base, for_src, .{
1271 .instructions = try loop_scope.arena.dupe(*zir.Inst, cond_scope.instructions.items),
1272 });
1273
1274 // increment index variable
1275 const one = try addZIRInstConst(mod, &loop_scope.base, for_src, .{
1276 .ty = Type.initTag(.usize),
1277 .val = Value.initTag(.one),
1278 });
1279 const index_plus_one = try addZIRBinOp(mod, &loop_scope.base, for_src, .add, index, one);
1280 _ = try addZIRBinOp(mod, &loop_scope.base, for_src, .store, index_ptr, index_plus_one);
1281
1282 // looping stuff
1283 const loop = try addZIRInstLoop(mod, &for_scope.base, for_src, .{
1284 .instructions = try for_scope.arena.dupe(*zir.Inst, loop_scope.instructions.items),
1285 });
1286 const for_block = try addZIRInstBlock(mod, scope, for_src, .{
1287 .instructions = try scope.arena().dupe(*zir.Inst, for_scope.instructions.items),
1288 });
1289
1290 // while body
1291 const then_src = tree.token_locs[for_node.body.lastToken()].start;
1292 var then_scope: Scope.GenZIR = .{
1293 .parent = &cond_scope.base,
1294 .decl = cond_scope.decl,
1295 .arena = cond_scope.arena,
1296 .instructions = .{},
1297 };
1298 defer then_scope.instructions.deinit(mod.gpa);
1299
1300 // Most result location types can be forwarded directly; however
1301 // if we need to write to a pointer which has an inferred type,
1302 // proper type inference requires peer type resolution on the while's
1303 // branches.
1304 const branch_rl: ResultLoc = switch (rl) {
1305 .discard, .none, .ty, .ptr, .ref => rl,
1306 .inferred_ptr, .bitcasted_ptr, .block_ptr => .{ .block_ptr = for_block },
1307 };
1308
1309 var index_scope: Scope.LocalPtr = undefined;
1310 const then_sub_scope = blk: {
1311 const payload = for_node.payload.castTag(.PointerIndexPayload).?;
1312 const is_ptr = payload.ptr_token != null;
1313 const value_name = tree.tokenSlice(payload.value_symbol.firstToken());
1314 if (!mem.eql(u8, value_name, "_")) {
1315 return mod.failNode(&then_scope.base, payload.value_symbol, "TODO implement for value payload", .{});
1316 } else if (is_ptr) {
1317 return mod.failTok(&then_scope.base, payload.ptr_token.?, "pointer modifier invalid on discard", .{});
1318 }
1319
1320 const index_symbol_node = payload.index_symbol orelse
1321 break :blk &then_scope.base;
1322
1323 const index_name = tree.tokenSlice(index_symbol_node.firstToken());
1324 if (mem.eql(u8, index_name, "_")) {
1325 break :blk &then_scope.base;
1326 }
1327 // TODO ensure this is const
1328 index_scope = .{
1329 .parent = &then_scope.base,
1330 .gen_zir = &then_scope,
1331 .name = index_name,
1332 .ptr = index_ptr,
1333 };
1334 break :blk &index_scope.base;
1335 };
1336
1337 const then_result = try expr(mod, then_sub_scope, branch_rl, for_node.body);
1338 if (!then_result.tag.isNoReturn()) {
1339 _ = try addZIRInst(mod, then_sub_scope, then_src, zir.Inst.Break, .{
1340 .block = cond_block,
1341 .operand = then_result,
1342 }, .{});
1343 }
1344 condbr.positionals.then_body = .{
1345 .instructions = try then_scope.arena.dupe(*zir.Inst, then_scope.instructions.items),
1346 };
1347
1348 // else branch
1349 var else_scope: Scope.GenZIR = .{
1350 .parent = &cond_scope.base,
1351 .decl = cond_scope.decl,
1352 .arena = cond_scope.arena,
1353 .instructions = .{},
1354 };
1355 defer else_scope.instructions.deinit(mod.gpa);
1356
1357 if (for_node.@"else") |else_node| {
1358 const else_src = tree.token_locs[else_node.body.lastToken()].start;
1359 const else_result = try expr(mod, &else_scope.base, branch_rl, else_node.body);
1360 if (!else_result.tag.isNoReturn()) {
1361 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.Break, .{
1362 .block = for_block,
1363 .operand = else_result,
1364 }, .{});
1365 }
1366 } else {
1367 const else_src = tree.token_locs[for_node.lastToken()].start;
1368 _ = try addZIRInst(mod, &else_scope.base, else_src, zir.Inst.BreakVoid, .{
1369 .block = for_block,
1370 }, .{});
1371 }
1372 condbr.positionals.else_body = .{
1373 .instructions = try else_scope.arena.dupe(*zir.Inst, else_scope.instructions.items),
1374 };
1375 return &for_block.base;
1376}
1377
12011378fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerError!*zir.Inst {
12021379 const tree = scope.tree();
12031380 const src = tree.token_locs[cfe.ltoken].start;
src-self-hosted/value.zig+29-7
......@@ -65,6 +65,7 @@ pub const Value = extern union {
6565
6666 undef,
6767 zero,
68 one,
6869 void_value,
6970 unreachable_value,
7071 empty_array,
......@@ -174,6 +175,7 @@ pub const Value = extern union {
174175 .anyframe_type,
175176 .undef,
176177 .zero,
178 .one,
177179 .void_value,
178180 .unreachable_value,
179181 .empty_array,
......@@ -313,6 +315,7 @@ pub const Value = extern union {
313315 .null_value => return out_stream.writeAll("null"),
314316 .undef => return out_stream.writeAll("undefined"),
315317 .zero => return out_stream.writeAll("0"),
318 .one => return out_stream.writeAll("1"),
316319 .void_value => return out_stream.writeAll("{}"),
317320 .unreachable_value => return out_stream.writeAll("unreachable"),
318321 .bool_true => return out_stream.writeAll("true"),
......@@ -447,6 +450,7 @@ pub const Value = extern union {
447450
448451 .undef,
449452 .zero,
453 .one,
450454 .void_value,
451455 .unreachable_value,
452456 .empty_array,
......@@ -546,7 +550,9 @@ pub const Value = extern union {
546550 .bool_false,
547551 => return BigIntMutable.init(&space.limbs, 0).toConst(),
548552
549 .bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(),
553 .one,
554 .bool_true,
555 => return BigIntMutable.init(&space.limbs, 1).toConst(),
550556
551557 .int_u64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_u64).?.int).toConst(),
552558 .int_i64 => return BigIntMutable.init(&space.limbs, self.cast(Payload.Int_i64).?.int).toConst(),
......@@ -627,7 +633,9 @@ pub const Value = extern union {
627633 .bool_false,
628634 => return 0,
629635
630 .bool_true => return 1,
636 .one,
637 .bool_true,
638 => return 1,
631639
632640 .int_u64 => return self.cast(Payload.Int_u64).?.int,
633641 .int_i64 => return @intCast(u64, self.cast(Payload.Int_i64).?.int),
......@@ -708,7 +716,9 @@ pub const Value = extern union {
708716 .bool_false,
709717 => return 0,
710718
711 .bool_true => return 1,
719 .one,
720 .bool_true,
721 => return 1,
712722
713723 .int_u64 => return @intCast(i64, self.cast(Payload.Int_u64).?.int),
714724 .int_i64 => return self.cast(Payload.Int_i64).?.int,
......@@ -734,6 +744,7 @@ pub const Value = extern union {
734744 .float_128 => @floatCast(T, self.cast(Payload.Float_128).?.val),
735745
736746 .zero => 0,
747 .one => 1,
737748 .int_u64 => @intToFloat(T, self.cast(Payload.Int_u64).?.int),
738749 .int_i64 => @intToFloat(T, self.cast(Payload.Int_i64).?.int),
739750
......@@ -814,7 +825,9 @@ pub const Value = extern union {
814825 .bool_false,
815826 => return 0,
816827
817 .bool_true => return 1,
828 .one,
829 .bool_true,
830 => return 1,
818831
819832 .int_u64 => {
820833 const x = self.cast(Payload.Int_u64).?.int;
......@@ -900,7 +913,9 @@ pub const Value = extern union {
900913 .bool_false,
901914 => return true,
902915
903 .bool_true => {
916 .one,
917 .bool_true,
918 => {
904919 const info = ty.intInfo(target);
905920 if (info.signed) {
906921 return info.bits >= 2;
......@@ -1064,7 +1079,9 @@ pub const Value = extern union {
10641079 .@"error",
10651080 => unreachable,
10661081
1067 .zero => false,
1082 .zero,
1083 .one,
1084 => false,
10681085
10691086 .float_16 => @rem(self.cast(Payload.Float_16).?.val, 1) != 0,
10701087 .float_32 => @rem(self.cast(Payload.Float_32).?.val, 1) != 0,
......@@ -1140,7 +1157,9 @@ pub const Value = extern union {
11401157 .bool_false,
11411158 => .eq,
11421159
1143 .bool_true => .gt,
1160 .one,
1161 .bool_true,
1162 => .gt,
11441163
11451164 .int_u64 => std.math.order(lhs.cast(Payload.Int_u64).?.int, 0),
11461165 .int_i64 => std.math.order(lhs.cast(Payload.Int_i64).?.int, 0),
......@@ -1257,6 +1276,7 @@ pub const Value = extern union {
12571276 .enum_literal_type,
12581277 .anyframe_type,
12591278 .zero,
1279 .one,
12601280 .bool_true,
12611281 .bool_false,
12621282 .null_value,
......@@ -1339,6 +1359,7 @@ pub const Value = extern union {
13391359 .enum_literal_type,
13401360 .anyframe_type,
13411361 .zero,
1362 .one,
13421363 .bool_true,
13431364 .bool_false,
13441365 .null_value,
......@@ -1438,6 +1459,7 @@ pub const Value = extern union {
14381459 .enum_literal_type,
14391460 .anyframe_type,
14401461 .zero,
1462 .one,
14411463 .empty_array,
14421464 .bool_true,
14431465 .bool_false,