| ... | ... | @@ -433,7 +433,7 @@ pub fn generate( |
| 433 | 433 | .prev_di_pc = 0, |
| 434 | 434 | .prev_di_line = module_fn.lbrace_line, |
| 435 | 435 | .prev_di_column = module_fn.lbrace_column, |
| 436 | | .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align), |
| 436 | .stack_size = function.max_end_stack, |
| 437 | 437 | .saved_regs_stack_space = function.saved_regs_stack_space, |
| 438 | 438 | }; |
| 439 | 439 | defer emit.deinit(); |
| ... | ... | @@ -560,6 +560,7 @@ fn gen(self: *Self) !void { |
| 560 | 560 | const total_stack_size = self.max_end_stack + self.saved_regs_stack_space; |
| 561 | 561 | const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align); |
| 562 | 562 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; |
| 563 | self.max_end_stack = stack_size; |
| 563 | 564 | if (math.cast(u12, stack_size)) |size| { |
| 564 | 565 | self.mir_instructions.set(backpatch_reloc, .{ |
| 565 | 566 | .tag = .sub_immediate, |
| ... | ... | @@ -982,11 +983,16 @@ fn allocMem( |
| 982 | 983 | assert(abi_size > 0); |
| 983 | 984 | assert(abi_align > 0); |
| 984 | 985 | |
| 985 | | if (abi_align > self.stack_align) |
| 986 | | self.stack_align = abi_align; |
| 986 | // In order to efficiently load and store stack items that fit |
| 987 | // into registers, we bump up the alignment to the next power of |
| 988 | // two. |
| 989 | const adjusted_align = if (abi_size > 8) |
| 990 | abi_align |
| 991 | else |
| 992 | std.math.ceilPowerOfTwoAssert(u32, abi_size); |
| 987 | 993 | |
| 988 | 994 | // TODO find a free slot instead of always appending |
| 989 | | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 995 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, adjusted_align) + abi_size; |
| 990 | 996 | self.next_stack_offset = offset; |
| 991 | 997 | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); |
| 992 | 998 | |
| ... | ... | @@ -5396,7 +5402,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 5396 | 5402 | } |
| 5397 | 5403 | |
| 5398 | 5404 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| 5399 | | const abi_size = ty.abiSize(self.target.*); |
| 5405 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 5400 | 5406 | switch (mcv) { |
| 5401 | 5407 | .dead => unreachable, |
| 5402 | 5408 | .unreach, .none => return, // Nothing to do. |
| ... | ... | @@ -5404,7 +5410,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5404 | 5410 | if (!self.wantSafety()) |
| 5405 | 5411 | return; // The already existing value will do just fine. |
| 5406 | 5412 | // TODO Upgrade this to a memset call when we have that available. |
| 5407 | | switch (ty.abiSize(self.target.*)) { |
| 5413 | switch (abi_size) { |
| 5408 | 5414 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), |
| 5409 | 5415 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 5410 | 5416 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| ... | ... | @@ -5426,6 +5432,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5426 | 5432 | .register => |reg| { |
| 5427 | 5433 | switch (abi_size) { |
| 5428 | 5434 | 1, 2, 4, 8 => { |
| 5435 | assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size)); |
| 5436 | |
| 5429 | 5437 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 5430 | 5438 | 1 => .strb_stack, |
| 5431 | 5439 | 2 => .strh_stack, |
| ... | ... | @@ -5438,7 +5446,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 5438 | 5446 | .tag = tag, |
| 5439 | 5447 | .data = .{ .load_store_stack = .{ |
| 5440 | 5448 | .rt = rt, |
| 5441 | | .offset = @intCast(u32, stack_offset), |
| 5449 | .offset = stack_offset, |
| 5442 | 5450 | } }, |
| 5443 | 5451 | }); |
| 5444 | 5452 | }, |
| ... | ... | @@ -6001,9 +6009,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { |
| 6001 | 6009 | } |
| 6002 | 6010 | |
| 6003 | 6011 | fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { |
| 6004 | | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 6012 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6013 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| 6005 | 6014 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airShuffle for {}", .{self.target.cpu.arch}); |
| 6006 | | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 6015 | return self.finishAir(inst, result, .{ extra.a, extra.b, .none }); |
| 6007 | 6016 | } |
| 6008 | 6017 | |
| 6009 | 6018 | fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |