| author | |
| committer | |
| log | 913393fd3b986dd262a8419341dced9ad5d9620d |
| tree | 24206439ed1abe1e7ca09a0f164d79981ea4eb2b |
| parent | ee6432537ee29485c5de6c8b0911ef1482d752a7 |
9 files changed, 429 insertions(+), 455 deletions(-)
BRANCH_TODO+122| ... | @@ -568,3 +568,125 @@ const DumpAir = struct { | ... | @@ -568,3 +568,125 @@ const DumpAir = struct { |
| 568 | } | 568 | } |
| 569 | } | 569 | } |
| 570 | }; | 570 | }; |
| 571 | |||
| 572 | pub 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 | |||
| 586 | pub 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 | |||
| 593 | pub 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 | |||
| 600 | pub 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 | |||
| 607 | pub 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 | |||
| 614 | pub 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 | |||
| 621 | pub 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 | |||
| 628 | pub 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 | |||
| 635 | pub 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 | |||
| 661 | pub 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 { | ... | @@ -29,8 +29,11 @@ pub const Inst = struct { |
| 29 | data: Data, | 29 | data: Data, |
| 30 | 30 | ||
| 31 | pub const Tag = enum(u8) { | 31 | pub const Tag = enum(u8) { |
| 32 | /// The first N instructions in Air must be one arg instruction per function parameter. | 32 | /// The first N instructions in the main block must be one arg instruction per |
| 33 | /// Uses the `ty` field. | 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. | ||
| 34 | arg, | 37 | arg, |
| 35 | /// Float or integer addition. For integers, wrapping is undefined behavior. | 38 | /// Float or integer addition. For integers, wrapping is undefined behavior. |
| 36 | /// Both operands are guaranteed to be the same type, and the result type | 39 | /// Both operands are guaranteed to be the same type, and the result type |
| ... | @@ -131,6 +134,8 @@ pub const Inst = struct { | ... | @@ -131,6 +134,8 @@ pub const Inst = struct { |
| 131 | /// A comptime-known value. Uses the `ty_pl` field, payload is index of | 134 | /// A comptime-known value. Uses the `ty_pl` field, payload is index of |
| 132 | /// `values` array. | 135 | /// `values` array. |
| 133 | constant, | 136 | constant, |
| 137 | /// A comptime-known type. Uses the `ty` field. | ||
| 138 | const_ty, | ||
| 134 | /// Notes the beginning of a source code statement and marks the line and column. | 139 | /// Notes the beginning of a source code statement and marks the line and column. |
| 135 | /// Result type is always void. | 140 | /// Result type is always void. |
| 136 | /// Uses the `dbg_stmt` field. | 141 | /// Uses the `dbg_stmt` field. |
| ... | @@ -289,6 +294,11 @@ pub const Inst = struct { | ... | @@ -289,6 +294,11 @@ pub const Inst = struct { |
| 289 | // Index into a different array. | 294 | // Index into a different array. |
| 290 | payload: u32, | 295 | payload: u32, |
| 291 | }, | 296 | }, |
| 297 | ty_str: struct { | ||
| 298 | ty: Ref, | ||
| 299 | // ZIR string table index. | ||
| 300 | str: u32, | ||
| 301 | }, | ||
| 292 | br: struct { | 302 | br: struct { |
| 293 | block_inst: Index, | 303 | block_inst: Index, |
| 294 | operand: Ref, | 304 | operand: Ref, |
src/AstGen.zig+1-1| ... | @@ -9821,7 +9821,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { | ... | @@ -9821,7 +9821,7 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 9821 | astgen.source_column = column; | 9821 | astgen.source_column = column; |
| 9822 | } | 9822 | } |
| 9823 | 9823 | ||
| 9824 | const ref_start_index = Zir.Inst.Ref.typed_value_map.len; | 9824 | const ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len; |
| 9825 | 9825 | ||
| 9826 | fn indexToRef(inst: Zir.Inst.Index) Zir.Inst.Ref { | 9826 | fn indexToRef(inst: Zir.Inst.Index) Zir.Inst.Ref { |
| 9827 | return @intToEnum(Zir.Inst.Ref, ref_start_index + inst); | 9827 | return @intToEnum(Zir.Inst.Ref, ref_start_index + inst); |
src/Module.zig+30-329| ... | @@ -1155,7 +1155,7 @@ pub const Scope = struct { | ... | @@ -1155,7 +1155,7 @@ pub const Scope = struct { |
| 1155 | /// This can vary during inline or comptime function calls. See `Sema.owner_decl` | 1155 | /// This can vary during inline or comptime function calls. See `Sema.owner_decl` |
| 1156 | /// for the one that will be the same for all Block instances. | 1156 | /// for the one that will be the same for all Block instances. |
| 1157 | src_decl: *Decl, | 1157 | src_decl: *Decl, |
| 1158 | instructions: ArrayListUnmanaged(*ir.Inst), | 1158 | instructions: ArrayListUnmanaged(Air.Inst.Index), |
| 1159 | label: ?*Label = null, | 1159 | label: ?*Label = null, |
| 1160 | inlining: ?*Inlining, | 1160 | inlining: ?*Inlining, |
| 1161 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. | 1161 | /// If runtime_index is not 0 then one of these is guaranteed to be non null. |
| ... | @@ -1187,14 +1187,14 @@ pub const Scope = struct { | ... | @@ -1187,14 +1187,14 @@ pub const Scope = struct { |
| 1187 | }; | 1187 | }; |
| 1188 | 1188 | ||
| 1189 | pub const Merges = struct { | 1189 | pub const Merges = struct { |
| 1190 | block_inst: *ir.Inst.Block, | 1190 | block_inst: Air.Inst.Index, |
| 1191 | /// Separate array list from break_inst_list so that it can be passed directly | 1191 | /// Separate array list from break_inst_list so that it can be passed directly |
| 1192 | /// to resolvePeerTypes. | 1192 | /// to resolvePeerTypes. |
| 1193 | results: ArrayListUnmanaged(*ir.Inst), | 1193 | results: ArrayListUnmanaged(Air.Inst.Index), |
| 1194 | /// Keeps track of the break instructions so that the operand can be replaced | 1194 | /// Keeps track of the break instructions so that the operand can be replaced |
| 1195 | /// if we need to add type coercion at the end of block analysis. | 1195 | /// if we need to add type coercion at the end of block analysis. |
| 1196 | /// Same indexes, capacity, length as `results`. | 1196 | /// Same indexes, capacity, length as `results`. |
| 1197 | br_list: ArrayListUnmanaged(*ir.Inst.Br), | 1197 | br_list: ArrayListUnmanaged(Air.Inst.Index), |
| 1198 | }; | 1198 | }; |
| 1199 | 1199 | ||
| 1200 | /// For debugging purposes. | 1200 | /// For debugging purposes. |
| ... | @@ -1230,187 +1230,6 @@ pub const Scope = struct { | ... | @@ -1230,187 +1230,6 @@ pub const Scope = struct { |
| 1230 | pub fn getFileScope(block: *Block) *Scope.File { | 1230 | pub fn getFileScope(block: *Block) *Scope.File { |
| 1231 | return block.src_decl.namespace.file_scope; | 1231 | return block.src_decl.namespace.file_scope; |
| 1232 | } | 1232 | } |
| 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 | } | ||
| 1414 | }; | 1233 | }; |
| 1415 | }; | 1234 | }; |
| 1416 | 1235 | ||
| ... | @@ -3594,30 +3413,14 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { | ... | @@ -3594,30 +3413,14 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { |
| 3594 | defer decl.value_arena.?.* = arena.state; | 3413 | defer decl.value_arena.?.* = arena.state; |
| 3595 | 3414 | ||
| 3596 | const fn_ty = decl.ty; | 3415 | 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()); |
| 3598 | defer gpa.free(param_inst_list); | 3417 | defer gpa.free(param_inst_list); |
| 3599 | 3418 | ||
| 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 | |||
| 3616 | var sema: Sema = .{ | 3419 | var sema: Sema = .{ |
| 3617 | .mod = mod, | 3420 | .mod = mod, |
| 3618 | .gpa = gpa, | 3421 | .gpa = gpa, |
| 3619 | .arena = &arena.allocator, | 3422 | .arena = &arena.allocator, |
| 3620 | .code = zir, | 3423 | .code = decl.namespace.file_scope.zir, |
| 3621 | .owner_decl = decl, | 3424 | .owner_decl = decl, |
| 3622 | .namespace = decl.namespace, | 3425 | .namespace = decl.namespace, |
| 3623 | .func = func, | 3426 | .func = func, |
| ... | @@ -3641,7 +3444,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { | ... | @@ -3641,7 +3444,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { |
| 3641 | }; | 3444 | }; |
| 3642 | defer inner_block.instructions.deinit(gpa); | 3445 | defer inner_block.instructions.deinit(gpa); |
| 3643 | 3446 | ||
| 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 | } | ||
| 3645 | try inner_block.instructions.appendSlice(gpa, param_inst_list); | 3462 | try inner_block.instructions.appendSlice(gpa, param_inst_list); |
| 3646 | 3463 | ||
| 3647 | func.state = .in_progress; | 3464 | func.state = .in_progress; |
| ... | @@ -3650,17 +3467,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { | ... | @@ -3650,17 +3467,21 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn) !Air { |
| 3650 | try sema.analyzeFnBody(&inner_block, func.zir_body_inst); | 3467 | try sema.analyzeFnBody(&inner_block, func.zir_body_inst); |
| 3651 | 3468 | ||
| 3652 | // Copy the block into place and mark that as the main block. | 3469 | // 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; | 3470 | try sema.air_extra.ensureUnusedCapacity(gpa, inner_block.instructions.items.len + 1); |
| 3654 | try sema.air_extra.appendSlice(inner_block.instructions.items); | 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; | ||
| 3655 | 3476 | ||
| 3656 | func.state = .success; | 3477 | func.state = .success; |
| 3657 | log.debug("set {s} to success", .{decl.name}); | 3478 | log.debug("set {s} to success", .{decl.name}); |
| 3658 | 3479 | ||
| 3659 | return Air{ | 3480 | return Air{ |
| 3660 | .instructions = sema.air_instructions.toOwnedSlice(), | 3481 | .instructions = sema.air_instructions.toOwnedSlice(), |
| 3661 | .extra = sema.air_extra.toOwnedSlice(), | 3482 | .extra = sema.air_extra.toOwnedSlice(gpa), |
| 3662 | .values = sema.air_values.toOwnedSlice(), | 3483 | .values = sema.air_values.toOwnedSlice(gpa), |
| 3663 | .variables = sema.air_variables.toOwnedSlice(), | 3484 | .variables = sema.air_variables.toOwnedSlice(gpa), |
| 3664 | }; | 3485 | }; |
| 3665 | } | 3486 | } |
| 3666 | 3487 | ||
| ... | @@ -3815,94 +3636,6 @@ pub fn analyzeExport( | ... | @@ -3815,94 +3636,6 @@ pub fn analyzeExport( |
| 3815 | de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; | 3636 | de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; |
| 3816 | errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); | 3637 | errdefer de_gop.value_ptr.* = mod.gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); |
| 3817 | } | 3638 | } |
| 3818 | pub 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 | |||
| 3832 | pub 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 | |||
| 3839 | pub 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 | |||
| 3846 | pub 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 | |||
| 3853 | pub 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 | |||
| 3860 | pub 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 | |||
| 3867 | pub 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 | |||
| 3874 | pub 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 | |||
| 3881 | pub 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 | } | ||
| 3906 | 3639 | ||
| 3907 | pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void { | 3640 | pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void { |
| 3908 | const scope_decl = scope.ownerDecl().?; | 3641 | const scope_decl = scope.ownerDecl().?; |
| ... | @@ -4438,38 +4171,6 @@ pub fn errorUnionType( | ... | @@ -4438,38 +4171,6 @@ pub fn errorUnionType( |
| 4438 | }); | 4171 | }); |
| 4439 | } | 4172 | } |
| 4440 | 4173 | ||
| 4441 | pub 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 | |||
| 4473 | pub fn getTarget(mod: Module) Target { | 4174 | pub fn getTarget(mod: Module) Target { |
| 4474 | return mod.comp.bin_file.options.target; | 4175 | return mod.comp.bin_file.options.target; |
| 4475 | } | 4176 | } |
src/Sema.zig+107-7| ... | @@ -12,9 +12,9 @@ gpa: *Allocator, | ... | @@ -12,9 +12,9 @@ gpa: *Allocator, |
| 12 | arena: *Allocator, | 12 | arena: *Allocator, |
| 13 | code: Zir, | 13 | code: Zir, |
| 14 | air_instructions: std.MultiArrayList(Air.Inst) = .{}, | 14 | air_instructions: std.MultiArrayList(Air.Inst) = .{}, |
| 15 | air_extra: ArrayListUnmanaged(u32) = .{}, | 15 | air_extra: std.ArrayListUnmanaged(u32) = .{}, |
| 16 | air_values: ArrayListUnmanaged(Value) = .{}, | 16 | air_values: std.ArrayListUnmanaged(Value) = .{}, |
| 17 | air_variables: ArrayListUnmanaged(Module.Var) = .{}, | 17 | air_variables: std.ArrayListUnmanaged(*Module.Var) = .{}, |
| 18 | /// Maps ZIR to AIR. | 18 | /// Maps ZIR to AIR. |
| 19 | inst_map: InstMap = .{}, | 19 | inst_map: InstMap = .{}, |
| 20 | /// When analyzing an inline function call, owner_decl is the Decl of the caller | 20 | /// 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 | ... | @@ -1263,15 +1263,16 @@ fn zirArg(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!Air |
| 1263 | sema.next_arg_index += 1; | 1263 | sema.next_arg_index += 1; |
| 1264 | 1264 | ||
| 1265 | // TODO check if arg_name shadows a Decl | 1265 | // TODO check if arg_name shadows a Decl |
| 1266 | _ = arg_name; | ||
| 1266 | 1267 | ||
| 1267 | if (block.inlining) |_| { | 1268 | if (block.inlining) |_| { |
| 1268 | return sema.param_inst_list[arg_index]; | 1269 | return sema.param_inst_list[arg_index]; |
| 1269 | } | 1270 | } |
| 1270 | 1271 | ||
| 1271 | // Need to set the name of the Air.Arg instruction. | 1272 | // Set the name of the Air.Arg instruction for use by codegen debug info. |
| 1272 | const air_arg = sema.param_inst_list[arg_index].castTag(.arg).?; | 1273 | const air_arg = sema.param_inst_list[arg_index]; |
| 1273 | air_arg.name = arg_name; | 1274 | sema.air.instructions.items(.data)[air_arg].ty_str.str = inst_data.start; |
| 1274 | return &air_arg.base; | 1275 | return air_arg; |
| 1275 | } | 1276 | } |
| 1276 | 1277 | ||
| 1277 | fn zirAllocExtended( | 1278 | fn zirAllocExtended( |
| ... | @@ -7940,3 +7941,102 @@ fn enumFieldSrcLoc( | ... | @@ -7940,3 +7941,102 @@ fn enumFieldSrcLoc( |
| 7940 | } | 7941 | } |
| 7941 | } else unreachable; | 7942 | } else unreachable; |
| 7942 | } | 7943 | } |
| 7944 | |||
| 7945 | pub 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 | |||
| 8009 | const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len; | ||
| 8010 | |||
| 8011 | fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref { | ||
| 8012 | return @intToEnum(Air.Inst.Ref, ref_start_index + inst); | ||
| 8013 | } | ||
| 8014 | |||
| 8015 | fn 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 | |||
| 8024 | pub 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 | |||
| 8030 | pub 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; | ... | @@ -3,6 +3,7 @@ const mem = std.mem; |
| 3 | const math = std.math; | 3 | const math = std.math; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const Air = @import("Air.zig"); | 5 | const Air = @import("Air.zig"); |
| 6 | const Liveness = @import("Liveness.zig"); | ||
| 6 | const Type = @import("type.zig").Type; | 7 | const Type = @import("type.zig").Type; |
| 7 | const Value = @import("value.zig").Value; | 8 | const Value = @import("value.zig").Value; |
| 8 | const TypedValue = @import("TypedValue.zig"); | 9 | const TypedValue = @import("TypedValue.zig"); |
| ... | @@ -45,6 +46,71 @@ pub const DebugInfoOutput = union(enum) { | ... | @@ -45,6 +46,71 @@ pub const DebugInfoOutput = union(enum) { |
| 45 | none, | 46 | none, |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 49 | pub 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 | |||
| 48 | pub fn generateSymbol( | 114 | pub fn generateSymbol( |
| 49 | bin_file: *link.File, | 115 | bin_file: *link.File, |
| 50 | src_loc: Module.SrcLoc, | 116 | src_loc: Module.SrcLoc, |
| ... | @@ -57,60 +123,14 @@ pub fn generateSymbol( | ... | @@ -57,60 +123,14 @@ pub fn generateSymbol( |
| 57 | 123 | ||
| 58 | switch (typed_value.ty.zigTypeTag()) { | 124 | switch (typed_value.ty.zigTypeTag()) { |
| 59 | .Fn => { | 125 | .Fn => { |
| 60 | switch (bin_file.options.target.cpu.arch) { | 126 | return Result{ |
| 61 | .wasm32 => unreachable, // has its own code path | 127 | .fail = try ErrorMsg.create( |
| 62 | .wasm64 => unreachable, // has its own code path | 128 | bin_file.allocator, |
| 63 | .arm => return Function(.arm).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), | 129 | src_loc, |
| 64 | .armeb => return Function(.armeb).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), | 130 | "TODO implement generateSymbol function pointers", |
| 65 | .aarch64 => return Function(.aarch64).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), | 131 | .{}, |
| 66 | .aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), | 132 | ), |
| 67 | .aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src_loc, typed_value, code, debug_output), | 133 | }; |
| 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 | } | ||
| 114 | }, | 134 | }, |
| 115 | .Array => { | 135 | .Array => { |
| 116 | // TODO populate .debug_info for the array | 136 | // TODO populate .debug_info for the array |
| ... | @@ -262,6 +282,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -262,6 +282,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 262 | 282 | ||
| 263 | return struct { | 283 | return struct { |
| 264 | gpa: *Allocator, | 284 | gpa: *Allocator, |
| 285 | air: *const Air, | ||
| 265 | bin_file: *link.File, | 286 | bin_file: *link.File, |
| 266 | target: *const std.Target, | 287 | target: *const std.Target, |
| 267 | mod_fn: *const Module.Fn, | 288 | mod_fn: *const Module.Fn, |
| ... | @@ -421,10 +442,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -421,10 +442,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 421 | 442 | ||
| 422 | const Self = @This(); | 443 | const Self = @This(); |
| 423 | 444 | ||
| 424 | fn generateSymbol( | 445 | fn generate( |
| 425 | bin_file: *link.File, | 446 | bin_file: *link.File, |
| 426 | src_loc: Module.SrcLoc, | 447 | src_loc: Module.SrcLoc, |
| 427 | typed_value: TypedValue, | 448 | module_fn: *Module.Fn, |
| 449 | air: Air, | ||
| 450 | liveness: Liveness, | ||
| 428 | code: *std.ArrayList(u8), | 451 | code: *std.ArrayList(u8), |
| 429 | debug_output: DebugInfoOutput, | 452 | debug_output: DebugInfoOutput, |
| 430 | ) GenerateSymbolError!Result { | 453 | ) GenerateSymbolError!Result { |
| ... | @@ -432,8 +455,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -432,8 +455,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 432 | @panic("Attempted to compile for architecture that was disabled by build configuration"); | 455 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 433 | } | 456 | } |
| 434 | 457 | ||
| 435 | const module_fn = typed_value.val.castTag(.function).?.data; | ||
| 436 | |||
| 437 | assert(module_fn.owner_decl.has_tv); | 458 | assert(module_fn.owner_decl.has_tv); |
| 438 | const fn_type = module_fn.owner_decl.ty; | 459 | const fn_type = module_fn.owner_decl.ty; |
| 439 | 460 | ||
| ... | @@ -447,6 +468,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -447,6 +468,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 447 | 468 | ||
| 448 | var function = Self{ | 469 | var function = Self{ |
| 449 | .gpa = bin_file.allocator, | 470 | .gpa = bin_file.allocator, |
| 471 | .air = &air, | ||
| 472 | .liveness = &liveness, | ||
| 450 | .target = &bin_file.options.target, | 473 | .target = &bin_file.options.target, |
| 451 | .bin_file = bin_file, | 474 | .bin_file = bin_file, |
| 452 | .mod_fn = module_fn, | 475 | .mod_fn = module_fn, |
| ... | @@ -2131,8 +2154,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2131,8 +2154,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2131 | } | 2154 | } |
| 2132 | 2155 | ||
| 2133 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void { | 2156 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void { |
| 2134 | const name_with_null = inst.name[0 .. mem.lenZ(inst.name) + 1]; | 2157 | const ty_str = self.air.instruction.items(.data)[inst].ty_str; |
| 2135 | const ty = self.air.getType(inst); | 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); | ||
| 2136 | 2162 | ||
| 2137 | switch (mcv) { | 2163 | switch (mcv) { |
| 2138 | .register => |reg| { | 2164 | .register => |reg| { |
| ... | @@ -2249,8 +2275,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2249,8 +2275,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2249 | } | 2275 | } |
| 2250 | 2276 | ||
| 2251 | fn genCall(self: *Self, inst: Air.Inst.Index) !MCValue { | 2277 | fn genCall(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 2252 | const inst_datas = self.air.instructions.items(.data); | 2278 | const pl_op = self.air.instruction.items(.data)[inst].pl_op; |
| 2253 | const pl_op = inst_datas[inst].pl_op; | ||
| 2254 | const fn_ty = self.air.getType(pl_op.operand); | 2279 | const fn_ty = self.air.getType(pl_op.operand); |
| 2255 | const callee = pl_op.operand; | 2280 | const callee = pl_op.operand; |
| 2256 | const extra = self.air.extraData(Air.Call, inst_data.payload); | 2281 | const extra = self.air.extraData(Air.Call, inst_data.payload); |
| ... | @@ -2848,8 +2873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -2848,8 +2873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2848 | } | 2873 | } |
| 2849 | 2874 | ||
| 2850 | fn genCondBr(self: *Self, inst: Air.Inst.Index) !MCValue { | 2875 | fn genCondBr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 2851 | const inst_datas = self.air.instructions.items(.data); | 2876 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 2852 | const pl_op = inst_datas[inst].pl_op; | ||
| 2853 | const cond = try self.resolveInst(pl_op.operand); | 2877 | const cond = try self.resolveInst(pl_op.operand); |
| 2854 | const extra = self.air.extraData(Air.CondBr, inst_data.payload); | 2878 | const extra = self.air.extraData(Air.CondBr, inst_data.payload); |
| 2855 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; | 2879 | 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 { | ... | @@ -3101,16 +3125,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3101 | fn genIsNull(self: *Self, inst: Air.Inst.Index) !MCValue { | 3125 | fn genIsNull(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3102 | if (self.liveness.isUnused(inst)) | 3126 | if (self.liveness.isUnused(inst)) |
| 3103 | return MCValue.dead; | 3127 | return MCValue.dead; |
| 3104 | const inst_datas = self.air.instructions.items(.data); | 3128 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3105 | const operand = try self.resolveInst(inst_datas[inst].un_op); | 3129 | const operand = try self.resolveInst(un_op); |
| 3106 | return self.isNull(operand); | 3130 | return self.isNull(operand); |
| 3107 | } | 3131 | } |
| 3108 | 3132 | ||
| 3109 | fn genIsNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3133 | fn genIsNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3110 | if (self.liveness.isUnused(inst)) | 3134 | if (self.liveness.isUnused(inst)) |
| 3111 | return MCValue.dead; | 3135 | return MCValue.dead; |
| 3112 | const inst_datas = self.air.instructions.items(.data); | 3136 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3113 | const operand_ptr = try self.resolveInst(inst_datas[inst].un_op); | 3137 | const operand_ptr = try self.resolveInst(un_op); |
| 3114 | const operand: MCValue = blk: { | 3138 | const operand: MCValue = blk: { |
| 3115 | if (self.reuseOperand(inst, 0, operand_ptr)) { | 3139 | if (self.reuseOperand(inst, 0, operand_ptr)) { |
| 3116 | // The MCValue that holds the pointer can be re-used as the value. | 3140 | // 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 { | ... | @@ -3126,16 +3150,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3126 | fn genIsNonNull(self: *Self, inst: Air.Inst.Index) !MCValue { | 3150 | fn genIsNonNull(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3127 | if (self.liveness.isUnused(inst)) | 3151 | if (self.liveness.isUnused(inst)) |
| 3128 | return MCValue.dead; | 3152 | return MCValue.dead; |
| 3129 | const inst_datas = self.air.instructions.items(.data); | 3153 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3130 | const operand = try self.resolveInst(inst_datas[inst].un_op); | 3154 | const operand = try self.resolveInst(un_op); |
| 3131 | return self.isNonNull(operand); | 3155 | return self.isNonNull(operand); |
| 3132 | } | 3156 | } |
| 3133 | 3157 | ||
| 3134 | fn genIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3158 | fn genIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3135 | if (self.liveness.isUnused(inst)) | 3159 | if (self.liveness.isUnused(inst)) |
| 3136 | return MCValue.dead; | 3160 | return MCValue.dead; |
| 3137 | const inst_datas = self.air.instructions.items(.data); | 3161 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3138 | const operand_ptr = try self.resolveInst(inst_datas[inst].un_op); | 3162 | const operand_ptr = try self.resolveInst(un_op); |
| 3139 | const operand: MCValue = blk: { | 3163 | const operand: MCValue = blk: { |
| 3140 | if (self.reuseOperand(inst, 0, operand_ptr)) { | 3164 | if (self.reuseOperand(inst, 0, operand_ptr)) { |
| 3141 | // The MCValue that holds the pointer can be re-used as the value. | 3165 | // 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 { | ... | @@ -3151,16 +3175,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3151 | fn genIsErr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3175 | fn genIsErr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3152 | if (self.liveness.isUnused(inst)) | 3176 | if (self.liveness.isUnused(inst)) |
| 3153 | return MCValue.dead; | 3177 | return MCValue.dead; |
| 3154 | const inst_datas = self.air.instructions.items(.data); | 3178 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3155 | const operand = try self.resolveInst(inst_datas[inst].un_op); | 3179 | const operand = try self.resolveInst(un_op); |
| 3156 | return self.isErr(operand); | 3180 | return self.isErr(operand); |
| 3157 | } | 3181 | } |
| 3158 | 3182 | ||
| 3159 | fn genIsErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3183 | fn genIsErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3160 | if (self.liveness.isUnused(inst)) | 3184 | if (self.liveness.isUnused(inst)) |
| 3161 | return MCValue.dead; | 3185 | return MCValue.dead; |
| 3162 | const inst_datas = self.air.instructions.items(.data); | 3186 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3163 | const operand_ptr = try self.resolveInst(inst_datas[inst].un_op); | 3187 | const operand_ptr = try self.resolveInst(un_op); |
| 3164 | const operand: MCValue = blk: { | 3188 | const operand: MCValue = blk: { |
| 3165 | if (self.reuseOperand(inst, 0, operand_ptr)) { | 3189 | if (self.reuseOperand(inst, 0, operand_ptr)) { |
| 3166 | // The MCValue that holds the pointer can be re-used as the value. | 3190 | // 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 { | ... | @@ -3176,16 +3200,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3176 | fn genIsNonErr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3200 | fn genIsNonErr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3177 | if (self.liveness.isUnused(inst)) | 3201 | if (self.liveness.isUnused(inst)) |
| 3178 | return MCValue.dead; | 3202 | return MCValue.dead; |
| 3179 | const inst_datas = self.air.instructions.items(.data); | 3203 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3180 | const operand = try self.resolveInst(inst_datas[inst].un_op); | 3204 | const operand = try self.resolveInst(un_op); |
| 3181 | return self.isNonErr(operand); | 3205 | return self.isNonErr(operand); |
| 3182 | } | 3206 | } |
| 3183 | 3207 | ||
| 3184 | fn genIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue { | 3208 | fn genIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3185 | if (self.liveness.isUnused(inst)) | 3209 | if (self.liveness.isUnused(inst)) |
| 3186 | return MCValue.dead; | 3210 | return MCValue.dead; |
| 3187 | const inst_datas = self.air.instructions.items(.data); | 3211 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3188 | const operand_ptr = try self.resolveInst(inst_datas[inst].un_op); | 3212 | const operand_ptr = try self.resolveInst(un_op); |
| 3189 | const operand: MCValue = blk: { | 3213 | const operand: MCValue = blk: { |
| 3190 | if (self.reuseOperand(inst, 0, operand_ptr)) { | 3214 | if (self.reuseOperand(inst, 0, operand_ptr)) { |
| 3191 | // The MCValue that holds the pointer can be re-used as the value. | 3215 | // 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 { | ... | @@ -3200,8 +3224,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 3200 | 3224 | ||
| 3201 | fn genLoop(self: *Self, inst: Air.Inst.Index) !MCValue { | 3225 | fn genLoop(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 3202 | // A loop is a setup to be able to jump back to the beginning. | 3226 | // A loop is a setup to be able to jump back to the beginning. |
| 3203 | const inst_datas = self.air.instructions.items(.data); | 3227 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 3204 | const loop = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload); | 3228 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 3205 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; | 3229 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; |
| 3206 | const start_index = self.code.items.len; | 3230 | const start_index = self.code.items.len; |
| 3207 | try self.genBody(body); | 3231 | try self.genBody(body); |
| ... | @@ -4377,13 +4401,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -4377,13 +4401,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4377 | } | 4401 | } |
| 4378 | 4402 | ||
| 4379 | fn genPtrToInt(self: *Self, inst: Air.Inst.Index) !MCValue { | 4403 | fn genPtrToInt(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 4380 | const inst_datas = self.air.instructions.items(.data); | 4404 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4381 | return self.resolveInst(inst_datas[inst].un_op); | 4405 | return self.resolveInst(un_op); |
| 4382 | } | 4406 | } |
| 4383 | 4407 | ||
| 4384 | fn genBitCast(self: *Self, inst: Air.Inst.Index) !MCValue { | 4408 | fn genBitCast(self: *Self, inst: Air.Inst.Index) !MCValue { |
| 4385 | const inst_datas = self.air.instructions.items(.data); | 4409 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4386 | return self.resolveInst(inst_datas[inst].ty_op.operand); | 4410 | return self.resolveInst(ty_op.operand); |
| 4387 | } | 4411 | } |
| 4388 | 4412 | ||
| 4389 | fn resolveInst(self: *Self, inst: Air.Inst.Index) !MCValue { | 4413 | fn resolveInst(self: *Self, inst: Air.Inst.Index) !MCValue { |
src/codegen/spirv.zig+35-22| ... | @@ -159,7 +159,10 @@ pub const DeclGen = struct { | ... | @@ -159,7 +159,10 @@ pub const DeclGen = struct { |
| 159 | /// The SPIR-V module code should be put in. | 159 | /// The SPIR-V module code should be put in. |
| 160 | spv: *SPIRVModule, | 160 | spv: *SPIRVModule, |
| 161 | 161 | ||
| 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. | ||
| 163 | args: std.ArrayList(ResultId), | 166 | args: std.ArrayList(ResultId), |
| 164 | 167 | ||
| 165 | /// A counter to keep track of how many `arg` instructions we've seen yet. | 168 | /// A counter to keep track of how many `arg` instructions we've seen yet. |
| ... | @@ -168,33 +171,35 @@ pub const DeclGen = struct { | ... | @@ -168,33 +171,35 @@ pub const DeclGen = struct { |
| 168 | /// A map keeping track of which instruction generated which result-id. | 171 | /// A map keeping track of which instruction generated which result-id. |
| 169 | inst_results: InstMap, | 172 | inst_results: InstMap, |
| 170 | 173 | ||
| 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. | ||
| 172 | blocks: BlockMap, | 176 | blocks: BlockMap, |
| 173 | 177 | ||
| 174 | /// The label of the SPIR-V block we are currently generating. | 178 | /// The label of the SPIR-V block we are currently generating. |
| 175 | current_block_label_id: ResultId, | 179 | current_block_label_id: ResultId, |
| 176 | 180 | ||
| 177 | /// The actual instructions for this function. We need to declare all locals in the first block, and because we don't | 181 | /// The actual instructions for this function. We need to declare all locals in |
| 178 | /// know which locals there are going to be, we're just going to generate everything after the locals-section in this array. | 182 | /// the first block, and because we don't know which locals there are going to be, |
| 179 | /// Note: It will not contain OpFunction, OpFunctionParameter, OpVariable and the initial OpLabel. These will be generated | 183 | /// we're just going to generate everything after the locals-section in this array. |
| 180 | /// into spv.binary.fn_decls directly. | 184 | /// Note: It will not contain OpFunction, OpFunctionParameter, OpVariable and the |
| 185 | /// initial OpLabel. These will be generated into spv.binary.fn_decls directly. | ||
| 181 | code: std.ArrayList(Word), | 186 | code: std.ArrayList(Word), |
| 182 | 187 | ||
| 183 | /// The decl we are currently generating code for. | 188 | /// The decl we are currently generating code for. |
| 184 | decl: *Decl, | 189 | decl: *Decl, |
| 185 | 190 | ||
| 186 | /// If `gen` returned `Error.AnalysisFail`, this contains an explanatory message. Memory is owned by | 191 | /// If `gen` returned `Error.AnalysisFail`, this contains an explanatory message. |
| 187 | /// `module.gpa`. | 192 | /// Memory is owned by `module.gpa`. |
| 188 | error_msg: ?*Module.ErrorMsg, | 193 | error_msg: ?*Module.ErrorMsg, |
| 189 | 194 | ||
| 190 | /// Possible errors the `gen` function may return. | 195 | /// Possible errors the `gen` function may return. |
| 191 | const Error = error{ AnalysisFail, OutOfMemory }; | 196 | const Error = error{ AnalysisFail, OutOfMemory }; |
| 192 | 197 | ||
| 193 | /// This structure is used to return information about a type typically used for arithmetic operations. | 198 | /// This structure is used to return information about a type typically used for |
| 194 | /// These types may either be integers, floats, or a vector of these. Most scalar operations also work on vectors, | 199 | /// arithmetic operations. These types may either be integers, floats, or a vector |
| 195 | /// so we can easily represent those as arithmetic types. | 200 | /// of these. Most scalar operations also work on vectors, so we can easily represent |
| 196 | /// If the type is a scalar, 'inner type' refers to the scalar type. Otherwise, if its a vector, it refers | 201 | /// those as arithmetic types. If the type is a scalar, 'inner type' refers to the |
| 197 | /// to the vector's element type. | 202 | /// scalar type. Otherwise, if its a vector, it refers to the vector's element type. |
| 198 | const ArithmeticTypeInfo = struct { | 203 | const ArithmeticTypeInfo = struct { |
| 199 | /// A classification of the inner type. | 204 | /// A classification of the inner type. |
| 200 | const Class = enum { | 205 | const Class = enum { |
| ... | @@ -206,13 +211,14 @@ pub const DeclGen = struct { | ... | @@ -206,13 +211,14 @@ pub const DeclGen = struct { |
| 206 | /// the relevant capability is enabled). | 211 | /// the relevant capability is enabled). |
| 207 | integer, | 212 | integer, |
| 208 | 213 | ||
| 209 | /// A regular float. These are all required to be natively supported. Floating points for | 214 | /// A regular float. These are all required to be natively supported. Floating points |
| 210 | /// which the relevant capability is not enabled are not emulated. | 215 | /// for which the relevant capability is not enabled are not emulated. |
| 211 | float, | 216 | float, |
| 212 | 217 | ||
| 213 | /// An integer of a 'strange' size (which' bit size is not the same as its backing type. **Note**: this | 218 | /// An integer of a 'strange' size (which' bit size is not the same as its backing |
| 214 | /// may **also** include power-of-2 integers for which the relevant capability is not enabled), but still | 219 | /// type. **Note**: this may **also** include power-of-2 integers for which the |
| 215 | /// within the limits of the largest natively supported integer type. | 220 | /// relevant capability is not enabled), but still within the limits of the largest |
| 221 | /// natively supported integer type. | ||
| 216 | strange_integer, | 222 | strange_integer, |
| 217 | 223 | ||
| 218 | /// An integer with more bits than the largest natively supported integer type. | 224 | /// An integer with more bits than the largest natively supported integer type. |
| ... | @@ -220,7 +226,7 @@ pub const DeclGen = struct { | ... | @@ -220,7 +226,7 @@ pub const DeclGen = struct { |
| 220 | }; | 226 | }; |
| 221 | 227 | ||
| 222 | /// The number of bits in the inner type. | 228 | /// 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. |
| 224 | bits: u16, | 230 | bits: u16, |
| 225 | 231 | ||
| 226 | /// Whether the type is a vector. | 232 | /// Whether the type is a vector. |
| ... | @@ -234,10 +240,12 @@ pub const DeclGen = struct { | ... | @@ -234,10 +240,12 @@ pub const DeclGen = struct { |
| 234 | class: Class, | 240 | class: Class, |
| 235 | }; | 241 | }; |
| 236 | 242 | ||
| 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. | ||
| 238 | pub fn init(spv: *SPIRVModule) DeclGen { | 245 | pub fn init(spv: *SPIRVModule) DeclGen { |
| 239 | return .{ | 246 | return .{ |
| 240 | .spv = spv, | 247 | .spv = spv, |
| 248 | .air = undefined, | ||
| 241 | .args = std.ArrayList(ResultId).init(spv.gpa), | 249 | .args = std.ArrayList(ResultId).init(spv.gpa), |
| 242 | .next_arg_index = undefined, | 250 | .next_arg_index = undefined, |
| 243 | .inst_results = InstMap.init(spv.gpa), | 251 | .inst_results = InstMap.init(spv.gpa), |
| ... | @@ -252,8 +260,9 @@ pub const DeclGen = struct { | ... | @@ -252,8 +260,9 @@ pub const DeclGen = struct { |
| 252 | /// Generate the code for `decl`. If a reportable error occured during code generation, | 260 | /// Generate the code for `decl`. If a reportable error occured during code generation, |
| 253 | /// a message is returned by this function. Callee owns the memory. If this function returns such | 261 | /// a message is returned by this function. Callee owns the memory. If this function returns such |
| 254 | /// a reportable error, it is valid to be called again for a different decl. | 262 | /// 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 { |
| 256 | // Reset internal resources, we don't want to re-allocate these. | 264 | // Reset internal resources, we don't want to re-allocate these. |
| 265 | self.air = &air; | ||
| 257 | self.args.items.len = 0; | 266 | self.args.items.len = 0; |
| 258 | self.next_arg_index = 0; | 267 | self.next_arg_index = 0; |
| 259 | self.inst_results.clearRetainingCapacity(); | 268 | self.inst_results.clearRetainingCapacity(); |
| ... | @@ -680,7 +689,7 @@ pub const DeclGen = struct { | ... | @@ -680,7 +689,7 @@ pub const DeclGen = struct { |
| 680 | 689 | ||
| 681 | .br => return self.genBr(inst), | 690 | .br => return self.genBr(inst), |
| 682 | .breakpoint => return, | 691 | .breakpoint => return, |
| 683 | .condbr => return self.genCondBr(inst), | 692 | .cond_br => return self.genCondBr(inst), |
| 684 | .constant => unreachable, | 693 | .constant => unreachable, |
| 685 | .dbg_stmt => return self.genDbgStmt(inst), | 694 | .dbg_stmt => return self.genDbgStmt(inst), |
| 686 | .loop => return self.genLoop(inst), | 695 | .loop => return self.genLoop(inst), |
| ... | @@ -688,6 +697,10 @@ pub const DeclGen = struct { | ... | @@ -688,6 +697,10 @@ pub const DeclGen = struct { |
| 688 | .store => return self.genStore(inst), | 697 | .store => return self.genStore(inst), |
| 689 | .unreach => return self.genUnreach(), | 698 | .unreach => return self.genUnreach(), |
| 690 | // zig fmt: on | 699 | // zig fmt: on |
| 700 | |||
| 701 | else => |tag| return self.fail("TODO: SPIR-V backend: implement AIR tag {s}", .{ | ||
| 702 | @tagName(tag), | ||
| 703 | }), | ||
| 691 | }; | 704 | }; |
| 692 | 705 | ||
| 693 | try self.inst_results.putNoClobber(inst, result_id); | 706 | 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 { | ... | @@ -135,6 +135,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { |
| 135 | const tracy = trace(@src()); | 135 | const tracy = trace(@src()); |
| 136 | defer tracy.end(); | 136 | defer tracy.end(); |
| 137 | 137 | ||
| 138 | if (build_options.skip_non_native) { | ||
| 139 | @panic("Attempted to compile for architecture that was disabled by build configuration"); | ||
| 140 | } | ||
| 141 | |||
| 138 | const module = self.base.options.module.?; | 142 | const module = self.base.options.module.?; |
| 139 | const target = comp.getTarget(); | 143 | const target = comp.getTarget(); |
| 140 | 144 |
src/register_manager.zig+8-8| ... | @@ -20,7 +20,7 @@ pub fn RegisterManager( | ... | @@ -20,7 +20,7 @@ pub fn RegisterManager( |
| 20 | ) type { | 20 | ) type { |
| 21 | return struct { | 21 | return struct { |
| 22 | /// The key must be canonical register. | 22 | /// 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, |
| 24 | free_registers: FreeRegInt = math.maxInt(FreeRegInt), | 24 | free_registers: FreeRegInt = math.maxInt(FreeRegInt), |
| 25 | /// Tracks all registers allocated in the course of this function | 25 | /// Tracks all registers allocated in the course of this function |
| 26 | allocated_registers: FreeRegInt = 0, | 26 | allocated_registers: FreeRegInt = 0, |
| ... | @@ -75,7 +75,7 @@ pub fn RegisterManager( | ... | @@ -75,7 +75,7 @@ pub fn RegisterManager( |
| 75 | pub fn tryAllocRegs( | 75 | pub fn tryAllocRegs( |
| 76 | self: *Self, | 76 | self: *Self, |
| 77 | comptime count: comptime_int, | 77 | comptime count: comptime_int, |
| 78 | insts: [count]?*ir.Inst, | 78 | insts: [count]?Air.Inst.Index, |
| 79 | exceptions: []const Register, | 79 | exceptions: []const Register, |
| 80 | ) ?[count]Register { | 80 | ) ?[count]Register { |
| 81 | comptime if (callee_preserved_regs.len == 0) return null; | 81 | comptime if (callee_preserved_regs.len == 0) return null; |
| ... | @@ -113,7 +113,7 @@ pub fn RegisterManager( | ... | @@ -113,7 +113,7 @@ pub fn RegisterManager( |
| 113 | /// Allocates a register and optionally tracks it with a | 113 | /// Allocates a register and optionally tracks it with a |
| 114 | /// corresponding instruction. Returns `null` if all registers | 114 | /// corresponding instruction. Returns `null` if all registers |
| 115 | /// are allocated. | 115 | /// 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 { |
| 117 | return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null; | 117 | return if (tryAllocRegs(self, 1, .{inst}, exceptions)) |regs| regs[0] else null; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| ... | @@ -123,7 +123,7 @@ pub fn RegisterManager( | ... | @@ -123,7 +123,7 @@ pub fn RegisterManager( |
| 123 | pub fn allocRegs( | 123 | pub fn allocRegs( |
| 124 | self: *Self, | 124 | self: *Self, |
| 125 | comptime count: comptime_int, | 125 | comptime count: comptime_int, |
| 126 | insts: [count]?*ir.Inst, | 126 | insts: [count]?Air.Inst.Index, |
| 127 | exceptions: []const Register, | 127 | exceptions: []const Register, |
| 128 | ) ![count]Register { | 128 | ) ![count]Register { |
| 129 | comptime assert(count > 0 and count <= callee_preserved_regs.len); | 129 | comptime assert(count > 0 and count <= callee_preserved_regs.len); |
| ... | @@ -168,14 +168,14 @@ pub fn RegisterManager( | ... | @@ -168,14 +168,14 @@ pub fn RegisterManager( |
| 168 | 168 | ||
| 169 | /// Allocates a register and optionally tracks it with a | 169 | /// Allocates a register and optionally tracks it with a |
| 170 | /// corresponding instruction. | 170 | /// 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 { |
| 172 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; | 172 | return (try self.allocRegs(1, .{inst}, exceptions))[0]; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | /// Spills the register if it is currently allocated. If a | 175 | /// Spills the register if it is currently allocated. If a |
| 176 | /// corresponding instruction is passed, will also track this | 176 | /// corresponding instruction is passed, will also track this |
| 177 | /// register. | 177 | /// 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 { |
| 179 | const index = reg.allocIndex() orelse return; | 179 | const index = reg.allocIndex() orelse return; |
| 180 | 180 | ||
| 181 | if (inst) |tracked_inst| | 181 | if (inst) |tracked_inst| |
| ... | @@ -202,7 +202,7 @@ pub fn RegisterManager( | ... | @@ -202,7 +202,7 @@ pub fn RegisterManager( |
| 202 | /// Allocates the specified register with the specified | 202 | /// Allocates the specified register with the specified |
| 203 | /// instruction. Asserts that the register is free and no | 203 | /// instruction. Asserts that the register is free and no |
| 204 | /// spilling is necessary. | 204 | /// 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 { |
| 206 | const index = reg.allocIndex() orelse return; | 206 | const index = reg.allocIndex() orelse return; |
| 207 | 207 | ||
| 208 | assert(self.registers[index] == null); | 208 | assert(self.registers[index] == null); |
| ... | @@ -264,7 +264,7 @@ fn MockFunction(comptime Register: type) type { | ... | @@ -264,7 +264,7 @@ fn MockFunction(comptime Register: type) type { |
| 264 | self.spilled.deinit(self.allocator); | 264 | self.spilled.deinit(self.allocator); |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 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 { |
| 268 | _ = inst; | 268 | _ = inst; |
| 269 | try self.spilled.append(self.allocator, reg); | 269 | try self.spilled.append(self.allocator, reg); |
| 270 | } | 270 | } |