Mercurial > projects > ldc
annotate gen/abi-x86-64.cpp @ 1111:0f8aeb31678c
Fix 32bit "+2" typo for Outbuffer::reserve
author | Kelly Wilson <wilsonk cpsc.ucalgary.ca> |
---|---|
date | Fri, 13 Mar 2009 07:17:29 -0600 |
parents | 40d7f9b7357f |
children | f2f13f111e2e |
rev | line source |
---|---|
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
1 /* TargetABI implementation for x86-64. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
2 * Written for LDC by Frits van Bommel in 2009. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
3 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
4 * extern(D) follows no particular external ABI, but tries to be smart about |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
5 * passing structs and returning them. It should probably be reviewed if the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
6 * way LLVM implements fastcc on this platform ever changes. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
7 * (Specifically, the number of return registers of various types is hardcoded) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
8 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
9 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
10 * extern(C) implements the C calling convention for x86-64, as found in |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
11 * http://www.x86-64.org/documentation/abi-0.99.pdf |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
12 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
13 * Note: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
14 * Where a discrepancy was found between llvm-gcc and the ABI documentation, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
15 * llvm-gcc behavior was used for compatibility (after it was verified that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
16 * regular gcc has the same behavior). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
17 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
18 * LLVM gets it right for most types, but complex numbers and structs need some |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
19 * help. To make sure it gets those right we essentially bitcast small structs |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
20 * to a type to which LLVM assigns the appropriate registers, and pass that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
21 * instead. Structs that are required to be passed in memory are explicitly |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
22 * marked with the ByVal attribute to ensure no part of them ends up in |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
23 * registers when only a subset of the desired registers are available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
24 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
25 * We don't perform the same transformation for D-specific types that contain |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
26 * multiple parts, such as dynamic arrays and delegates. They're passed as if |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
27 * the parts were passed as separate parameters. This helps make things like |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
28 * printf("%.*s", o.toString()) work as expected; if we didn't do this that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
29 * wouldn't work if there were 4 other integer/pointer arguments before the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
30 * toString() call because the string got bumped to memory with one integer |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
31 * register still free. Keeping it untransformed puts the length in a register |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
32 * and the pointer in memory, as printf expects it. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
33 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
34 |
1063
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
35 #include "mtype.h" |
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
36 #include "declaration.h" |
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
37 #include "aggregate.h" |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
38 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
39 #include "gen/llvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
40 #include "gen/tollvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
41 #include "gen/logger.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
42 #include "gen/dvalue.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
43 #include "gen/llvmhelpers.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
44 #include "gen/abi.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
45 #include "gen/abi-x86-64.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
46 #include "ir/irfunction.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
47 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
48 #include <cassert> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
49 #include <map> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
50 #include <string> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
51 #include <utility> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
52 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
53 // Implementation details for extern(C) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
54 namespace { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
55 /** |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
56 * This function helps filter out things that look like structs to C, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
57 * but should be passed to C in separate arguments anyway. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
58 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
59 * (e.g. dynamic arrays are passed as separate length and ptr. This |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
60 * is both less work and makes printf("%.*s", o.toString()) work) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
61 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
62 inline bool keepUnchanged(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
63 switch (t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
64 case Tarray: // dynamic array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
65 case Taarray: // assoc array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
66 case Tdelegate: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
67 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
68 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
69 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
70 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
71 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
72 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
73 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
74 enum ArgClass { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
75 Integer, Sse, SseUp, X87, X87Up, ComplexX87, NoClass, Memory |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
76 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
77 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
78 struct Classification { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
79 bool isMemory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
80 ArgClass classes[2]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
81 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
82 Classification() : isMemory(false) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
83 classes[0] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
84 classes[1] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
85 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
86 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
87 void addField(unsigned offset, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
88 if (isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
89 return; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
90 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
91 // Note that we don't need to bother checking if it crosses 8 bytes. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
92 // We don't get here with unaligned fields, and anything that can be |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
93 // big enough to cross 8 bytes (cdoubles, reals, structs and arrays) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
94 // is special-cased in classifyType() |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
95 int idx = (offset < 8 ? 0 : 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
96 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
97 ArgClass nw = merge(classes[idx], cl); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
98 if (nw != classes[idx]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
99 classes[idx] = nw; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
100 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
101 if (nw == Memory) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
102 classes[1-idx] = Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
103 isMemory = true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
104 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
105 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
106 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
107 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
108 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
109 ArgClass merge(ArgClass accum, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
110 if (accum == cl) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
111 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
112 if (accum == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
113 return cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
114 if (cl == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
115 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
116 if (accum == Memory || cl == Memory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
117 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
118 if (accum == Integer || cl == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
119 return Integer; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
120 if (accum == X87 || accum == X87Up || accum == ComplexX87 || |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
121 cl == X87 || cl == X87Up || cl == ComplexX87) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
122 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
123 return Sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
124 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
125 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
126 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
127 void classifyType(Classification& accum, Type* ty, d_uns64 offset) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
128 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
129 Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
130 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
131 ty = ty->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
132 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
133 if (ty->isintegral() || ty->ty == Tpointer) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
134 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
135 } else if (ty->ty == Tfloat80 || ty->ty == Timaginary80) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
136 accum.addField(offset, X87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
137 accum.addField(offset+8, X87Up); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
138 } else if (ty->ty == Tcomplex80) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
139 accum.addField(offset, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
140 // make sure other half knows about it too: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
141 accum.addField(offset+16, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
142 } else if (ty->ty == Tcomplex64) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
143 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
144 accum.addField(offset+8, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
145 } else if (ty->ty == Tcomplex32) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
146 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
147 accum.addField(offset+4, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
148 } else if (ty->isfloating()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
149 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
150 } else if (ty->size() > 16 || hasUnalignedFields(ty)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
151 // This isn't creal, yet is > 16 bytes, so pass in memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
152 // Must be after creal case but before arrays and structs, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
153 // the other types that can get bigger than 16 bytes |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
154 accum.addField(offset, Memory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
155 } else if (ty->ty == Tsarray) { |
1054
a3d7288c4473
Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents:
1051
diff
changeset
|
156 Type* eltType = ty->nextOf(); |
a3d7288c4473
Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents:
1051
diff
changeset
|
157 d_uns64 eltsize = eltType->size(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
158 if (eltsize > 0) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
159 d_uns64 dim = ty->size() / eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
160 assert(dim <= 16 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
161 && "Array of non-empty type <= 16 bytes but > 16 elements?"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
162 for (d_uns64 i = 0; i < dim; i++) { |
1054
a3d7288c4473
Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents:
1051
diff
changeset
|
163 classifyType(accum, eltType, offset); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
164 offset += eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
165 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
166 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
167 } else if (ty->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
168 Array* fields = &((TypeStruct*) ty)->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
169 for (size_t i = 0; i < fields->dim; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
170 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
171 classifyType(accum, field->type, offset + field->offset); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
172 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
173 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
174 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
175 Logger::cout() << "x86-64 ABI: Implicitly handled type: " |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
176 << ty->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
177 // arrays, delegates, etc. (pointer-sized fields, <= 16 bytes) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
178 assert(offset == 0 || offset == 8 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
179 && "must be aligned and doesn't fit otherwise"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
180 assert(ty->size() % 8 == 0 && "Not a multiple of pointer size?"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
181 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
182 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
183 if (ty->size() > 8) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
184 accum.addField(offset+8, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
185 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
186 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
187 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
188 Classification classify(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
189 typedef std::map<Type*, Classification> ClassMap; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
190 static ClassMap cache; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
191 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
192 ClassMap::iterator it = cache.find(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
193 if (it != cache.end()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
194 return it->second; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
195 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
196 Classification cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
197 classifyType(cl, ty, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
198 cache[ty] = cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
199 return cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
200 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
201 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
202 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
203 /// Returns the type to pass as, or null if no transformation is needed. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
204 LLType* getAbiType(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
205 ty = ty->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
206 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
207 // First, check if there's any need of a transformation: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
208 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
209 if (keepUnchanged(ty)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
210 return 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
211 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
212 if (ty->ty != Tcomplex32 && ty->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
213 return 0; // Nothing to do, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
214 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
215 Classification cl = classify(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
216 assert(!cl.isMemory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
217 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
218 if (cl.classes[0] == NoClass) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
219 assert(cl.classes[1] == NoClass && "Non-empty struct with empty first half?"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
220 return 0; // Empty structs should also be handled correctly by LLVM |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
221 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
222 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
223 // Okay, we may need to transform. Figure out a canonical type: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
224 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
225 std::vector<const LLType*> parts; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
226 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
227 unsigned size = ty->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
228 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
229 switch (cl.classes[0]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
230 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
231 unsigned bits = (size >= 8 ? 64 : (size * 8)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
232 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
233 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
234 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
235 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
236 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
237 parts.push_back(size <= 4 ? LLType::FloatTy : LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
238 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
239 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
240 case X87: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
241 assert(cl.classes[1] == X87Up && "Upper half of real not X87Up?"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
242 /// The type only contains a single real/ireal field, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
243 /// so just use that type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
244 return const_cast<LLType*>(LLType::X86_FP80Ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
245 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
246 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
247 assert(0 && "Unanticipated argument class"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
248 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
249 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
250 switch(cl.classes[1]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
251 case NoClass: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
252 assert(parts.size() == 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
253 // No need to use a single-element struct type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
254 // Just use the element type instead. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
255 return const_cast<LLType*>(parts[0]); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
256 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
257 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
258 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
259 assert(size > 8); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
260 unsigned bits = (size - 8) * 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
261 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
262 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
263 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
264 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
265 parts.push_back(size <= 12 ? LLType::FloatTy : LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
266 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
267 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
268 case X87Up: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
269 if(cl.classes[0] == X87) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
270 // This won't happen: it was short-circuited while |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
271 // processing the first half. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
272 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
273 // I can't find this anywhere in the ABI documentation, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
274 // but this is what gcc does (both regular and llvm-gcc). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
275 // (This triggers for types like union { real r; byte b; }) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
276 parts.push_back(LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
277 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
278 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
279 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
280 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
281 assert(0 && "Unanticipated argument class for second half"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
282 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
283 return LLStructType::get(parts); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
284 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
285 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
286 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
287 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
288 // Implementation details for extern(D) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
289 namespace x86_64_D_cc { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
290 struct DRegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
291 unsigned ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
292 unsigned sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
293 unsigned x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
294 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
295 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
296 : ints(ints_), sse(sse_), x87(x87_) {} |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
297 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
298 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
299 // Count the number of registers needed for a simple type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
300 // (Not a struct or static array) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
301 DRegCount regsNeededForSimpleType(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
302 DRegCount r(0, 0, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
303 switch(t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
304 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
305 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
306 assert(0 && "Not a simple type!"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
307 // Return huge numbers if assertions are disabled, so it'll always get |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
308 // bumped to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
309 r.ints = r.sse = r.x87 = (unsigned)-1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
310 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
311 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
312 // Floats, doubles and such are passed in SSE registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
313 case Tfloat32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
314 case Tfloat64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
315 case Timaginary32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
316 case Timaginary64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
317 r.sse = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
318 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
319 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
320 case Tcomplex32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
321 case Tcomplex64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
322 r.sse = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
323 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
324 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
325 // Reals, ireals and creals are passed in x87 registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
326 case Tfloat80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
327 case Timaginary80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
328 r.x87 = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
329 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
330 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
331 case Tcomplex80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
332 r.x87 = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
333 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
334 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
335 // Anything else is passed in one or two integer registers, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
336 // depending on its size. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
337 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
338 int needed = (t->size() + 7) / 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
339 assert(needed <= 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
340 r.ints = needed; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
341 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
342 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
343 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
344 return r; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
345 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
346 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
347 // Returns true if it's possible (and a good idea) to pass the struct in the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
348 // specified number of registers. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
349 // (May return false if it's a bad idea to pass the type in registers for |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
350 // reasons other than it not fitting) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
351 // Note that if true is returned, 'left' is also modified to contain the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
352 // number of registers left. This property is used in the recursive case. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
353 // If false is returned, 'left' is garbage. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
354 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
355 // If it has unaligned fields, there's probably a reason for it, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
356 // so keep it in memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
357 if (hasUnalignedFields(t)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
358 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
359 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
360 Array* fields = &t->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
361 d_uns64 nextbyte = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
362 for (d_uns64 i = 0; i < fields->dim; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
363 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
364 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
365 // This depends on ascending order of field offsets in structs |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
366 // without overlapping fields. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
367 if (field->offset < nextbyte) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
368 // Don't return unions (or structs containing them) in registers. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
369 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
370 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
371 nextbyte = field->offset + field->type->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
372 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
373 switch (field->type->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
374 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
375 if (!shouldPassStructInRegs((TypeStruct*) field->type, left)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
376 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
377 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
378 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
379 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
380 // Don't return static arrays in registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
381 // (indexing registers doesn't work well) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
382 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
383 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
384 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
385 DRegCount needed = regsNeededForSimpleType(field->type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
386 if (needed.ints > left.ints || needed.sse > left.sse || needed.x87 > left.x87) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
387 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
388 left.ints -= needed.ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
389 left.sse -= needed.sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
390 left.x87 -= needed.x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
391 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
392 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
393 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
394 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
395 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
396 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
397 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
398 // Returns true if the struct fits in return registers in the x86-64 fastcc |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
399 // calling convention. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
400 bool retStructInRegs(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
401 // 'fastcc' allows returns in up to two registers of each kind: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
402 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
403 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
404 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
405 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
406 // Heuristic for determining whether to pass a struct type directly or |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
407 // bump it to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
408 bool passStructTypeDirectly(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
409 // If the type fits in a reasonable number of registers, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
410 // pass it directly. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
411 // This does not necessarily mean it will actually be passed in |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
412 // registers. For example, x87 registers are never actually used for |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
413 // parameters. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
414 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
415 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
416 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
417 // This doesn't work well: Since the register count can differ depending |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
418 // on backend options, there's no way to be exact anyway. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
419 /* |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
420 // Regular fastcc: 6 int, 8 sse, 0 x87 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
421 // fastcc + tailcall: 5 int, 8 sse, 0 x87 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
422 RegCount state(5, 8, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
423 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
424 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
425 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
426 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
427 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
428 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
429 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
430 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
431 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
432 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
433 /// Just store to memory and it's readable as the other type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
434 struct X86_64_C_struct_rewrite : ABIRewrite { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
435 // Get struct from ABI-mangled representation |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
436 LLValue* get(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
437 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
438 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
439 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
440 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
441 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
442 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
443 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
444 lval = DtoAlloca(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
445 DtoStore(rval, lval); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
446 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
447 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
448 const LLType* pTy = getPtrToType(DtoType(dty)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
449 return DtoLoad(DtoBitCast(lval, pTy), "get-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
450 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
451 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
452 // Get struct from ABI-mangled representation, and store in the provided location. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
453 void getL(Type* dty, DValue* v, llvm::Value* lval) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
454 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
455 const LLType* pTy = getPtrToType(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
456 DtoStore(rval, DtoBitCast(lval, pTy)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
457 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
458 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
459 // Turn a struct into an ABI-mangled representation |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
460 LLValue* put(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
461 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
462 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
463 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
464 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
465 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
466 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
467 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
468 lval = DtoAlloca(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
469 DtoStore(rval, lval); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
470 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
471 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
472 LLType* abiTy = getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
473 assert(abiTy && "Why are we rewriting a non-rewritten type?"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
474 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
475 const LLType* pTy = getPtrToType(abiTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
476 return DtoLoad(DtoBitCast(lval, pTy), "put-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
477 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
478 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
479 /// should return the transformed type for this rewrite |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
480 const LLType* type(Type* dty, const LLType* t) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
481 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
482 return getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
483 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
484 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
485 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
486 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
487 struct RegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
488 unsigned char int_regs, sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
489 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
490 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
491 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
492 struct X86_64TargetABI : TargetABI { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
493 X86_64_C_struct_rewrite struct_rewrite; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
494 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
495 void newFunctionType(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
496 funcTypeStack.push_back(FuncTypeData(tf->linkage)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
497 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
498 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
499 bool returnInArg(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
500 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
501 bool passByVal(Type* t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
502 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
503 void rewriteFunctionType(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
504 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
505 void doneWithFunctionType() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
506 funcTypeStack.pop_back(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
507 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
508 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
509 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
510 struct FuncTypeData { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
511 LINK linkage; // Linkage of the function type currently under construction |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
512 RegCount state; // bookkeeping for extern(C) parameter registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
513 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
514 FuncTypeData(LINK linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
515 : linkage(linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
516 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
517 state.int_regs = 6; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
518 state.sse_regs = 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
519 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
520 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
521 std::vector<FuncTypeData> funcTypeStack; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
522 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
523 LINK linkage() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
524 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
525 return funcTypeStack.back().linkage; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
526 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
527 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
528 RegCount& state() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
529 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
530 return funcTypeStack.back().state; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
531 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
532 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
533 void fixup(IrFuncTyArg& arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
534 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
535 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
536 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
537 // The public getter for abi.cpp |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
538 TargetABI* getX86_64TargetABI() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
539 return new X86_64TargetABI; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
540 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
541 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
542 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
543 bool X86_64TargetABI::returnInArg(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
544 assert(linkage() == tf->linkage); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
545 Type* rt = tf->next->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
546 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
547 if (tf->linkage == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
548 assert(rt->ty != Tsarray && "Update calling convention for static array returns"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
549 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
550 // All non-structs can be returned in registers. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
551 if (rt->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
552 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
553 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
554 // Try to figure out whether the struct fits in return registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
555 // and whether it's a good idea to put it there. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
556 return !x86_64_D_cc::retStructInRegs((TypeStruct*) rt); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
557 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
558 if (rt == Type::tvoid || keepUnchanged(rt)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
559 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
560 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
561 Classification cl = classify(rt); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
562 return cl.isMemory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
563 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
564 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
565 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
566 bool X86_64TargetABI::passByVal(Type* t) { |
1049 | 567 t = t->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
568 if (linkage() == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
569 if (t->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
570 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
571 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
572 // Try to be smart about which structs are passed in memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
573 return !x86_64_D_cc::passStructTypeDirectly((TypeStruct*) t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
574 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
575 // This implements the C calling convention for x86-64. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
576 // It might not be correct for other calling conventions. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
577 Classification cl = classify(t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
578 if (cl.isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
579 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
580 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
581 // Figure out how many registers we want for this arg: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
582 RegCount wanted = { 0, 0 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
583 for (int i = 0 ; i < 2; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
584 if (cl.classes[i] == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
585 wanted.int_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
586 else if (cl.classes[i] == Sse) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
587 wanted.sse_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
588 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
589 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
590 // See if they're available: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
591 RegCount& state = this->state(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
592 if (wanted.int_regs <= state.int_regs && wanted.sse_regs <= state.sse_regs) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
593 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
594 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
595 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
596 if (keepUnchanged(t)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
597 // Not enough registers available, but this is passed as if it's |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
598 // multiple arguments. Just use the registers there are, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
599 // automatically spilling the rest to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
600 if (wanted.int_regs > state.int_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
601 state.int_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
602 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
603 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
604 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
605 if (wanted.sse_regs > state.sse_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
606 state.sse_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
607 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
608 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
609 } else if (t->iscomplex() || t->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
610 // Spill entirely to memory, even if some of the registers are |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
611 // available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
612 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
613 // FIXME: Don't do this if *none* of the wanted registers are available, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
614 // (i.e. only when absolutely necessary for abi-compliance) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
615 // so it gets alloca'd by the callee and -scalarrepl can |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
616 // more easily break it up? |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
617 // Note: this won't be necessary if the following LLVM bug gets fixed: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
618 // http://llvm.org/bugs/show_bug.cgi?id=3741 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
619 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
620 } else { |
1048 | 621 assert(t == Type::tfloat80 || t == Type::timaginary80 || t->size() <= 8 |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
622 && "What other big types are there?"); // other than static arrays... |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
623 // In any case, they shouldn't be represented as structs in LLVM: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
624 assert(!isaStruct(DtoType(t))); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
625 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
626 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
627 // Everything else that's passed in memory is handled by LLVM. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
628 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
629 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
630 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
631 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
632 // Helper function for rewriteFunctionType. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
633 // Return type and parameters are passed here (unless they're already in memory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
634 // to get the rewrite applied (if necessary). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
635 void X86_64TargetABI::fixup(IrFuncTyArg& arg) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
636 LLType* abiTy = getAbiType(arg.type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
637 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
638 if (abiTy && abiTy != arg.ltype) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
639 assert(arg.type == Type::tcomplex32 || arg.type->ty == Tstruct); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
640 arg.ltype = abiTy; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
641 arg.rewrite = &struct_rewrite; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
642 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
643 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
644 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
645 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
646 // extern(D) is handled entirely by passByVal and returnInArg |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
647 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
648 if (tf->linkage != LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
649 // TODO: See if this is correct for more than just extern(C). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
650 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
651 IrFuncTy& fty = tf->fty; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
652 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
653 if (!fty.arg_sret) { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
654 Logger::println("x86-64 ABI: Transforming return type"); |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
655 Type* rt = fty.ret->type->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
656 if (rt != Type::tvoid) |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
657 fixup(*fty.ret); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
658 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
659 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
660 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
661 Logger::println("x86-64 ABI: Transforming arguments"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
662 LOG_SCOPE; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
663 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
664 for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
665 IrFuncTyArg& arg = **I; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
666 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
667 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
668 Logger::cout() << "Arg: " << arg.type->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
669 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
670 // Arguments that are in memory are of no interest to us. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
671 if (arg.byref) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
672 continue; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
673 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
674 Type* ty = arg.type->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
675 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
676 fixup(arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
677 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
678 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
679 Logger::cout() << "New arg type: " << *arg.ltype << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
680 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
681 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
682 } |