| ... | @@ -247,6 +247,31 @@ const BigTomb = struct { | ... | @@ -247,6 +247,31 @@ const BigTomb = struct { |
| 247 | log.debug("%{d} => {}", .{ bt.inst, result }); | 247 | log.debug("%{d} => {}", .{ bt.inst, result }); |
| 248 | const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1]; | 248 | const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1]; |
| 249 | branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result); | 249 | branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result); |
| | 250 | |
| | 251 | switch (result) { |
| | 252 | .register => |reg| { |
| | 253 | // In some cases (such as bitcast), an operand |
| | 254 | // may be the same MCValue as the result. If |
| | 255 | // that operand died and was a register, it |
| | 256 | // was freed by processDeath. We have to |
| | 257 | // "re-allocate" the register. |
| | 258 | if (bt.function.register_manager.isRegFree(reg)) { |
| | 259 | bt.function.register_manager.getRegAssumeFree(reg, bt.inst); |
| | 260 | } |
| | 261 | }, |
| | 262 | .register_c_flag, |
| | 263 | .register_v_flag, |
| | 264 | => |reg| { |
| | 265 | if (bt.function.register_manager.isRegFree(reg)) { |
| | 266 | bt.function.register_manager.getRegAssumeFree(reg, bt.inst); |
| | 267 | } |
| | 268 | bt.function.cpsr_flags_inst = bt.inst; |
| | 269 | }, |
| | 270 | .cpsr_flags => { |
| | 271 | bt.function.cpsr_flags_inst = bt.inst; |
| | 272 | }, |
| | 273 | else => {}, |
| | 274 | } |
| 250 | } | 275 | } |
| 251 | bt.function.finishAirBookkeeping(); | 276 | bt.function.finishAirBookkeeping(); |
| 252 | } | 277 | } |
| ... | @@ -332,7 +357,7 @@ pub fn generate( | ... | @@ -332,7 +357,7 @@ pub fn generate( |
| 332 | }; | 357 | }; |
| 333 | | 358 | |
| 334 | for (function.dbg_arg_relocs.items) |reloc| { | 359 | for (function.dbg_arg_relocs.items) |reloc| { |
| 335 | try function.genArgDbgInfo(reloc.inst, reloc.index, call_info.stack_byte_count); | 360 | try function.genArgDbgInfo(reloc.inst, reloc.index); |
| 336 | } | 361 | } |
| 337 | | 362 | |
| 338 | var mir = Mir{ | 363 | var mir = Mir{ |
| ... | @@ -351,7 +376,8 @@ pub fn generate( | ... | @@ -351,7 +376,8 @@ pub fn generate( |
| 351 | .prev_di_pc = 0, | 376 | .prev_di_pc = 0, |
| 352 | .prev_di_line = module_fn.lbrace_line, | 377 | .prev_di_line = module_fn.lbrace_line, |
| 353 | .prev_di_column = module_fn.lbrace_column, | 378 | .prev_di_column = module_fn.lbrace_column, |
| 354 | .prologue_stack_space = call_info.stack_byte_count + function.saved_regs_stack_space, | 379 | .stack_size = function.max_end_stack, |
| | 380 | .saved_regs_stack_space = function.saved_regs_stack_space, |
| 355 | }; | 381 | }; |
| 356 | defer emit.deinit(); | 382 | defer emit.deinit(); |
| 357 | | 383 | |
| ... | @@ -464,6 +490,7 @@ fn gen(self: *Self) !void { | ... | @@ -464,6 +490,7 @@ fn gen(self: *Self) !void { |
| 464 | const total_stack_size = self.max_end_stack + self.saved_regs_stack_space; | 490 | const total_stack_size = self.max_end_stack + self.saved_regs_stack_space; |
| 465 | const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align); | 491 | const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align); |
| 466 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; | 492 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; |
| | 493 | self.max_end_stack = stack_size; |
| 467 | if (Instruction.Operand.fromU32(stack_size)) |op| { | 494 | if (Instruction.Operand.fromU32(stack_size)) |op| { |
| 468 | self.mir_instructions.set(sub_reloc, .{ | 495 | self.mir_instructions.set(sub_reloc, .{ |
| 469 | .tag = .sub, | 496 | .tag = .sub, |
| ... | @@ -1812,7 +1839,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV | ... | @@ -1812,7 +1839,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV |
| 1812 | switch (error_union_mcv) { | 1839 | switch (error_union_mcv) { |
| 1813 | .register => return self.fail("TODO errUnionErr for registers", .{}), | 1840 | .register => return self.fail("TODO errUnionErr for registers", .{}), |
| 1814 | .stack_argument_offset => |off| { | 1841 | .stack_argument_offset => |off| { |
| 1815 | return MCValue{ .stack_argument_offset = off - err_offset }; | 1842 | return MCValue{ .stack_argument_offset = off + err_offset }; |
| 1816 | }, | 1843 | }, |
| 1817 | .stack_offset => |off| { | 1844 | .stack_offset => |off| { |
| 1818 | return MCValue{ .stack_offset = off - err_offset }; | 1845 | return MCValue{ .stack_offset = off - err_offset }; |
| ... | @@ -1849,7 +1876,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) | ... | @@ -1849,7 +1876,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) |
| 1849 | switch (error_union_mcv) { | 1876 | switch (error_union_mcv) { |
| 1850 | .register => return self.fail("TODO errUnionPayload for registers", .{}), | 1877 | .register => return self.fail("TODO errUnionPayload for registers", .{}), |
| 1851 | .stack_argument_offset => |off| { | 1878 | .stack_argument_offset => |off| { |
| 1852 | return MCValue{ .stack_argument_offset = off - payload_offset }; | 1879 | return MCValue{ .stack_argument_offset = off + payload_offset }; |
| 1853 | }, | 1880 | }, |
| 1854 | .stack_offset => |off| { | 1881 | .stack_offset => |off| { |
| 1855 | return MCValue{ .stack_offset = off - payload_offset }; | 1882 | return MCValue{ .stack_offset = off - payload_offset }; |
| ... | @@ -1983,7 +2010,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1983,7 +2010,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1983 | .dead, .unreach => unreachable, | 2010 | .dead, .unreach => unreachable, |
| 1984 | .register => unreachable, // a slice doesn't fit in one register | 2011 | .register => unreachable, // a slice doesn't fit in one register |
| 1985 | .stack_argument_offset => |off| { | 2012 | .stack_argument_offset => |off| { |
| 1986 | break :result MCValue{ .stack_argument_offset = off - 4 }; | 2013 | break :result MCValue{ .stack_argument_offset = off + 4 }; |
| 1987 | }, | 2014 | }, |
| 1988 | .stack_offset => |off| { | 2015 | .stack_offset => |off| { |
| 1989 | break :result MCValue{ .stack_offset = off - 4 }; | 2016 | break :result MCValue{ .stack_offset = off - 4 }; |
| ... | @@ -2259,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2259,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2259 | .register_c_flag, | 2286 | .register_c_flag, |
| 2260 | .register_v_flag, | 2287 | .register_v_flag, |
| 2261 | => unreachable, // cannot hold an address | 2288 | => unreachable, // cannot hold an address |
| 2262 | .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }), | 2289 | .immediate => |imm| { |
| 2263 | .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }), | 2290 | try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }); |
| | 2291 | }, |
| | 2292 | .ptr_stack_offset => |off| { |
| | 2293 | try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }); |
| | 2294 | }, |
| 2264 | .register => |reg| { | 2295 | .register => |reg| { |
| 2265 | const reg_lock = self.register_manager.lockReg(reg); | 2296 | const reg_lock = self.register_manager.lockReg(reg); |
| 2266 | defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked); | 2297 | defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked); |
| 2267 | | 2298 | |
| 2268 | switch (dst_mcv) { | 2299 | switch (dst_mcv) { |
| 2269 | .dead => unreachable, | | |
| 2270 | .undef => unreachable, | | |
| 2271 | .cpsr_flags => unreachable, | | |
| 2272 | .register => |dst_reg| { | 2300 | .register => |dst_reg| { |
| 2273 | try self.genLdrRegister(dst_reg, reg, elem_ty); | 2301 | try self.genLdrRegister(dst_reg, reg, elem_ty); |
| 2274 | }, | 2302 | }, |
| ... | @@ -2304,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2304,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2304 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); | 2332 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); |
| 2305 | } | 2333 | } |
| 2306 | }, | 2334 | }, |
| 2307 | else => return self.fail("TODO load from register into {}", .{dst_mcv}), | 2335 | else => unreachable, // attempting to load into non-register or non-stack MCValue |
| 2308 | } | 2336 | } |
| 2309 | }, | 2337 | }, |
| 2310 | .memory, | 2338 | .memory, |
| ... | @@ -2401,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -2401,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2401 | // sub src_reg, fp, #off | 2429 | // sub src_reg, fp, #off |
| 2402 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); | 2430 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 2403 | }, | 2431 | }, |
| 2404 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), | 2432 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 2405 | .stack_argument_offset => |off| { | 2433 | .stack_argument_offset => |off| { |
| 2406 | _ = try self.addInst(.{ | 2434 | _ = try self.addInst(.{ |
| 2407 | .tag = .ldr_ptr_stack_argument, | 2435 | .tag = .ldr_ptr_stack_argument, |
| ... | @@ -2507,7 +2535,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2507,7 +2535,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2507 | switch (mcv) { | 2535 | switch (mcv) { |
| 2508 | .dead, .unreach => unreachable, | 2536 | .dead, .unreach => unreachable, |
| 2509 | .stack_argument_offset => |off| { | 2537 | .stack_argument_offset => |off| { |
| 2510 | break :result MCValue{ .stack_argument_offset = off - struct_field_offset }; | 2538 | break :result MCValue{ .stack_argument_offset = off + struct_field_offset }; |
| 2511 | }, | 2539 | }, |
| 2512 | .stack_offset => |off| { | 2540 | .stack_offset => |off| { |
| 2513 | break :result MCValue{ .stack_offset = off - struct_field_offset }; | 2541 | break :result MCValue{ .stack_offset = off - struct_field_offset }; |
| ... | @@ -3347,6 +3375,102 @@ fn genInlineMemcpy( | ... | @@ -3347,6 +3375,102 @@ fn genInlineMemcpy( |
| 3347 | // end: | 3375 | // end: |
| 3348 | } | 3376 | } |
| 3349 | | 3377 | |
| | 3378 | fn genInlineMemset( |
| | 3379 | self: *Self, |
| | 3380 | dst: MCValue, |
| | 3381 | val: MCValue, |
| | 3382 | len: MCValue, |
| | 3383 | ) !void { |
| | 3384 | const dst_reg = switch (dst) { |
| | 3385 | .register => |r| r, |
| | 3386 | else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst), |
| | 3387 | }; |
| | 3388 | const dst_reg_lock = self.register_manager.lockReg(dst_reg); |
| | 3389 | defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3390 | |
| | 3391 | const val_reg = switch (val) { |
| | 3392 | .register => |r| r, |
| | 3393 | else => try self.copyToTmpRegister(Type.initTag(.u8), val), |
| | 3394 | }; |
| | 3395 | const val_reg_lock = self.register_manager.lockReg(val_reg); |
| | 3396 | defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3397 | |
| | 3398 | const len_reg = switch (len) { |
| | 3399 | .register => |r| r, |
| | 3400 | else => try self.copyToTmpRegister(Type.usize, len), |
| | 3401 | }; |
| | 3402 | const len_reg_lock = self.register_manager.lockReg(len_reg); |
| | 3403 | defer if (len_reg_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3404 | |
| | 3405 | const count_reg = try self.register_manager.allocReg(null, gp); |
| | 3406 | |
| | 3407 | try self.genInlineMemsetCode(dst_reg, val_reg, len_reg, count_reg); |
| | 3408 | } |
| | 3409 | |
| | 3410 | fn genInlineMemsetCode( |
| | 3411 | self: *Self, |
| | 3412 | dst: Register, |
| | 3413 | val: Register, |
| | 3414 | len: Register, |
| | 3415 | count: Register, |
| | 3416 | ) !void { |
| | 3417 | // mov count, #0 |
| | 3418 | _ = try self.addInst(.{ |
| | 3419 | .tag = .mov, |
| | 3420 | .data = .{ .rr_op = .{ |
| | 3421 | .rd = count, |
| | 3422 | .rn = .r0, |
| | 3423 | .op = Instruction.Operand.imm(0, 0), |
| | 3424 | } }, |
| | 3425 | }); |
| | 3426 | |
| | 3427 | // loop: |
| | 3428 | // cmp count, len |
| | 3429 | _ = try self.addInst(.{ |
| | 3430 | .tag = .cmp, |
| | 3431 | .data = .{ .rr_op = .{ |
| | 3432 | .rd = .r0, |
| | 3433 | .rn = count, |
| | 3434 | .op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none), |
| | 3435 | } }, |
| | 3436 | }); |
| | 3437 | |
| | 3438 | // bge end |
| | 3439 | _ = try self.addInst(.{ |
| | 3440 | .tag = .b, |
| | 3441 | .cond = .ge, |
| | 3442 | .data = .{ .inst = @intCast(u32, self.mir_instructions.len + 4) }, |
| | 3443 | }); |
| | 3444 | |
| | 3445 | // strb val, [src, count] |
| | 3446 | _ = try self.addInst(.{ |
| | 3447 | .tag = .strb, |
| | 3448 | .data = .{ .rr_offset = .{ |
| | 3449 | .rt = val, |
| | 3450 | .rn = dst, |
| | 3451 | .offset = .{ .offset = Instruction.Offset.reg(count, .none) }, |
| | 3452 | } }, |
| | 3453 | }); |
| | 3454 | |
| | 3455 | // add count, count, #1 |
| | 3456 | _ = try self.addInst(.{ |
| | 3457 | .tag = .add, |
| | 3458 | .data = .{ .rr_op = .{ |
| | 3459 | .rd = count, |
| | 3460 | .rn = count, |
| | 3461 | .op = Instruction.Operand.imm(1, 0), |
| | 3462 | } }, |
| | 3463 | }); |
| | 3464 | |
| | 3465 | // b loop |
| | 3466 | _ = try self.addInst(.{ |
| | 3467 | .tag = .b, |
| | 3468 | .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 4) }, |
| | 3469 | }); |
| | 3470 | |
| | 3471 | // end: |
| | 3472 | } |
| | 3473 | |
| 3350 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, | 3474 | /// Adds a Type to the .debug_info at the current position. The bytes will be populated later, |
| 3351 | /// after codegen for this symbol is done. | 3475 | /// after codegen for this symbol is done. |
| 3352 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { | 3476 | fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { |
| ... | @@ -3369,9 +3493,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { | ... | @@ -3369,9 +3493,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void { |
| 3369 | } | 3493 | } |
| 3370 | } | 3494 | } |
| 3371 | | 3495 | |
| 3372 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void { | 3496 | fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void { |
| 3373 | const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space; | | |
| 3374 | | | |
| 3375 | const mcv = self.args[arg_index]; | 3497 | const mcv = self.args[arg_index]; |
| 3376 | const ty = self.air.instructions.items(.data)[inst].ty; | 3498 | const ty = self.air.instructions.items(.data)[inst].ty; |
| 3377 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); | 3499 | const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index); |
| ... | @@ -3404,7 +3526,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c | ... | @@ -3404,7 +3526,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c |
| 3404 | // const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | 3526 | // const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3405 | const adjusted_stack_offset = switch (mcv) { | 3527 | const adjusted_stack_offset = switch (mcv) { |
| 3406 | .stack_offset => |offset| -@intCast(i32, offset), | 3528 | .stack_offset => |offset| -@intCast(i32, offset), |
| 3407 | .stack_argument_offset => |offset| @intCast(i32, prologue_stack_space - offset), | 3529 | .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), |
| 3408 | else => unreachable, | 3530 | else => unreachable, |
| 3409 | }; | 3531 | }; |
| 3410 | | 3532 | |
| ... | @@ -3524,7 +3646,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3524,7 +3646,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3524 | try self.register_manager.getReg(reg, null); | 3646 | try self.register_manager.getReg(reg, null); |
| 3525 | } | 3647 | } |
| 3526 | | 3648 | |
| 3527 | if (info.return_value == .stack_offset) { | 3649 | // If returning by reference, r0 will contain the address of where |
| | 3650 | // to put the result into. In that case, make sure that r0 remains |
| | 3651 | // untouched by the parameter passing code |
| | 3652 | const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: { |
| 3528 | log.debug("airCall: return by reference", .{}); | 3653 | log.debug("airCall: return by reference", .{}); |
| 3529 | const ret_ty = fn_ty.fnReturnType(); | 3654 | const ret_ty = fn_ty.fnReturnType(); |
| 3530 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 3655 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| ... | @@ -3540,7 +3665,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3540,7 +3665,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3540 | try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset }); | 3665 | try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset }); |
| 3541 | | 3666 | |
| 3542 | info.return_value = .{ .stack_offset = stack_offset }; | 3667 | info.return_value = .{ .stack_offset = stack_offset }; |
| 3543 | } | 3668 | |
| | 3669 | break :blk self.register_manager.lockRegAssumeUnused(.r0); |
| | 3670 | } else null; |
| | 3671 | defer if (r0_lock) |reg| self.register_manager.unlockReg(reg); |
| 3544 | | 3672 | |
| 3545 | // Make space for the arguments passed via the stack | 3673 | // Make space for the arguments passed via the stack |
| 3546 | self.max_end_stack += info.stack_byte_count; | 3674 | self.max_end_stack += info.stack_byte_count; |
| ... | @@ -3559,7 +3687,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3559,7 +3687,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3559 | .stack_offset => unreachable, | 3687 | .stack_offset => unreachable, |
| 3560 | .stack_argument_offset => |offset| try self.genSetStackArgument( | 3688 | .stack_argument_offset => |offset| try self.genSetStackArgument( |
| 3561 | arg_ty, | 3689 | arg_ty, |
| 3562 | info.stack_byte_count - offset, | 3690 | offset, |
| 3563 | arg_mcv, | 3691 | arg_mcv, |
| 3564 | ), | 3692 | ), |
| 3565 | else => unreachable, | 3693 | else => unreachable, |
| ... | @@ -4621,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -4621,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4621 | if (!self.wantSafety()) | 4749 | if (!self.wantSafety()) |
| 4622 | return; // The already existing value will do just fine. | 4750 | return; // The already existing value will do just fine. |
| 4623 | // TODO Upgrade this to a memset call when we have that available. | 4751 | // TODO Upgrade this to a memset call when we have that available. |
| 4624 | switch (ty.abiSize(self.target.*)) { | 4752 | switch (abi_size) { |
| 4625 | 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), | 4753 | 1 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }), |
| 4626 | 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), | 4754 | 2 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 4627 | 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), | 4755 | 4 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| 4628 | else => return self.fail("TODO implement memset", .{}), | 4756 | else => try self.genInlineMemset( |
| | 4757 | .{ .ptr_stack_offset = stack_offset }, |
| | 4758 | .{ .immediate = 0xaa }, |
| | 4759 | .{ .immediate = abi_size }, |
| | 4760 | ), |
| 4629 | } | 4761 | } |
| 4630 | }, | 4762 | }, |
| 4631 | .cpsr_flags, | 4763 | .cpsr_flags, |
| ... | @@ -5037,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -5037,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 5037 | return; // The already existing value will do just fine. | 5169 | return; // The already existing value will do just fine. |
| 5038 | // TODO Upgrade this to a memset call when we have that available. | 5170 | // TODO Upgrade this to a memset call when we have that available. |
| 5039 | switch (abi_size) { | 5171 | switch (abi_size) { |
| 5040 | 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }), | 5172 | 1 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }), |
| 5041 | 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }), | 5173 | 2 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 5042 | 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), | 5174 | 4 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| 5043 | else => return self.fail("TODO implement memset", .{}), | 5175 | else => return self.fail("TODO implement memset", .{}), |
| 5044 | } | 5176 | } |
| 5045 | }, | 5177 | }, |
| ... | @@ -5653,8 +5785,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -5653,8 +5785,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 5653 | if (ty.abiAlignment(self.target.*) == 8) | 5785 | if (ty.abiAlignment(self.target.*) == 8) |
| 5654 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); | 5786 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); |
| 5655 | | 5787 | |
| 5656 | nsaa += param_size; | | |
| 5657 | result.args[i] = .{ .stack_argument_offset = nsaa }; | 5788 | result.args[i] = .{ .stack_argument_offset = nsaa }; |
| | 5789 | nsaa += param_size; |
| 5658 | } | 5790 | } |
| 5659 | } | 5791 | } |
| 5660 | | 5792 | |
| ... | @@ -5687,9 +5819,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -5687,9 +5819,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 5687 | for (param_types) |ty, i| { | 5819 | for (param_types) |ty, i| { |
| 5688 | if (ty.abiSize(self.target.*) > 0) { | 5820 | if (ty.abiSize(self.target.*) > 0) { |
| 5689 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 5821 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| | 5822 | const param_alignment = ty.abiAlignment(self.target.*); |
| 5690 | | 5823 | |
| 5691 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)) + param_size; | 5824 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment); |
| 5692 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 5825 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
| | 5826 | stack_offset += param_size; |
| 5693 | } else { | 5827 | } else { |
| 5694 | result.args[i] = .{ .none = {} }; | 5828 | result.args[i] = .{ .none = {} }; |
| 5695 | } | 5829 | } |