Class: Rubycc::IR::CallConvention
- Inherits:
-
Object
- Object
- Rubycc::IR::CallConvention
- Defined in:
- lib/rubycc/ir/call_convention.rb,
lib/rubycc/ir/call_convention.rb
Overview
The part of a target's calling convention the IR generator has to know about, so that where every argument lands is decided once — where the argument's C type is still in hand — rather than guessed at by a backend that only sees a tag.
Three things are target-specific and all three live here:
-
how many registers there are to hand out. System V AMD64 offers six integer registers (rdi, rsi, rdx, rcx, r8, r9) and AAPCS64 eight (x0..x7); both offer eight vector ones. Getting the counts from the target is what lets a seventh integer argument reach x6 on aarch64 instead of arriving tagged for the stack.
-
how an aggregate is cut up and where the pieces go (#aggregate_plan). The System V eightbyte classification and the AAPCS64 HFA / 16-byte / by-reference rules disagree in ways that are silent when guessed at: struct { float a, b; } is one SSE eightbyte in xmm0 under System V and two single-precision registers, s0 and s1, under AAPCS64.
-
how the register files are consumed as the argument list is walked (#placer). Both conventions place an argument as a unit, but they differ on what happens when one does not fit: System V leaves the registers it did not use available to a later argument, while AAPCS64 declares the file exhausted (6.4.2 stage C sets NGRN or NSRN to eight), so a trailing int after a spilled two-register struct is in a register on x86-64 and on the stack on aarch64.
hidden_result_kind is the kind of the implicit pointer to a
caller-provided result buffer: an ordinary leading integer argument under
System V, and its own mechanism (:indirect_result, the x8 register) under
AAPCS64.
The va_list_* trio is the fourth target-specific thing the convention
owns, and it belongs here for the same reason the others do: a va_list
walks exactly the register/stack layout the convention laid a call's
arguments out in, so the shape of the tag, the type the front end declares
__builtin_va_list to name, and the flavour of the va_arg walk are all
facets of the one ABI. va_list_abi is a plain tag (:system_v / :aapcs64)
the generator switches its va_arg lowering on: the two walks read a
different structure with the offsets running opposite ways, so they are
kept as separate lowerings rather than one merged over a descriptor — and
keeping the System V path untouched is what guarantees its emitted code
does not shift by a byte.
Direct Known Subclasses
Constant Summary collapse
- SYSTEM_V_AMD64 =
SystemVAMD64Convention.new
- AAPCS64 =
AAPCS64Convention.new
Instance Attribute Summary collapse
-
#fp_registers ⇒ Object
readonly
Returns the value of attribute fp_registers.
-
#gp_registers ⇒ Object
readonly
Returns the value of attribute gp_registers.
-
#hidden_result_kind ⇒ Object
readonly
Returns the value of attribute hidden_result_kind.
-
#va_list_abi ⇒ Object
readonly
Returns the value of attribute va_list_abi.
-
#va_list_tag ⇒ Object
readonly
Returns the value of attribute va_list_tag.
-
#va_list_type ⇒ Object
readonly
Returns the value of attribute va_list_type.
Class Method Summary collapse
-
.memory_pieces(size) ⇒ Object
The pieces a value of
sizebytes is cut into when it travels in the stack argument area.
Instance Method Summary collapse
-
#aggregate_plan(_type) ⇒ Object
The convention's plan for passing an aggregate of
typeby value. -
#initialize(gp_registers:, fp_registers:, va_list_tag:, va_list_type:, va_list_abi:, hidden_result_kind: :gp) ⇒ CallConvention
constructor
A new instance of CallConvention.
-
#placer ⇒ Object
A fresh running placement of one argument list (see the Placer classes).
Constructor Details
#initialize(gp_registers:, fp_registers:, va_list_tag:, va_list_type:, va_list_abi:, hidden_result_kind: :gp) ⇒ CallConvention
Returns a new instance of CallConvention.
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubycc/ir/call_convention.rb', line 97 def initialize(gp_registers:, fp_registers:, va_list_tag:, va_list_type:, va_list_abi:, hidden_result_kind: :gp) @gp_registers = gp_registers @fp_registers = fp_registers @hidden_result_kind = hidden_result_kind @va_list_tag = va_list_tag @va_list_type = va_list_type @va_list_abi = va_list_abi freeze end |
Instance Attribute Details
#fp_registers ⇒ Object (readonly)
Returns the value of attribute fp_registers.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def fp_registers @fp_registers end |
#gp_registers ⇒ Object (readonly)
Returns the value of attribute gp_registers.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def gp_registers @gp_registers end |
#hidden_result_kind ⇒ Object (readonly)
Returns the value of attribute hidden_result_kind.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def hidden_result_kind @hidden_result_kind end |
#va_list_abi ⇒ Object (readonly)
Returns the value of attribute va_list_abi.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def va_list_abi @va_list_abi end |
#va_list_tag ⇒ Object (readonly)
Returns the value of attribute va_list_tag.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def va_list_tag @va_list_tag end |
#va_list_type ⇒ Object (readonly)
Returns the value of attribute va_list_type.
94 95 96 |
# File 'lib/rubycc/ir/call_convention.rb', line 94 def va_list_type @va_list_type end |
Class Method Details
.memory_pieces(size) ⇒ Object
The pieces a value of size bytes is cut into when it travels in the
stack argument area. Both conventions round a stack argument up to a
multiple of eight and align it to at least eight, so a spilled value is
ceil(size/8) whole eightbytes whatever shape it would have taken in
registers — an aarch64 HFA that runs out of vector registers is passed
as packed eightbytes, not as one stack slot per member.
114 115 116 |
# File 'lib/rubycc/ir/call_convention.rb', line 114 def self.memory_pieces(size) Array.new((size + 7) / 8) { |i| AbiPiece.new(offset: 8 * i, size: 8, kind: :mem) } end |
Instance Method Details
#aggregate_plan(_type) ⇒ Object
The convention's plan for passing an aggregate of type by value.
119 120 121 |
# File 'lib/rubycc/ir/call_convention.rb', line 119 def aggregate_plan(_type) raise NotImplementedError end |
#placer ⇒ Object
A fresh running placement of one argument list (see the Placer classes).
124 125 126 |
# File 'lib/rubycc/ir/call_convention.rb', line 124 def placer raise NotImplementedError end |