authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-12 15:30:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-20 12:19:16-07:00
log913393fd3b986dd262a8419341dced9ad5d9620d
tree24206439ed1abe1e7ca09a0f164d79981ea4eb2b
parentee6432537ee29485c5de6c8b0911ef1482d752a7

stage2: first pass over Module.zig for AIR memory layout


9 files changed, 429 insertions(+), 455 deletions(-)

BRANCH_TODO+122
......@@ -568,3 +568,125 @@ const DumpAir = struct {
568568 }
569569 }
570570};
571
572pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {
573 _ = mod;
574 const const_inst = try arena.create(ir.Inst.Constant);
575 const_inst.* = .{
576 .base = .{
577 .tag = ir.Inst.Constant.base_tag,
578 .ty = typed_value.ty,
579 .src = src,
580 },
581 .val = typed_value.val,
582 };
583 return &const_inst.base;
584}
585
586pub fn constType(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
587 return mod.constInst(arena, src, .{
588 .ty = Type.initTag(.type),
589 .val = try ty.toValue(arena),
590 });
591}
592
593pub fn constVoid(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
594 return mod.constInst(arena, src, .{
595 .ty = Type.initTag(.void),
596 .val = Value.initTag(.void_value),
597 });
598}
599
600pub fn constNoReturn(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
601 return mod.constInst(arena, src, .{
602 .ty = Type.initTag(.noreturn),
603 .val = Value.initTag(.unreachable_value),
604 });
605}
606
607pub fn constUndef(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
608 return mod.constInst(arena, src, .{
609 .ty = ty,
610 .val = Value.initTag(.undef),
611 });
612}
613
614pub fn constBool(mod: *Module, arena: *Allocator, src: LazySrcLoc, v: bool) !*ir.Inst {
615 return mod.constInst(arena, src, .{
616 .ty = Type.initTag(.bool),
617 .val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)],
618 });
619}
620
621pub fn constIntUnsigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: u64) !*ir.Inst {
622 return mod.constInst(arena, src, .{
623 .ty = ty,
624 .val = try Value.Tag.int_u64.create(arena, int),
625 });
626}
627
628pub fn constIntSigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: i64) !*ir.Inst {
629 return mod.constInst(arena, src, .{
630 .ty = ty,
631 .val = try Value.Tag.int_i64.create(arena, int),
632 });
633}
634
635pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, big_int: BigIntConst) !*ir.Inst {
636 if (big_int.positive) {
637 if (big_int.to(u64)) |x| {
638 return mod.constIntUnsigned(arena, src, ty, x);
639 } else |err| switch (err) {
640 error.NegativeIntoUnsigned => unreachable,
641 error.TargetTooSmall => {}, // handled below
642 }
643 return mod.constInst(arena, src, .{
644 .ty = ty,
645 .val = try Value.Tag.int_big_positive.create(arena, big_int.limbs),
646 });
647 } else {
648 if (big_int.to(i64)) |x| {
649 return mod.constIntSigned(arena, src, ty, x);
650 } else |err| switch (err) {
651 error.NegativeIntoUnsigned => unreachable,
652 error.TargetTooSmall => {}, // handled below
653 }
654 return mod.constInst(arena, src, .{
655 .ty = ty,
656 .val = try Value.Tag.int_big_negative.create(arena, big_int.limbs),
657 });
658 }
659}
660
661pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void {
662 const zir_module = scope.namespace();
663 const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source");
664 const loc = std.zig.findLineColumn(source, inst.src);
665 if (inst.tag == .constant) {
666 std.debug.print("constant ty={} val={} src={s}:{d}:{d}\n", .{
667 inst.ty,
668 inst.castTag(.constant).?.val,
669 zir_module.subFilePath(),
670 loc.line + 1,
671 loc.column + 1,
672 });
673 } else if (inst.deaths == 0) {
674 std.debug.print("{s} ty={} src={s}:{d}:{d}\n", .{
675 @tagName(inst.tag),
676 inst.ty,
677 zir_module.subFilePath(),
678 loc.line + 1,
679 loc.column + 1,
680 });
681 } else {
682 std.debug.print("{s} ty={} deaths={b} src={s}:{d}:{d}\n", .{
683 @tagName(inst.tag),
684 inst.ty,
685 inst.deaths,
686 zir_module.subFilePath(),
687 loc.line + 1,
688 loc.column + 1,
689 });
690 }
691}
692
src/Air.zig+12-2
......@@ -29,8 +29,11 @@ pub const Inst = struct {
2929 data: Data,
3030
3131 pub const Tag = enum(u8) {
32 /// The first N instructions in Air must be one arg instruction per function parameter.
33 /// Uses the `ty` field.
32 /// The first N instructions in the main block must be one arg instruction per
33 /// function parameter. This makes function parameters participate in
34 /// liveness analysis without any special handling.
35 /// Uses the `ty_str` field.
36 /// The string is the parameter name.
3437 arg,
3538 /// Float or integer addition. For integers, wrapping is undefined behavior.
3639 /// Both operands are guaranteed to be the same type, and the result type
......@@ -131,6 +134,8 @@ pub const Inst = struct {
131134 /// A comptime-known value. Uses the `ty_pl` field, payload is index of
132135 /// `values` array.
133136 constant,
137 /// A comptime-known type. Uses the `ty` field.
138 const_ty,
134139 /// Notes the beginning of a source code statement and marks the line and column.
135140 /// Result type is always void.
136141 /// Uses the `dbg_stmt` field.
......@@ -289,6 +294,11 @@ pub const Inst = struct {
289294 // Index into a different array.
290295 payload: u32,
291296 },
297 ty_str: struct {
298 ty: Ref,
299 // ZIR string table index.
300 str: u32,
301 },
292302 br: struct {
293303 block_inst: Index,
294304 operand: Ref,
src/AstGen.zig+1-1
......@@ -9821,7 +9821,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
98219821 astgen.source_column = column;
98229822}
98239823
9824const ref_start_index = Zir.Inst.Ref.typed_value_map.len;
9824const ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len;
98259825
98269826fn indexToRef(inst: Zir.Inst.Index) Zir.Inst.Ref {
98279827 return @intToEnum(Zir.Inst.Ref, ref_start_index + inst);
src/Module.zig+30-329
......@@ -1155,7 +1155,7 @@ pub const Scope = struct {
11551155 /// This can vary during inline or comptime function calls. See `Sema.owner_decl`
11561156 /// for the one that will be the same for all Block instances.
11571157 src_decl: *Decl,
1158 instructions: ArrayListUnmanaged(*ir.Inst),
1158 instructions: ArrayListUnmanaged(Air.Inst.Index),
11591159 label: ?*Label = null,
11601160 inlining: ?*Inlining,
11611161 /// If runtime_index is not 0 then one of these is guaranteed to be non null.
......@@ -1187,14 +1187,14 @@ pub const Scope = struct {
11871187 };
11881188
11891189 pub const Merges = struct {
1190 block_inst: *ir.Inst.Block,
1190 block_inst: Air.Inst.Index,
11911191 /// Separate array list from break_inst_list so that it can be passed directly
11921192 /// to resolvePeerTypes.
1193 results: ArrayListUnmanaged(*ir.Inst),
1193 results: ArrayListUnmanaged(Air.Inst.Index),
11941194 /// Keeps track of the break instructions so that the operand can be replaced
11951195 /// if we need to add type coercion at the end of block analysis.
11961196 /// Same indexes, capacity, length as `results`.
1197 br_list: ArrayListUnmanaged(*ir.Inst.Br),
1197 br_list: ArrayListUnmanaged(Air.Inst.Index),
11981198 };
11991199
12001200 /// For debugging purposes.
......@@ -1230,187 +1230,6 @@ pub const Scope = struct {
12301230 pub fn getFileScope(block: *Block) *Scope.File {
12311231 return block.src_decl.namespace.file_scope;
12321232 }
1233
1234 pub fn addNoOp(
1235 block: *Scope.Block,
1236 src: LazySrcLoc,
1237 ty: Type,
1238 comptime tag: ir.Inst.Tag,
1239 ) !*ir.Inst {
1240 const inst = try block.sema.arena.create(tag.Type());
1241 inst.* = .{
1242 .base = .{
1243 .tag = tag,
1244 .ty = ty,
1245 .src = src,
1246 },
1247 };
1248 try block.instructions.append(block.sema.gpa, &inst.base);
1249 return &inst.base;
1250 }
1251
1252 pub fn addUnOp(
1253 block: *Scope.Block,
1254 src: LazySrcLoc,
1255 ty: Type,
1256 tag: ir.Inst.Tag,
1257 operand: *ir.Inst,
1258 ) !*ir.Inst {
1259 const inst = try block.sema.arena.create(ir.Inst.UnOp);
1260 inst.* = .{
1261 .base = .{
1262 .tag = tag,
1263 .ty = ty,
1264 .src = src,
1265 },
1266 .operand = operand,
1267 };
1268 try block.instructions.append(block.sema.gpa, &inst.base);
1269 return &inst.base;
1270 }
1271
1272 pub fn addBinOp(
1273 block: *Scope.Block,
1274 src: LazySrcLoc,
1275 ty: Type,
1276 tag: ir.Inst.Tag,
1277 lhs: *ir.Inst,
1278 rhs: *ir.Inst,
1279 ) !*ir.Inst {
1280 const inst = try block.sema.arena.create(ir.Inst.BinOp);
1281 inst.* = .{
1282 .base = .{
1283 .tag = tag,
1284 .ty = ty,
1285 .src = src,
1286 },
1287 .lhs = lhs,
1288 .rhs = rhs,
1289 };
1290 try block.instructions.append(block.sema.gpa, &inst.base);
1291 return &inst.base;
1292 }
1293
1294 pub fn addBr(
1295 scope_block: *Scope.Block,
1296 src: LazySrcLoc,
1297 target_block: *ir.Inst.Block,
1298 operand: *ir.Inst,
1299 ) !*ir.Inst.Br {
1300 const inst = try scope_block.sema.arena.create(ir.Inst.Br);
1301 inst.* = .{
1302 .base = .{
1303 .tag = .br,
1304 .ty = Type.initTag(.noreturn),
1305 .src = src,
1306 },
1307 .operand = operand,
1308 .block = target_block,
1309 };
1310 try scope_block.instructions.append(scope_block.sema.gpa, &inst.base);
1311 return inst;
1312 }
1313
1314 pub fn addCondBr(
1315 block: *Scope.Block,
1316 src: LazySrcLoc,
1317 condition: *ir.Inst,
1318 then_body: ir.Body,
1319 else_body: ir.Body,
1320 ) !*ir.Inst {
1321 const inst = try block.sema.arena.create(ir.Inst.CondBr);
1322 inst.* = .{
1323 .base = .{
1324 .tag = .condbr,
1325 .ty = Type.initTag(.noreturn),
1326 .src = src,
1327 },
1328 .condition = condition,
1329 .then_body = then_body,
1330 .else_body = else_body,
1331 };
1332 try block.instructions.append(block.sema.gpa, &inst.base);
1333 return &inst.base;
1334 }
1335
1336 pub fn addCall(
1337 block: *Scope.Block,
1338 src: LazySrcLoc,
1339 ty: Type,
1340 func: *ir.Inst,
1341 args: []const *ir.Inst,
1342 ) !*ir.Inst {
1343 const inst = try block.sema.arena.create(ir.Inst.Call);
1344 inst.* = .{
1345 .base = .{
1346 .tag = .call,
1347 .ty = ty,
1348 .src = src,
1349 },
1350 .func = func,
1351 .args = args,
1352 };
1353 try block.instructions.append(block.sema.gpa, &inst.base);
1354 return &inst.base;
1355 }
1356
1357 pub fn addSwitchBr(
1358 block: *Scope.Block,
1359 src: LazySrcLoc,
1360 operand: *ir.Inst,
1361 cases: []ir.Inst.SwitchBr.Case,
1362 else_body: ir.Body,
1363 ) !*ir.Inst {
1364 const inst = try block.sema.arena.create(ir.Inst.SwitchBr);
1365 inst.* = .{
1366 .base = .{
1367 .tag = .switchbr,
1368 .ty = Type.initTag(.noreturn),
1369 .src = src,
1370 },
1371 .target = operand,
1372 .cases = cases,
1373 .else_body = else_body,
1374 };
1375 try block.instructions.append(block.sema.gpa, &inst.base);
1376 return &inst.base;
1377 }
1378
1379 pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, line: u32, column: u32) !*ir.Inst {
1380 const inst = try block.sema.arena.create(ir.Inst.DbgStmt);
1381 inst.* = .{
1382 .base = .{
1383 .tag = .dbg_stmt,
1384 .ty = Type.initTag(.void),
1385 .src = src,
1386 },
1387 .line = line,
1388 .column = column,
1389 };
1390 try block.instructions.append(block.sema.gpa, &inst.base);
1391 return &inst.base;
1392 }
1393
1394 pub fn addStructFieldPtr(
1395 block: *Scope.Block,
1396 src: LazySrcLoc,
1397 ty: Type,
1398 struct_ptr: *ir.Inst,
1399 field_index: u32,
1400 ) !*ir.Inst {
1401 const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr);
1402 inst.* = .{
1403 .base = .{
1404 .tag = .struct_field_ptr,
1405 .ty = ty,
1406 .src = src,
1407 },
1408 .struct_ptr = struct_ptr,
1409 .field_index = field_index,
1410 };
1411 try block.instructions.append(block.sema.gpa, &inst.base);
1412 return &inst.base;
1413 }
14141233 };
14151234};
14161235
......@@ -3594,30 +3413,14 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
35943413 defer decl.value_arena.?.* = arena.state;
35953414
35963415 const fn_ty = decl.ty;
3597 const param_inst_list = try gpa.alloc(*ir.Inst, fn_ty.fnParamLen());
3416 const param_inst_list = try gpa.alloc(Air.Inst.Index, fn_ty.fnParamLen());
35983417 defer gpa.free(param_inst_list);
35993418
3600 for (param_inst_list) |*param_inst, param_index| {
3601 const param_type = fn_ty.fnParamType(param_index);
3602 const arg_inst = try arena.allocator.create(ir.Inst.Arg);
3603 arg_inst.* = .{
3604 .base = .{
3605 .tag = .arg,
3606 .ty = param_type,
3607 .src = .unneeded,
3608 },
3609 .name = undefined, // Set in the semantic analysis of the arg instruction.
3610 };
3611 param_inst.* = &arg_inst.base;
3612 }
3613
3614 const zir = decl.namespace.file_scope.zir;
3615
36163419 var sema: Sema = .{
36173420 .mod = mod,
36183421 .gpa = gpa,
36193422 .arena = &arena.allocator,
3620 .code = zir,
3423 .code = decl.namespace.file_scope.zir,
36213424 .owner_decl = decl,
36223425 .namespace = decl.namespace,
36233426 .func = func,
......@@ -3641,7 +3444,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
36413444 };
36423445 defer inner_block.instructions.deinit(gpa);
36433446
3644 // AIR currently requires the arg parameters to be the first N instructions
3447 // AIR requires the arg parameters to be the first N instructions.
3448 for (param_inst_list) |*param_inst, param_index| {
3449 const param_type = fn_ty.fnParamType(param_index);
3450 const ty_ref = try sema.addType(param_type);
3451 param_inst.* = @intCast(u32, sema.air_instructions.len);
3452 try sema.air_instructions.append(gpa, .{
3453 .tag = .arg,
3454 .data = .{
3455 .ty_str = .{
3456 .ty = ty_ref,
3457 .str = undefined, // Set in the semantic analysis of the arg instruction.
3458 },
3459 },
3460 });
3461 }
36453462 try inner_block.instructions.appendSlice(gpa, param_inst_list);
36463463
36473464 func.state = .in_progress;
......@@ -3650,17 +3467,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air {
36503467 try sema.analyzeFnBody(&inner_block, func.zir_body_inst);
36513468
36523469 // Copy the block into place and mark that as the main block.
3653 sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = sema.air_extra.items.len;
3654 try sema.air_extra.appendSlice(inner_block.instructions.items);
3470 try sema.air_extra.ensureUnusedCapacity(gpa, inner_block.instructions.items.len + 1);
3471 const main_block_index = sema.addExtraAssumeCapacity(Air.Block{
3472 .body_len = @intCast(u32, inner_block.instructions.items.len),
3473 });
3474 sema.air_extra.appendSliceAssumeCapacity(inner_block.instructions.items);
3475 sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;
36553476
36563477 func.state = .success;
36573478 log.debug("set {s} to success", .{decl.name});
36583479
36593480 return Air{
36603481 .instructions = sema.air_instructions.toOwnedSlice(),
3661 .extra = sema.air_extra.toOwnedSlice(),
3662 .values = sema.air_values.toOwnedSlice(),
3663 .variables = sema.air_variables.toOwnedSlice(),
3482 .extra = sema.air_extra.toOwnedSlice(gpa),
3483 .values = sema.air_values.toOwnedSlice(gpa),
3484 .variables = sema.air_variables.toOwnedSlice(gpa),
36643485 };
36653486}
36663487
......@@ -3815,94 +3636,6 @@ pub fn analyzeExport(
38153636 de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export;
38163637 errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1);
38173638}
3818pub fn constInst(mod: *Module, arena: *Allocator, src: LazySrcLoc, typed_value: TypedValue) !*ir.Inst {
3819 _ = mod;
3820 const const_inst = try arena.create(ir.Inst.Constant);
3821 const_inst.* = .{
3822 .base = .{
3823 .tag = ir.Inst.Constant.base_tag,
3824 .ty = typed_value.ty,
3825 .src = src,
3826 },
3827 .val = typed_value.val,
3828 };
3829 return &const_inst.base;
3830}
3831
3832pub fn constType(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
3833 return mod.constInst(arena, src, .{
3834 .ty = Type.initTag(.type),
3835 .val = try ty.toValue(arena),
3836 });
3837}
3838
3839pub fn constVoid(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
3840 return mod.constInst(arena, src, .{
3841 .ty = Type.initTag(.void),
3842 .val = Value.initTag(.void_value),
3843 });
3844}
3845
3846pub fn constNoReturn(mod: *Module, arena: *Allocator, src: LazySrcLoc) !*ir.Inst {
3847 return mod.constInst(arena, src, .{
3848 .ty = Type.initTag(.noreturn),
3849 .val = Value.initTag(.unreachable_value),
3850 });
3851}
3852
3853pub fn constUndef(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type) !*ir.Inst {
3854 return mod.constInst(arena, src, .{
3855 .ty = ty,
3856 .val = Value.initTag(.undef),
3857 });
3858}
3859
3860pub fn constBool(mod: *Module, arena: *Allocator, src: LazySrcLoc, v: bool) !*ir.Inst {
3861 return mod.constInst(arena, src, .{
3862 .ty = Type.initTag(.bool),
3863 .val = ([2]Value{ Value.initTag(.bool_false), Value.initTag(.bool_true) })[@boolToInt(v)],
3864 });
3865}
3866
3867pub fn constIntUnsigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: u64) !*ir.Inst {
3868 return mod.constInst(arena, src, .{
3869 .ty = ty,
3870 .val = try Value.Tag.int_u64.create(arena, int),
3871 });
3872}
3873
3874pub fn constIntSigned(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, int: i64) !*ir.Inst {
3875 return mod.constInst(arena, src, .{
3876 .ty = ty,
3877 .val = try Value.Tag.int_i64.create(arena, int),
3878 });
3879}
3880
3881pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, big_int: BigIntConst) !*ir.Inst {
3882 if (big_int.positive) {
3883 if (big_int.to(u64)) |x| {
3884 return mod.constIntUnsigned(arena, src, ty, x);
3885 } else |err| switch (err) {
3886 error.NegativeIntoUnsigned => unreachable,
3887 error.TargetTooSmall => {}, // handled below
3888 }
3889 return mod.constInst(arena, src, .{
3890 .ty = ty,
3891 .val = try Value.Tag.int_big_positive.create(arena, big_int.limbs),
3892 });
3893 } else {
3894 if (big_int.to(i64)) |x| {
3895 return mod.constIntSigned(arena, src, ty, x);
3896 } else |err| switch (err) {
3897 error.NegativeIntoUnsigned => unreachable,
3898 error.TargetTooSmall => {}, // handled below
3899 }
3900 return mod.constInst(arena, src, .{
3901 .ty = ty,
3902 .val = try Value.Tag.int_big_negative.create(arena, big_int.limbs),
3903 });
3904 }
3905}
39063639
39073640pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void {
39083641 const scope_decl = scope.ownerDecl().?;
......@@ -4438,38 +4171,6 @@ pub fn errorUnionType(
44384171 });
44394172}
44404173
4441pub fn dumpInst(mod: *Module, scope: *Scope, inst: *ir.Inst) void {
4442 const zir_module = scope.namespace();
4443 const source = zir_module.getSource(mod) catch @panic("dumpInst failed to get source");
4444 const loc = std.zig.findLineColumn(source, inst.src);
4445 if (inst.tag == .constant) {
4446 std.debug.print("constant ty={} val={} src={s}:{d}:{d}\n", .{
4447 inst.ty,
4448 inst.castTag(.constant).?.val,
4449 zir_module.subFilePath(),
4450 loc.line + 1,
4451 loc.column + 1,
4452 });
4453 } else if (inst.deaths == 0) {
4454 std.debug.print("{s} ty={} src={s}:{d}:{d}\n", .{
4455 @tagName(inst.tag),
4456 inst.ty,
4457 zir_module.subFilePath(),
4458 loc.line + 1,
4459 loc.column + 1,
4460 });
4461 } else {
4462 std.debug.print("{s} ty={} deaths={b} src={s}:{d}:{d}\n", .{
4463 @tagName(inst.tag),
4464 inst.ty,
4465 inst.deaths,
4466 zir_module.subFilePath(),
4467 loc.line + 1,
4468 loc.column + 1,
4469 });
4470 }
4471}
4472
44734174pub fn getTarget(mod: Module) Target {
44744175 return mod.comp.bin_file.options.target;
44754176}
src/Sema.zig+107-7
......@@ -12,9 +12,9 @@ gpa: *Allocator,
1212arena: *Allocator,
1313code: Zir,
1414air_instructions: std.MultiArrayList(Air.Inst) = .{},
15air_extra: ArrayListUnmanaged(u32) = .{},
16air_values: ArrayListUnmanaged(Value) = .{},
17air_variables: ArrayListUnmanaged(Module.Var) = .{},
15air_extra: std.ArrayListUnmanaged(u32) = .{},
16air_values: std.ArrayListUnmanaged(Value) = .{},
17air_variables: std.ArrayListUnmanaged(*Module.Var) = .{},
1818/// Maps ZIR to AIR.
1919inst_map: InstMap = .{},
2020/// When analyzing an inline function call, owner_decl is the Decl of the caller
......@@ -1263,15 +1263,16 @@ fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air
12631263 sema.next_arg_index += 1;
12641264
12651265 // TODO check if arg_name shadows a Decl
1266 _ = arg_name;
12661267
12671268 if (block.inlining) |_| {
12681269 return sema.param_inst_list[arg_index];
12691270 }
12701271
1271 // Need to set the name of the Air.Arg instruction.
1272 const air_arg = sema.param_inst_list[arg_index].castTag(.arg).?;
1273 air_arg.name = arg_name;
1274 return &air_arg.base;
1272 // Set the name of the Air.Arg instruction for use by codegen debug info.
1273 const air_arg = sema.param_inst_list[arg_index];
1274 sema.air.instructions.items(.data)[air_arg].ty_str.str = inst_data.start;
1275 return air_arg;
12751276}
12761277
12771278fn zirAllocExtended(
......@@ -7940,3 +7941,102 @@ fn enumFieldSrcLoc(
79407941 }
79417942 } else unreachable;
79427943}
7944
7945pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
7946 switch (ty.tag()) {
7947 .u8 => return .u8_type,
7948 .i8 => return .i8_type,
7949 .u16 => return .u16_type,
7950 .i16 => return .i16_type,
7951 .u32 => return .u32_type,
7952 .i32 => return .i32_type,
7953 .u64 => return .u64_type,
7954 .i64 => return .i64_type,
7955 .u128 => return .u128_type,
7956 .i128 => return .i128_type,
7957 .usize => return .usize_type,
7958 .isize => return .isize_type,
7959 .c_short => return .c_short_type,
7960 .c_ushort => return .c_ushort_type,
7961 .c_int => return .c_int_type,
7962 .c_uint => return .c_uint_type,
7963 .c_long => return .c_long_type,
7964 .c_ulong => return .c_ulong_type,
7965 .c_longlong => return .c_longlong_type,
7966 .c_ulonglong => return .c_ulonglong_type,
7967 .c_longdouble => return .c_longdouble_type,
7968 .f16 => return .f16_type,
7969 .f32 => return .f32_type,
7970 .f64 => return .f64_type,
7971 .f128 => return .f128_type,
7972 .c_void => return .c_void_type,
7973 .bool => return .bool_type,
7974 .void => return .void_type,
7975 .type => return .type_type,
7976 .anyerror => return .anyerror_type,
7977 .comptime_int => return .comptime_int_type,
7978 .comptime_float => return .comptime_float_type,
7979 .noreturn => return .noreturn_type,
7980 .@"anyframe" => return .anyframe_type,
7981 .@"null" => return .null_type,
7982 .@"undefined" => return .undefined_type,
7983 .enum_literal => return .enum_literal_type,
7984 .atomic_ordering => return .atomic_ordering_type,
7985 .atomic_rmw_op => return .atomic_rmw_op_type,
7986 .calling_convention => return .calling_convention_type,
7987 .float_mode => return .float_mode_type,
7988 .reduce_op => return .reduce_op_type,
7989 .call_options => return .call_options_type,
7990 .export_options => return .export_options_type,
7991 .extern_options => return .extern_options_type,
7992 .manyptr_u8 => return .manyptr_u8_type,
7993 .manyptr_const_u8 => return .manyptr_const_u8_type,
7994 .fn_noreturn_no_args => return .fn_noreturn_no_args_type,
7995 .fn_void_no_args => return .fn_void_no_args_type,
7996 .fn_naked_noreturn_no_args => return .fn_naked_noreturn_no_args_type,
7997 .fn_ccc_void_no_args => return .fn_ccc_void_no_args_type,
7998 .single_const_pointer_to_comptime_int => return .single_const_pointer_to_comptime_int_type,
7999 .const_slice_u8 => return .const_slice_u8_type,
8000 else => {},
8001 }
8002 try sema.air_instructions.append(sema.gpa, .{
8003 .tag = .const_ty,
8004 .data = .{ .ty = ty },
8005 });
8006 return indexToRef(@intCast(u32, sema.air_instructions.len - 1));
8007}
8008
8009const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len;
8010
8011fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {
8012 return @intToEnum(Air.Inst.Ref, ref_start_index + inst);
8013}
8014
8015fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
8016 const ref_int = @enumToInt(inst);
8017 if (ref_int >= ref_start_index) {
8018 return ref_int - ref_start_index;
8019 } else {
8020 return null;
8021 }
8022}
8023
8024pub fn addExtra(sema: *Sema, extra: anytype) Allocator.Error!u32 {
8025 const fields = std.meta.fields(@TypeOf(extra));
8026 try sema.air_extra.ensureUnusedCapacity(sema.gpa, fields.len);
8027 return addExtraAssumeCapacity(sema, extra);
8028}
8029
8030pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 {
8031 const fields = std.meta.fields(@TypeOf(extra));
8032 const result = @intCast(u32, sema.air_extra.items.len);
8033 inline for (fields) |field| {
8034 sema.air_extra.appendAssumeCapacity(switch (field.field_type) {
8035 u32 => @field(extra, field.name),
8036 Air.Inst.Ref => @enumToInt(@field(extra, field.name)),
8037 i32 => @bitCast(u32, @field(extra, field.name)),
8038 else => @compileError("bad field type"),
8039 });
8040 }
8041 return result;
8042}
src/codegen.zig+110-86
......@@ -3,6 +3,7 @@ const mem = std.mem;
33const math = std.math;
44const assert = std.debug.assert;
55const Air = @import("Air.zig");
6const Liveness = @import("Liveness.zig");
67const Type = @import("type.zig").Type;
78const Value = @import("value.zig").Value;
89const TypedValue = @import("TypedValue.zig");
......@@ -45,6 +46,71 @@ pub const DebugInfoOutput = union(enum) {
4546 none,
4647};
4748
49pub fn generateFunction(
50 bin_file: *link.File,
51 src_loc: Module.SrcLoc,
52 func: *Module.Fn,
53 air: Air,
54 liveness: Liveness,
55 code: *std.ArrayList(u8),
56 debug_output: DebugInfoOutput,
57) GenerateSymbolError!Result {
58 switch (bin_file.options.target.cpu.arch) {
59 .wasm32 => unreachable, // has its own code path
60 .wasm64 => unreachable, // has its own code path
61 .arm => return Function(.arm).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
62 .armeb => return Function(.armeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
63 .aarch64 => return Function(.aarch64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
64 .aarch64_be => return Function(.aarch64_be).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
65 .aarch64_32 => return Function(.aarch64_32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
66 //.arc => return Function(.arc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
67 //.avr => return Function(.avr).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
68 //.bpfel => return Function(.bpfel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
69 //.bpfeb => return Function(.bpfeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
70 //.hexagon => return Function(.hexagon).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
71 //.mips => return Function(.mips).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
72 //.mipsel => return Function(.mipsel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
73 //.mips64 => return Function(.mips64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
74 //.mips64el => return Function(.mips64el).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
75 //.msp430 => return Function(.msp430).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
76 //.powerpc => return Function(.powerpc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
77 //.powerpc64 => return Function(.powerpc64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
78 //.powerpc64le => return Function(.powerpc64le).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
79 //.r600 => return Function(.r600).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
80 //.amdgcn => return Function(.amdgcn).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
81 //.riscv32 => return Function(.riscv32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
82 .riscv64 => return Function(.riscv64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
83 //.sparc => return Function(.sparc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
84 //.sparcv9 => return Function(.sparcv9).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
85 //.sparcel => return Function(.sparcel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
86 //.s390x => return Function(.s390x).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
87 //.tce => return Function(.tce).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
88 //.tcele => return Function(.tcele).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
89 //.thumb => return Function(.thumb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
90 //.thumbeb => return Function(.thumbeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
91 //.i386 => return Function(.i386).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
92 .x86_64 => return Function(.x86_64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
93 //.xcore => return Function(.xcore).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
94 //.nvptx => return Function(.nvptx).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
95 //.nvptx64 => return Function(.nvptx64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
96 //.le32 => return Function(.le32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
97 //.le64 => return Function(.le64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
98 //.amdil => return Function(.amdil).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
99 //.amdil64 => return Function(.amdil64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
100 //.hsail => return Function(.hsail).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
101 //.hsail64 => return Function(.hsail64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
102 //.spir => return Function(.spir).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
103 //.spir64 => return Function(.spir64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
104 //.kalimba => return Function(.kalimba).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
105 //.shave => return Function(.shave).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
106 //.lanai => return Function(.lanai).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
107 //.renderscript32 => return Function(.renderscript32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
108 //.renderscript64 => return Function(.renderscript64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
109 //.ve => return Function(.ve).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
110 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
111 }
112}
113
48114pub fn generateSymbol(
49115 bin_file: *link.File,
50116 src_loc: Module.SrcLoc,
......@@ -57,60 +123,14 @@ pub fn generateSymbol(
57123
58124 switch (typed_value.ty.zigTypeTag()) {
59125 .Fn => {
60 switch (bin_file.options.target.cpu.arch) {
61 .wasm32 => unreachable, // has its own code path
62 .wasm64 => unreachable, // has its own code path
63 .arm => return Function(.arm).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
64 .armeb => return Function(.armeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
65 .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
66 .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
67 .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
68 //.arc => return Function(.arc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
69 //.avr => return Function(.avr).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
70 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
71 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
72 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
73 //.mips => return Function(.mips).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
74 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
75 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
76 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
77 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
78 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
79 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
80 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
81 //.r600 => return Function(.r600).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
82 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
83 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
84 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
85 //.sparc => return Function(.sparc).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
86 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
87 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
88 //.s390x => return Function(.s390x).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
89 //.tce => return Function(.tce).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
90 //.tcele => return Function(.tcele).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
91 //.thumb => return Function(.thumb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
92 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
93 //.i386 => return Function(.i386).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
94 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
95 //.xcore => return Function(.xcore).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
96 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
97 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
98 //.le32 => return Function(.le32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
99 //.le64 => return Function(.le64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
100 //.amdil => return Function(.amdil).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
101 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
102 //.hsail => return Function(.hsail).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
103 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
104 //.spir => return Function(.spir).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
105 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
106 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
107 //.shave => return Function(.shave).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
108 //.lanai => return Function(.lanai).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
109 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
110 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
111 //.ve => return Function(.ve).generateSymbol(bin_file, src_loc, typed_value, code, debug_output),
112 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
113 }
126 return Result{
127 .fail = try ErrorMsg.create(
128 bin_file.allocator,
129 src_loc,
130 "TODO implement generateSymbol function pointers",
131 .{},
132 ),
133 };
114134 },
115135 .Array => {
116136 // TODO populate .debug_info for the array
......@@ -262,6 +282,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
262282
263283 return struct {
264284 gpa: *Allocator,
285 air: *const Air,
265286 bin_file: *link.File,
266287 target: *const std.Target,
267288 mod_fn: *const Module.Fn,
......@@ -421,10 +442,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
421442
422443 const Self = @This();
423444
424 fn generateSymbol(
445 fn generate(
425446 bin_file: *link.File,
426447 src_loc: Module.SrcLoc,
427 typed_value: TypedValue,
448 module_fn: *Module.Fn,
449 air: Air,
450 liveness: Liveness,
428451 code: *std.ArrayList(u8),
429452 debug_output: DebugInfoOutput,
430453 ) GenerateSymbolError!Result {
......@@ -432,8 +455,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
432455 @panic("Attempted to compile for architecture that was disabled by build configuration");
433456 }
434457
435 const module_fn = typed_value.val.castTag(.function).?.data;
436
437458 assert(module_fn.owner_decl.has_tv);
438459 const fn_type = module_fn.owner_decl.ty;
439460
......@@ -447,6 +468,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
447468
448469 var function = Self{
449470 .gpa = bin_file.allocator,
471 .air = &air,
472 .liveness = &liveness,
450473 .target = &bin_file.options.target,
451474 .bin_file = bin_file,
452475 .mod_fn = module_fn,
......@@ -2131,8 +2154,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
21312154 }
21322155
21332156 fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void {
2134 const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1];
2135 const ty = self.air.getType(inst);
2157 const ty_str = self.air.instruction.items(.data)[inst].ty_str;
2158 const zir = &self.mod_fn.owner_decl.namespace.file_scope.zir;
2159 const name = zir.nullTerminatedString(ty_str.str);
2160 const name_with_null = name.ptr[0 .. name.len + 1];
2161 const ty = self.air.getRefType(ty_str.ty);
21362162
21372163 switch (mcv) {
21382164 .register => |reg| {
......@@ -2249,8 +2275,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
22492275 }
22502276
22512277 fn genCall(self: *Self, inst: Air.Inst.Index) !MCValue {
2252 const inst_datas = self.air.instructions.items(.data);
2253 const pl_op = inst_datas[inst].pl_op;
2278 const pl_op = self.air.instruction.items(.data)[inst].pl_op;
22542279 const fn_ty = self.air.getType(pl_op.operand);
22552280 const callee = pl_op.operand;
22562281 const extra = self.air.extraData(Air.Call, inst_data.payload);
......@@ -2848,8 +2873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
28482873 }
28492874
28502875 fn genCondBr(self: *Self, inst: Air.Inst.Index) !MCValue {
2851 const inst_datas = self.air.instructions.items(.data);
2852 const pl_op = inst_datas[inst].pl_op;
2876 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
28532877 const cond = try self.resolveInst(pl_op.operand);
28542878 const extra = self.air.extraData(Air.CondBr, inst_data.payload);
28552879 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
......@@ -3101,16 +3125,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
31013125 fn genIsNull(self: *Self, inst: Air.Inst.Index) !MCValue {
31023126 if (self.liveness.isUnused(inst))
31033127 return MCValue.dead;
3104 const inst_datas = self.air.instructions.items(.data);
3105 const operand = try self.resolveInst(inst_datas[inst].un_op);
3128 const un_op = self.air.instructions.items(.data)[inst].un_op;
3129 const operand = try self.resolveInst(un_op);
31063130 return self.isNull(operand);
31073131 }
31083132
31093133 fn genIsNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue {
31103134 if (self.liveness.isUnused(inst))
31113135 return MCValue.dead;
3112 const inst_datas = self.air.instructions.items(.data);
3113 const operand_ptr = try self.resolveInst(inst_datas[inst].un_op);
3136 const un_op = self.air.instructions.items(.data)[inst].un_op;
3137 const operand_ptr = try self.resolveInst(un_op);
31143138 const operand: MCValue = blk: {
31153139 if (self.reuseOperand(inst, 0, operand_ptr)) {
31163140 // The MCValue that holds the pointer can be re-used as the value.
......@@ -3126,16 +3150,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
31263150 fn genIsNonNull(self: *Self, inst: Air.Inst.Index) !MCValue {
31273151 if (self.liveness.isUnused(inst))
31283152 return MCValue.dead;
3129 const inst_datas = self.air.instructions.items(.data);
3130 const operand = try self.resolveInst(inst_datas[inst].un_op);
3153 const un_op = self.air.instructions.items(.data)[inst].un_op;
3154 const operand = try self.resolveInst(un_op);
31313155 return self.isNonNull(operand);
31323156 }
31333157
31343158 fn genIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue {
31353159 if (self.liveness.isUnused(inst))
31363160 return MCValue.dead;
3137 const inst_datas = self.air.instructions.items(.data);
3138 const operand_ptr = try self.resolveInst(inst_datas[inst].un_op);
3161 const un_op = self.air.instructions.items(.data)[inst].un_op;
3162 const operand_ptr = try self.resolveInst(un_op);
31393163 const operand: MCValue = blk: {
31403164 if (self.reuseOperand(inst, 0, operand_ptr)) {
31413165 // The MCValue that holds the pointer can be re-used as the value.
......@@ -3151,16 +3175,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
31513175 fn genIsErr(self: *Self, inst: Air.Inst.Index) !MCValue {
31523176 if (self.liveness.isUnused(inst))
31533177 return MCValue.dead;
3154 const inst_datas = self.air.instructions.items(.data);
3155 const operand = try self.resolveInst(inst_datas[inst].un_op);
3178 const un_op = self.air.instructions.items(.data)[inst].un_op;
3179 const operand = try self.resolveInst(un_op);
31563180 return self.isErr(operand);
31573181 }
31583182
31593183 fn genIsErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue {
31603184 if (self.liveness.isUnused(inst))
31613185 return MCValue.dead;
3162 const inst_datas = self.air.instructions.items(.data);
3163 const operand_ptr = try self.resolveInst(inst_datas[inst].un_op);
3186 const un_op = self.air.instructions.items(.data)[inst].un_op;
3187 const operand_ptr = try self.resolveInst(un_op);
31643188 const operand: MCValue = blk: {
31653189 if (self.reuseOperand(inst, 0, operand_ptr)) {
31663190 // The MCValue that holds the pointer can be re-used as the value.
......@@ -3176,16 +3200,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
31763200 fn genIsNonErr(self: *Self, inst: Air.Inst.Index) !MCValue {
31773201 if (self.liveness.isUnused(inst))
31783202 return MCValue.dead;
3179 const inst_datas = self.air.instructions.items(.data);
3180 const operand = try self.resolveInst(inst_datas[inst].un_op);
3203 const un_op = self.air.instructions.items(.data)[inst].un_op;
3204 const operand = try self.resolveInst(un_op);
31813205 return self.isNonErr(operand);
31823206 }
31833207
31843208 fn genIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue {
31853209 if (self.liveness.isUnused(inst))
31863210 return MCValue.dead;
3187 const inst_datas = self.air.instructions.items(.data);
3188 const operand_ptr = try self.resolveInst(inst_datas[inst].un_op);
3211 const un_op = self.air.instructions.items(.data)[inst].un_op;
3212 const operand_ptr = try self.resolveInst(un_op);
31893213 const operand: MCValue = blk: {
31903214 if (self.reuseOperand(inst, 0, operand_ptr)) {
31913215 // The MCValue that holds the pointer can be re-used as the value.
......@@ -3200,8 +3224,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
32003224
32013225 fn genLoop(self: *Self, inst: Air.Inst.Index) !MCValue {
32023226 // A loop is a setup to be able to jump back to the beginning.
3203 const inst_datas = self.air.instructions.items(.data);
3204 const loop = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload);
3227 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3228 const loop = self.air.extraData(Air.Block, ty_pl.payload);
32053229 const body = self.air.extra[loop.end..][0..loop.data.body_len];
32063230 const start_index = self.code.items.len;
32073231 try self.genBody(body);
......@@ -4377,13 +4401,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
43774401 }
43784402
43794403 fn genPtrToInt(self: *Self, inst: Air.Inst.Index) !MCValue {
4380 const inst_datas = self.air.instructions.items(.data);
4381 return self.resolveInst(inst_datas[inst].un_op);
4404 const un_op = self.air.instructions.items(.data)[inst].un_op;
4405 return self.resolveInst(un_op);
43824406 }
43834407
43844408 fn genBitCast(self: *Self, inst: Air.Inst.Index) !MCValue {
4385 const inst_datas = self.air.instructions.items(.data);
4386 return self.resolveInst(inst_datas[inst].ty_op.operand);
4409 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
4410 return self.resolveInst(ty_op.operand);
43874411 }
43884412
43894413 fn resolveInst(self: *Self, inst: Air.Inst.Index) !MCValue {
src/codegen/spirv.zig+35-22
......@@ -159,7 +159,10 @@ pub const DeclGen = struct {
159159 /// The SPIR-V module code should be put in.
160160 spv: *SPIRVModule,
161161
162 /// An array of function argument result-ids. Each index corresponds with the function argument of the same index.
162 air: *const Air,
163
164 /// An array of function argument result-ids. Each index corresponds with the
165 /// function argument of the same index.
163166 args: std.ArrayList(ResultId),
164167
165168 /// A counter to keep track of how many `arg` instructions we've seen yet.
......@@ -168,33 +171,35 @@ pub const DeclGen = struct {
168171 /// A map keeping track of which instruction generated which result-id.
169172 inst_results: InstMap,
170173
171 /// We need to keep track of result ids for block labels, as well as the 'incoming' blocks for a block.
174 /// We need to keep track of result ids for block labels, as well as the 'incoming'
175 /// blocks for a block.
172176 blocks: BlockMap,
173177
174178 /// The label of the SPIR-V block we are currently generating.
175179 current_block_label_id: ResultId,
176180
177 /// The actual instructions for this function. We need to declare all locals in the first block, and because we don't
178 /// know which locals there are going to be, we're just going to generate everything after the locals-section in this array.
179 /// Note: It will not contain OpFunction, OpFunctionParameter, OpVariable and the initial OpLabel. These will be generated
180 /// into spv.binary.fn_decls directly.
181 /// The actual instructions for this function. We need to declare all locals in
182 /// the first block, and because we don't know which locals there are going to be,
183 /// we're just going to generate everything after the locals-section in this array.
184 /// Note: It will not contain OpFunction, OpFunctionParameter, OpVariable and the
185 /// initial OpLabel. These will be generated into spv.binary.fn_decls directly.
181186 code: std.ArrayList(Word),
182187
183188 /// The decl we are currently generating code for.
184189 decl: *Decl,
185190
186 /// If `gen` returned `Error.AnalysisFail`, this contains an explanatory message. Memory is owned by
187 /// `module.gpa`.
191 /// If `gen` returned `Error.AnalysisFail`, this contains an explanatory message.
192 /// Memory is owned by `module.gpa`.
188193 error_msg: ?*Module.ErrorMsg,
189194
190195 /// Possible errors the `gen` function may return.
191196 const Error = error{ AnalysisFail, OutOfMemory };
192197
193 /// This structure is used to return information about a type typically used for arithmetic operations.
194 /// These types may either be integers, floats, or a vector of these. Most scalar operations also work on vectors,
195 /// so we can easily represent those as arithmetic types.
196 /// If the type is a scalar, 'inner type' refers to the scalar type. Otherwise, if its a vector, it refers
197 /// to the vector's element type.
198 /// This structure is used to return information about a type typically used for
199 /// arithmetic operations. These types may either be integers, floats, or a vector
200 /// of these. Most scalar operations also work on vectors, so we can easily represent
201 /// those as arithmetic types. If the type is a scalar, 'inner type' refers to the
202 /// scalar type. Otherwise, if its a vector, it refers to the vector's element type.
198203 const ArithmeticTypeInfo = struct {
199204 /// A classification of the inner type.
200205 const Class = enum {
......@@ -206,13 +211,14 @@ pub const DeclGen = struct {
206211 /// the relevant capability is enabled).
207212 integer,
208213
209 /// A regular float. These are all required to be natively supported. Floating points for
210 /// which the relevant capability is not enabled are not emulated.
214 /// A regular float. These are all required to be natively supported. Floating points
215 /// for which the relevant capability is not enabled are not emulated.
211216 float,
212217
213 /// An integer of a 'strange' size (which' bit size is not the same as its backing type. **Note**: this
214 /// may **also** include power-of-2 integers for which the relevant capability is not enabled), but still
215 /// within the limits of the largest natively supported integer type.
218 /// An integer of a 'strange' size (which' bit size is not the same as its backing
219 /// type. **Note**: this may **also** include power-of-2 integers for which the
220 /// relevant capability is not enabled), but still within the limits of the largest
221 /// natively supported integer type.
216222 strange_integer,
217223
218224 /// An integer with more bits than the largest natively supported integer type.
......@@ -220,7 +226,7 @@ pub const DeclGen = struct {
220226 };
221227
222228 /// The number of bits in the inner type.
223 /// Note: this is the actual number of bits of the type, not the size of the backing integer.
229 /// This is the actual number of bits of the type, not the size of the backing integer.
224230 bits: u16,
225231
226232 /// Whether the type is a vector.
......@@ -234,10 +240,12 @@ pub const DeclGen = struct {
234240 class: Class,
235241 };
236242
237 /// Initialize the common resources of a DeclGen. Some fields are left uninitialized, only set when `gen` is called.
243 /// Initialize the common resources of a DeclGen. Some fields are left uninitialized,
244 /// only set when `gen` is called.
238245 pub fn init(spv: *SPIRVModule) DeclGen {
239246 return .{
240247 .spv = spv,
248 .air = undefined,
241249 .args = std.ArrayList(ResultId).init(spv.gpa),
242250 .next_arg_index = undefined,
243251 .inst_results = InstMap.init(spv.gpa),
......@@ -252,8 +260,9 @@ pub const DeclGen = struct {
252260 /// Generate the code for `decl`. If a reportable error occured during code generation,
253261 /// a message is returned by this function. Callee owns the memory. If this function returns such
254262 /// a reportable error, it is valid to be called again for a different decl.
255 pub fn gen(self: *DeclGen, decl: *Decl) !?*Module.ErrorMsg {
263 pub fn gen(self: *DeclGen, decl: *Decl, air: Air) !?*Module.ErrorMsg {
256264 // Reset internal resources, we don't want to re-allocate these.
265 self.air = &air;
257266 self.args.items.len = 0;
258267 self.next_arg_index = 0;
259268 self.inst_results.clearRetainingCapacity();
......@@ -680,7 +689,7 @@ pub const DeclGen = struct {
680689
681690 .br => return self.genBr(inst),
682691 .breakpoint => return,
683 .condbr => return self.genCondBr(inst),
692 .cond_br => return self.genCondBr(inst),
684693 .constant => unreachable,
685694 .dbg_stmt => return self.genDbgStmt(inst),
686695 .loop => return self.genLoop(inst),
......@@ -688,6 +697,10 @@ pub const DeclGen = struct {
688697 .store => return self.genStore(inst),
689698 .unreach => return self.genUnreach(),
690699 // zig fmt: on
700
701 else => |tag| return self.fail("TODO: SPIR-V backend: implement AIR tag {s}", .{
702 @tagName(tag),
703 }),
691704 };
692705
693706 try self.inst_results.putNoClobber(inst, result_id);
src/link/SpirV.zig+4
......@@ -135,6 +135,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
135135 const tracy = trace(@src());
136136 defer tracy.end();
137137
138 if (build_options.skip_non_native) {
139 @panic("Attempted to compile for architecture that was disabled by build configuration");
140 }
141
138142 const module = self.base.options.module.?;
139143 const target = comp.getTarget();
140144
src/register_manager.zig+8-8
......@@ -20,7 +20,7 @@ pub fn RegisterManager(
2020) type {
2121 return struct {
2222 /// The key must be canonical register.
23 registers: [callee_preserved_regs.len]?*ir.Inst = [_]?*ir.Inst{null} ** callee_preserved_regs.len,
23 registers: [callee_preserved_regs.len]?Air.Inst.Index = [_]?Air.Inst.Index{null} ** callee_preserved_regs.len,
2424 free_registers: FreeRegInt = math.maxInt(FreeRegInt),
2525 /// Tracks all registers allocated in the course of this function
2626 allocated_registers: FreeRegInt = 0,
......@@ -75,7 +75,7 @@ pub fn RegisterManager(
7575 pub fn tryAllocRegs(
7676 self: *Self,
7777 comptime count: comptime_int,
78 insts: [count]?*ir.Inst,
78 insts: [count]?Air.Inst.Index,
7979 exceptions: []const Register,
8080 ) ?[count]Register {
8181 comptime if (callee_preserved_regs.len == 0) return null;
......@@ -113,7 +113,7 @@ pub fn RegisterManager(
113113 /// Allocates a register and optionally tracks it with a
114114 /// corresponding instruction. Returns `null` if all registers
115115 /// are allocated.
116 pub fn tryAllocReg(self: *Self, inst: ?*ir.Inst, exceptions: []const Register) ?Register {
116 pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, exceptions: []const Register) ?Register {
117117 return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null;
118118 }
119119
......@@ -123,7 +123,7 @@ pub fn RegisterManager(
123123 pub fn allocRegs(
124124 self: *Self,
125125 comptime count: comptime_int,
126 insts: [count]?*ir.Inst,
126 insts: [count]?Air.Inst.Index,
127127 exceptions: []const Register,
128128 ) ![count]Register {
129129 comptime assert(count > 0 and count <= callee_preserved_regs.len);
......@@ -168,14 +168,14 @@ pub fn RegisterManager(
168168
169169 /// Allocates a register and optionally tracks it with a
170170 /// corresponding instruction.
171 pub fn allocReg(self: *Self, inst: ?*ir.Inst, exceptions: []const Register) !Register {
171 pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, exceptions: []const Register) !Register {
172172 return (try self.allocRegs(1, .{inst}, exceptions))[0];
173173 }
174174
175175 /// Spills the register if it is currently allocated. If a
176176 /// corresponding instruction is passed, will also track this
177177 /// register.
178 pub fn getReg(self: *Self, reg: Register, inst: ?*ir.Inst) !void {
178 pub fn getReg(self: *Self, reg: Register, inst: ?Air.Inst.Index) !void {
179179 const index = reg.allocIndex() orelse return;
180180
181181 if (inst) |tracked_inst|
......@@ -202,7 +202,7 @@ pub fn RegisterManager(
202202 /// Allocates the specified register with the specified
203203 /// instruction. Asserts that the register is free and no
204204 /// spilling is necessary.
205 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: *ir.Inst) void {
205 pub fn getRegAssumeFree(self: *Self, reg: Register, inst: Air.Inst.Index) void {
206206 const index = reg.allocIndex() orelse return;
207207
208208 assert(self.registers[index] == null);
......@@ -264,7 +264,7 @@ fn MockFunction(comptime Register: type) type {
264264 self.spilled.deinit(self.allocator);
265265 }
266266
267 pub fn spillInstruction(self: *Self, reg: Register, inst: *ir.Inst) !void {
267 pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
268268 _ = inst;
269269 try self.spilled.append(self.allocator, reg);
270270 }