| ... | @@ -111,11 +111,6 @@ const MCValue = union(enum) { | ... | @@ -111,11 +111,6 @@ const MCValue = union(enum) { |
| 111 | /// A pointer-sized integer that fits in a register. | 111 | /// A pointer-sized integer that fits in a register. |
| 112 | /// If the type is a pointer, this is the pointer address in virtual address space. | 112 | /// If the type is a pointer, this is the pointer address in virtual address space. |
| 113 | immediate: u64, | 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 | /// The value is in a target-specific register. | 114 | /// The value is in a target-specific register. |
| 120 | register: Register, | 115 | register: Register, |
| 121 | /// The value is in memory at a hard-coded address. | 116 | /// The value is in memory at a hard-coded address. |
| ... | @@ -129,7 +124,7 @@ const MCValue = union(enum) { | ... | @@ -129,7 +124,7 @@ const MCValue = union(enum) { |
| 129 | | 124 | |
| 130 | fn isMemory(mcv: MCValue) bool { | 125 | fn isMemory(mcv: MCValue) bool { |
| 131 | return switch (mcv) { | 126 | return switch (mcv) { |
| 132 | .embedded_in_code, .memory, .stack_offset => true, | 127 | .memory, .stack_offset => true, |
| 133 | else => false, | 128 | else => false, |
| 134 | }; | 129 | }; |
| 135 | } | 130 | } |
| ... | @@ -148,10 +143,8 @@ const MCValue = union(enum) { | ... | @@ -148,10 +143,8 @@ const MCValue = union(enum) { |
| 148 | .dead => unreachable, | 143 | .dead => unreachable, |
| 149 | | 144 | |
| 150 | .immediate, | 145 | .immediate, |
| 151 | .embedded_in_code, | | |
| 152 | .memory, | 146 | .memory, |
| 153 | .ptr_stack_offset, | 147 | .ptr_stack_offset, |
| 154 | .ptr_embedded_in_code, | | |
| 155 | .undef, | 148 | .undef, |
| 156 | => false, | 149 | => false, |
| 157 | | 150 | |
| ... | @@ -1279,12 +1272,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1279,12 +1272,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1279 | .dead => unreachable, | 1272 | .dead => unreachable, |
| 1280 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), | 1273 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), |
| 1281 | .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }), | 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 | .register => { | 1275 | .register => { |
| 1289 | return self.fail("TODO implement loading from MCValue.register", .{}); | 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,27 +1314,19 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1327 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 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 { | 1317 | fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) !void { |
| 1331 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1318 | _ = ptr_ty; |
| 1332 | const ptr = try self.resolveInst(bin_op.lhs); | 1319 | |
| 1333 | const value = try self.resolveInst(bin_op.rhs); | | |
| 1334 | const elem_ty = self.air.typeOf(bin_op.rhs); | | |
| 1335 | switch (ptr) { | 1320 | switch (ptr) { |
| 1336 | .none => unreachable, | 1321 | .none => unreachable, |
| 1337 | .undef => unreachable, | 1322 | .undef => unreachable, |
| 1338 | .unreach => unreachable, | 1323 | .unreach => unreachable, |
| 1339 | .dead => unreachable, | 1324 | .dead => unreachable, |
| 1340 | .immediate => |imm| { | 1325 | .immediate => |imm| { |
| 1341 | try self.setRegOrMem(elem_ty, .{ .memory = imm }, value); | 1326 | try self.setRegOrMem(value_ty, .{ .memory = imm }, value); |
| 1342 | }, | 1327 | }, |
| 1343 | .ptr_stack_offset => |off| { | 1328 | .ptr_stack_offset => |off| { |
| 1344 | try self.genSetStack(elem_ty, off, value); | 1329 | try self.genSetStack(value_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", .{}); | | |
| 1351 | }, | 1330 | }, |
| 1352 | .register => { | 1331 | .register => { |
| 1353 | return self.fail("TODO implement storing to MCValue.register", .{}); | 1332 | return self.fail("TODO implement storing to MCValue.register", .{}); |
| ... | @@ -1359,6 +1338,17 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1359,6 +1338,17 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void { |
| 1359 | return self.fail("TODO implement storing to MCValue.stack_offset", .{}); | 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 | return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none }); | 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,7 +1494,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1504 | .immediate => unreachable, | 1494 | .immediate => unreachable, |
| 1505 | .unreach => unreachable, | 1495 | .unreach => unreachable, |
| 1506 | .dead => unreachable, | 1496 | .dead => unreachable, |
| 1507 | .embedded_in_code => unreachable, | | |
| 1508 | .memory => unreachable, | 1497 | .memory => unreachable, |
| 1509 | .register => |reg| { | 1498 | .register => |reg| { |
| 1510 | try self.register_manager.getReg(reg, null); | 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,9 +1505,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 1516 | .ptr_stack_offset => { | 1505 | .ptr_stack_offset => { |
| 1517 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); | 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,7 +2029,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2043 | switch (mcv) { | 2029 | switch (mcv) { |
| 2044 | .dead => unreachable, | 2030 | .dead => unreachable, |
| 2045 | .ptr_stack_offset => unreachable, | 2031 | .ptr_stack_offset => unreachable, |
| 2046 | .ptr_embedded_in_code => unreachable, | | |
| 2047 | .unreach, .none => return, // Nothing to do. | 2032 | .unreach, .none => return, // Nothing to do. |
| 2048 | .undef => { | 2033 | .undef => { |
| 2049 | if (!self.wantSafety()) | 2034 | if (!self.wantSafety()) |
| ... | @@ -2312,27 +2297,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | ... | @@ -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 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { | 2300 | fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue { |
| 2337 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 2301 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 2338 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | 2302 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |