Class: Rubycc::IR::AAPCS64Convention::Placer

Inherits:
Object
  • Object
show all
Defined in:
lib/rubycc/ir/call_convention.rb

Overview

Hands out x0..x7 and v0..v7 over one argument list, by 6.4.2 stage C. An argument never draws on both files here (a scalar is one or the other, an HFA is all vector, every other aggregate all integer, and an aggregate passed by reference is just a pointer), so the two counters advance independently.

The difference from System V that matters is what an argument that does not fit leaves behind: the standard sets NGRN (or NSRN) to eight, so the file it overflowed is exhausted and every later argument of that class goes to the stack as well. The other file is untouched — a spilled HFA does not stop a following int from reaching x0.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(convention) ⇒ Placer

Returns a new instance of Placer.



418
419
420
421
422
423
424
425
# File 'lib/rubycc/ir/call_convention.rb', line 418

def initialize(convention)
  @convention = convention
  @ngrn = 0
  @nsrn = 0
  @nsaa = 0        # next stacked argument, counted in eightbytes (NSAA/8)
  @pad_gp = 0
  @pad_stack = 0
end

Instance Attribute Details

#pad_gpObject (readonly)

The alignment padding the most recent #place inserted before the argument it placed: one integer register (pad_gp) when a 16-byte aligned aggregate rounded NGRN up over an odd register so it lands in an aligned x-register pair (6.4.2 stage C.4), or one stack eightbyte (pad_stack) when such an aggregate spilled onto an odd stack offset and had to start at a 16-byte boundary (stage C.13's NSAA alignment). At most one is ever nonzero. The generator reads them to emit a matching pad slot, so the backend's sequential register/stack handout skips the same place the standard reserves.



436
437
438
# File 'lib/rubycc/ir/call_convention.rb', line 436

def pad_gp
  @pad_gp
end

#pad_stackObject (readonly)

The alignment padding the most recent #place inserted before the argument it placed: one integer register (pad_gp) when a 16-byte aligned aggregate rounded NGRN up over an odd register so it lands in an aligned x-register pair (6.4.2 stage C.4), or one stack eightbyte (pad_stack) when such an aggregate spilled onto an odd stack offset and had to start at a 16-byte boundary (stage C.13's NSAA alignment). At most one is ever nonzero. The generator reads them to emit a matching pad slot, so the backend's sequential register/stack handout skips the same place the standard reserves.



436
437
438
# File 'lib/rubycc/ir/call_convention.rb', line 436

def pad_stack
  @pad_stack
end

Instance Method Details

#place(request) ⇒ Object



438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/rubycc/ir/call_convention.rb', line 438

def place(request)
  @pad_gp = 0
  @pad_stack = 0
  need_fp = request.kinds.count { |kind| kind == :sse4 || kind == :sse8 }
  return place_fp(need_fp, request.mem_eightbytes) if need_fp.positive?

  need_gp = request.kinds.count(:gp)
  return place_gp(need_gp, request.align16, request.mem_eightbytes) if need_gp.positive?

  # An :indirect_result pointer rides a register of its own (x8), which
  # is not part of either file's budget.
  :registers
end