| ... | ... | @@ -111,11 +111,6 @@ const MCValue = union(enum) { |
| 111 | 111 | /// A pointer-sized integer that fits in a register. |
| 112 | 112 | /// If the type is a pointer, this is the pointer address in virtual address space. |
| 113 | 113 | immediate: u64, |
| 114 | | /// The constant was emitted into the code, at this offset. |
| 115 | | /// If the type is a pointer, it means the pointer address is embedded in the code. |
| 116 | | embedded_in_code: usize, |
| 117 | | /// The value is a pointer to a constant which was emitted into the code, at this offset. |
| 118 | | ptr_embedded_in_code: usize, |
| 119 | 114 | /// The value is in a target-specific register. |
| 120 | 115 | register: Register, |
| 121 | 116 | /// The value is in memory at a hard-coded address. |
| ... | ... | @@ -129,7 +124,7 @@ const MCValue = union(enum) { |
| 129 | 124 | |
| 130 | 125 | fn isMemory(mcv: MCValue) bool { |
| 131 | 126 | return switch (mcv) { |
| 132 | | .embedded_in_code, .memory, .stack_offset => true, |
| 127 | .memory, .stack_offset => true, |
| 133 | 128 | else => false, |
| 134 | 129 | }; |
| 135 | 130 | } |
| ... | ... | @@ -148,10 +143,8 @@ const MCValue = union(enum) { |
| 148 | 143 | .dead => unreachable, |
| 149 | 144 | |
| 150 | 145 | .immediate, |
| 151 | | .embedded_in_code, |
| 152 | 146 | .memory, |
| 153 | 147 | .ptr_stack_offset, |
| 154 | | .ptr_embedded_in_code, |
| 155 | 148 | .undef, |
| 156 | 149 | => false, |
| 157 | 150 | |
| ... | ... | @@ -1279,12 +1272,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1279 | 1272 | .dead => unreachable, |
| 1280 | 1273 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), |
| 1281 | 1274 | .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }), |
| 1282 | | .ptr_embedded_in_code => |off| { |
| 1283 | | try self.setRegOrMem(elem_ty, dst_mcv, .{ .embedded_in_code = off }); |
| 1284 | | }, |
| 1285 | | .embedded_in_code => { |
| 1286 | | return self.fail("TODO implement loading from MCValue.embedded_in_code", .{}); |
| 1287 | | }, |
| 1288 | 1275 | .register => { |
| 1289 | 1276 | return self.fail("TODO implement loading from MCValue.register", .{}); |
| 1290 | 1277 | }, |
| ... | ... | @@ -1327,27 +1314,19 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1327 | 1314 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1328 | 1315 | } |
| 1329 | 1316 | |
| 1330 | | fn airStore(self: *Self, inst: Air.Inst.Index) !void { |
| 1331 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1332 | | const ptr = try self.resolveInst(bin_op.lhs); |
| 1333 | | const value = try self.resolveInst(bin_op.rhs); |
| 1334 | | const elem_ty = self.air.typeOf(bin_op.rhs); |
| 1317 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { |
| 1318 | _ = ptr_ty; |
| 1319 | |
| 1335 | 1320 | switch (ptr) { |
| 1336 | 1321 | .none => unreachable, |
| 1337 | 1322 | .undef => unreachable, |
| 1338 | 1323 | .unreach => unreachable, |
| 1339 | 1324 | .dead => unreachable, |
| 1340 | 1325 | .immediate => |imm| { |
| 1341 | | try self.setRegOrMem(elem_ty, .{ .memory = imm }, value); |
| 1326 | try self.setRegOrMem(value_ty, .{ .memory = imm }, value); |
| 1342 | 1327 | }, |
| 1343 | 1328 | .ptr_stack_offset => |off| { |
| 1344 | | try self.genSetStack(elem_ty, off, value); |
| 1345 | | }, |
| 1346 | | .ptr_embedded_in_code => |off| { |
| 1347 | | try self.setRegOrMem(elem_ty, .{ .embedded_in_code = off }, value); |
| 1348 | | }, |
| 1349 | | .embedded_in_code => { |
| 1350 | | return self.fail("TODO implement storing to MCValue.embedded_in_code", .{}); |
| 1329 | try self.genSetStack(value_ty, off, value); |
| 1351 | 1330 | }, |
| 1352 | 1331 | .register => { |
| 1353 | 1332 | return self.fail("TODO implement storing to MCValue.register", .{}); |
| ... | ... | @@ -1359,6 +1338,17 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void { |
| 1359 | 1338 | return self.fail("TODO implement storing to MCValue.stack_offset", .{}); |
| 1360 | 1339 | }, |
| 1361 | 1340 | } |
| 1341 | } |
| 1342 | |
| 1343 | fn airStore(self: *Self, inst: Air.Inst.Index) !void { |
| 1344 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1345 | const ptr = try self.resolveInst(bin_op.lhs); |
| 1346 | const value = try self.resolveInst(bin_op.rhs); |
| 1347 | const ptr_ty = self.air.typeOf(bin_op.lhs); |
| 1348 | const value_ty = self.air.typeOf(bin_op.rhs); |
| 1349 | |
| 1350 | try self.store(ptr, value, ptr_ty, value_ty); |
| 1351 | |
| 1362 | 1352 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1363 | 1353 | } |
| 1364 | 1354 | |
| ... | ... | @@ -1504,7 +1494,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1504 | 1494 | .immediate => unreachable, |
| 1505 | 1495 | .unreach => unreachable, |
| 1506 | 1496 | .dead => unreachable, |
| 1507 | | .embedded_in_code => unreachable, |
| 1508 | 1497 | .memory => unreachable, |
| 1509 | 1498 | .register => |reg| { |
| 1510 | 1499 | try self.register_manager.getReg(reg, null); |
| ... | ... | @@ -1516,9 +1505,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1516 | 1505 | .ptr_stack_offset => { |
| 1517 | 1506 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| 1518 | 1507 | }, |
| 1519 | | .ptr_embedded_in_code => { |
| 1520 | | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); |
| 1521 | | }, |
| 1522 | 1508 | } |
| 1523 | 1509 | } |
| 1524 | 1510 | |
| ... | ... | @@ -2043,7 +2029,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2043 | 2029 | switch (mcv) { |
| 2044 | 2030 | .dead => unreachable, |
| 2045 | 2031 | .ptr_stack_offset => unreachable, |
| 2046 | | .ptr_embedded_in_code => unreachable, |
| 2047 | 2032 | .unreach, .none => return, // Nothing to do. |
| 2048 | 2033 | .undef => { |
| 2049 | 2034 | if (!self.wantSafety()) |
| ... | ... | @@ -2312,27 +2297,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 2312 | 2297 | } |
| 2313 | 2298 | } |
| 2314 | 2299 | |
| 2315 | | /// If the MCValue is an immediate, and it does not fit within this type, |
| 2316 | | /// we put it in a register. |
| 2317 | | /// A potential opportunity for future optimization here would be keeping track |
| 2318 | | /// of the fact that the instruction is available both as an immediate |
| 2319 | | /// and as a register. |
| 2320 | | fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue { |
| 2321 | | const mcv = try self.resolveInst(operand); |
| 2322 | | const ti = @typeInfo(T).Int; |
| 2323 | | switch (mcv) { |
| 2324 | | .immediate => |imm| { |
| 2325 | | // This immediate is unsigned. |
| 2326 | | const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed)); |
| 2327 | | if (imm >= math.maxInt(U)) { |
| 2328 | | return MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.usize), mcv) }; |
| 2329 | | } |
| 2330 | | }, |
| 2331 | | else => {}, |
| 2332 | | } |
| 2333 | | return mcv; |
| 2334 | | } |
| 2335 | | |
| 2336 | 2300 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { |
| 2337 | 2301 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 2338 | 2302 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |