Class: Rubycc::IR::AAPCS64Convention

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

Overview

AAPCS64 (Procedure Call Standard for the Arm 64-bit Architecture, 6.4.2).

Defined Under Namespace

Classes: Placer

Constant Summary collapse

MAX_HFA_MEMBERS =

The most members a homogeneous floating aggregate may have and still travel in vector registers (6.4.2 stage B: "at most four uniquely addressable members"). A fifth member sends the whole aggregate by reference, however small each member is.

4
MAX_REGISTER_AGGREGATE =

The largest aggregate that is passed in integer registers rather than by reference. An HFA is exempt: four doubles are 32 bytes and still ride d0..d3.

16

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

#initializeAAPCS64Convention

Returns a new instance of AAPCS64Convention.



318
319
320
321
322
# File 'lib/rubycc/ir/call_convention.rb', line 318

def initialize
  super(gp_registers: 8, fp_registers: 8, hidden_result_kind: :indirect_result,
        va_list_tag: Type::AArch64VaListTag, va_list_type: Type::AArch64BuiltinVaList,
        va_list_abi: :aapcs64)
end

Instance Method Details

#aggregate_plan(type) ⇒ Object

Classifies an aggregate by AAPCS64 6.4.2, in the order the standard tests it:

  • a Homogeneous Floating-point Aggregate — every scalar in it, however deeply nested, is the same floating type, and there are at most four of them — puts each member in a vector register of its own. This is the rule with no System V counterpart at all: struct { float a, b; } is s0 and s1 here where System V packs both into one xmm0.
  • any other aggregate of 16 bytes or less takes one or two consecutive integer registers, whatever its members are (a packed struct included: AAPCS64 has no unaligned-field escape to memory). One whose alignment is 16 must start at an even-numbered register, which is what align16 asks the placer for.
  • anything larger travels by reference: the caller copies it and passes the copy's address.


339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/rubycc/ir/call_convention.rb', line 339

def aggregate_plan(type)
  base, count = homogeneous_float(type)
  if base && count <= MAX_HFA_MEMBERS && type.size == base * count
    kind = base == 8 ? :sse8 : :sse4
    pieces = Array.new(count) { |i| AbiPiece.new(offset: base * i, size: base, kind: kind) }
    return AggregatePlan.new(mode: :registers, pieces: pieces, align16: false)
  end

  if type.size <= MAX_REGISTER_AGGREGATE
    pieces = Array.new((type.size + 7) / 8) { |i| AbiPiece.new(offset: 8 * i, size: 8, kind: :gp) }
    return AggregatePlan.new(mode: :registers, pieces: pieces, align16: type.alignment >= 16)
  end

  AggregatePlan.new(mode: :by_reference, pieces: [], align16: false)
end

#placerObject



355
356
357
# File 'lib/rubycc/ir/call_convention.rb', line 355

def placer
  Placer.new(self)
end