aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/Sparc/SparcCallingConv.td
blob: a181bcf3d2636951a1a9e2fbd25113ad731145bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//===-- SparcCallingConv.td - Calling Conventions Sparc ----*- tablegen -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This describes the calling conventions for the Sparc architectures.
//
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// SPARC v8 32-bit.
//===----------------------------------------------------------------------===//

def CC_Sparc32 : CallingConv<[
  // Custom assign SRet to [sp+64].
  CCIfSRet<CCCustom<"CC_Sparc_Assign_SRet">>,
  // i32 f32 arguments get passed in integer registers if there is space.
  CCIfType<[i32, f32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
  // f64 arguments are split and passed through registers or through stack.
  CCIfType<[f64], CCCustom<"CC_Sparc_Assign_f64">>,

  // Alternatively, they are assigned to the stack in 4-byte aligned units.
  CCAssignToStack<4, 4>
]>;

def RetCC_Sparc32 : CallingConv<[
  CCIfType<[i32], CCAssignToReg<[I0, I1, I2, I3, I4, I5]>>,
  CCIfType<[f32], CCAssignToReg<[F0, F1, F2, F3]>>,
  CCIfType<[f64], CCAssignToReg<[D0, D1]>>
]>;


//===----------------------------------------------------------------------===//
// SPARC v9 64-bit.
//===----------------------------------------------------------------------===//
//
// The 64-bit ABI conceptually assigns all function arguments to a parameter
// array starting at [%fp+BIAS+128] in the callee's stack frame. All arguments
// occupy a multiple of 8 bytes in the array. Integer arguments are extended to
// 64 bits by the caller. Floats are right-aligned in their 8-byte slot, the
// first 4 bytes in the slot are undefined.
//
// The integer registers %i0 to %i5 shadow the first 48 bytes of the parameter
// array at fixed offsets. Integer arguments are promoted to registers when
// possible.
//
// The floating point registers %f0 to %f31 shadow the first 128 bytes of the
// parameter array at fixed offsets. Float and double parameters are promoted
// to these registers when possible.
//
// Structs up to 16 bytes in size are passed by value. They are right-aligned
// in one or two 8-byte slots in the parameter array. Struct members are
// promoted to both floating point and integer registers when possible. A
// struct containing two floats would thus be passed in %f0 and %f1, while two
// float function arguments would occupy 8 bytes each, and be passed in %f1 and
// %f3.
//
// When a struct { int, float } is passed by value, the int goes in the high
// bits of an integer register while the float goes in a floating point
// register.
//
// The difference is encoded in LLVM IR using the inreg atttribute on function
// arguments:
//
//   C:   void f(float, float);
//   IR:  declare void f(float %f1, float %f3)
//
//   C:   void f(struct { float f0, f1; });
//   IR:  declare void f(float inreg %f0, float inreg %f1)
//
//   C:   void f(int, float);
//   IR:  declare void f(int signext %i0, float %f3)
//
//   C:   void f(struct { int i0high; float f1; });
//   IR:  declare void f(i32 inreg %i0high, float inreg %f1)
//
// Two ints in a struct are simply coerced to i64:
//
//   C:   void f(struct { int i0high, i0low; });
//   IR:  declare void f(i64 %i0.coerced)
//
// The frontend and backend divide the task of producing ABI compliant code for
// C functions. The C frontend will:
//
//  - Annotate integer arguments with zeroext or signext attributes.
//
//  - Split structs into one or two 64-bit sized chunks, or 32-bit chunks with
//    inreg attributes.
//
//  - Pass structs larger than 16 bytes indirectly with an explicit pointer
//    argument. The byval attribute is not used.
//
// The backend will:
//
//  - Assign all arguments to 64-bit aligned stack slots, 32-bits for inreg.
//
//  - Promote to integer or floating point registers depending on type.
//
// Function return values are passed exactly like function arguments, except a
// struct up to 32 bytes in size can be returned in registers.

// Function arguments AND return values.
def CC_Sparc64 : CallingConv<[
  // The frontend uses the inreg flag to indicate i32 and float arguments from
  // structs. These arguments are not promoted to 64 bits, but they can still
  // be assigned to integer and float registers.
  CCIfInReg<CCIfType<[i32, f32], CCCustom<"CC_Sparc64_Half">>>,

  // All integers are promoted to i64 by the caller.
  CCIfType<[i32], CCPromoteToType<i64>>,

  // Custom assignment is required because stack space is reserved for all
  // arguments whether they are passed in registers or not.
  CCCustom<"CC_Sparc64_Full">
]>;