Class: Rubycc::IR::SystemVAMD64Convention

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

Overview

System V AMD64 (psABI 3.2.3).

Defined Under Namespace

Classes: Placer

Constant Summary

Constants inherited from CallConvention

CallConvention::AAPCS64, CallConvention::SYSTEM_V_AMD64

Instance Attribute Summary

Attributes inherited from CallConvention

#fp_registers, #gp_registers, #hidden_result_kind, #va_list_abi, #va_list_tag, #va_list_type

Instance Method Summary collapse

Methods inherited from CallConvention

memory_pieces

Constructor Details

#initializeSystemVAMD64Convention

Returns a new instance of SystemVAMD64Convention.



131
132
133
134
135
# File 'lib/rubycc/ir/call_convention.rb', line 131

def initialize
  super(gp_registers: 6, fp_registers: 8,
        va_list_tag: Type::VaListTag, va_list_type: Type::BuiltinVaList,
        va_list_abi: :system_v)
end

Instance Method Details

#aggregate_plan(type) ⇒ Object

Classifies an aggregate by the psABI's eightbyte rules. A struct or union larger than two eightbytes — or one with any unaligned field — is passed in memory; otherwise each of its one or two eightbytes gets a class from the scalar fields that fall in it, :gp for an INTEGER eightbyte and :sse8 for an SSE one (moved as a full 8-byte double even when it holds two packed floats, since a single movsd carries the whole eightbyte).

The unaligned-field test is what a GNU attribute((packed)) demands (Step 28): the psABI gives an aggregate "containing unaligned fields" class MEMORY, and gcc follows it — a packed struct whose field would straddle an eightbyte boundary is passed on the stack, not in registers. Every non-packed layout here is naturally aligned, so this only ever fires for a packed struct. (AAPCS64 has no such rule, which is one more reason the classification cannot be shared.)



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/rubycc/ir/call_convention.rb', line 152

def aggregate_plan(type)
  size = type.size
  # A 16-byte-aligned aggregate (one holding an __int128, or _Alignas(16))
  # is placed on a 16-byte-aligned stack slot when it spills, so its plan
  # carries the alignment for the placer to pad NSAA up to — even for a
  # MEMORY-class aggregate, whose stack slot the psABI aligns the same way.
  align16 = type.alignment >= 16
  if size > 16 || unaligned_field?(type, 0)
    return AggregatePlan.new(mode: :memory, pieces: CallConvention.memory_pieces(size), align16: align16)
  end

  eightbytes = Array.new((size + 7) / 8, nil)
  classify_eightbytes(eightbytes, type, 0)
  # A NO_CLASS eightbyte (only padding fell in it) defaults to SSE, the
  # psABI's benign choice; INTEGER otherwise wins over SSE per #merge_class.
  pieces = eightbytes.each_with_index.map do |cls, i|
    AbiPiece.new(offset: 8 * i, size: 8, kind: cls == :integer ? :gp : :sse8)
  end
  AggregatePlan.new(mode: :registers, pieces: pieces, align16: align16)
end

#placerObject



173
174
175
# File 'lib/rubycc/ir/call_convention.rb', line 173

def placer
  Placer.new(self)
end