Mercurial > projects > ldc
annotate gen/abi-x86-64.cpp @ 1353:45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Thu, 14 May 2009 20:36:55 +0200 |
parents | 15e9762bb620 |
children | 701d11a1e7b1 |
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" |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
46 #include "gen/structs.h" |
1348
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
47 //#include "gen/llvm-version.h" // only use is commented out. |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
48 #include "ir/irfunction.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
49 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
50 #include <cassert> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
51 #include <map> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
52 #include <string> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
53 #include <utility> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
54 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
55 // Implementation details for extern(C) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
56 namespace { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
57 /** |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
58 * 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
|
59 * 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
|
60 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
61 * (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
|
62 * 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
|
63 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
64 inline bool keepUnchanged(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
65 switch (t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
66 case Tarray: // dynamic array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
67 case Taarray: // assoc array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
68 case Tdelegate: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
69 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
70 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
71 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
72 return false; |
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 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
75 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
76 enum ArgClass { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
77 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
|
78 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
79 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
80 struct Classification { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
81 bool isMemory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
82 ArgClass classes[2]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
83 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
84 Classification() : isMemory(false) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
85 classes[0] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
86 classes[1] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
87 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
88 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
89 void addField(unsigned offset, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
90 if (isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
91 return; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
92 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
93 // 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
|
94 // 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
|
95 // 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
|
96 // is special-cased in classifyType() |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
97 int idx = (offset < 8 ? 0 : 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
98 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
99 ArgClass nw = merge(classes[idx], cl); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
100 if (nw != classes[idx]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
101 classes[idx] = nw; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
102 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
103 if (nw == Memory) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
104 classes[1-idx] = Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
105 isMemory = true; |
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 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
109 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
110 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
111 ArgClass merge(ArgClass accum, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
112 if (accum == cl) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
113 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
114 if (accum == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
115 return cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
116 if (cl == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
117 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
118 if (accum == Memory || cl == Memory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
119 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
120 if (accum == Integer || cl == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
121 return Integer; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
122 if (accum == X87 || accum == X87Up || accum == ComplexX87 || |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
123 cl == X87 || cl == X87Up || cl == ComplexX87) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
124 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
125 return Sse; |
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 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
128 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
129 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
|
130 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
131 Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n'; |
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 ty = ty->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
134 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
135 if (ty->isintegral() || ty->ty == Tpointer) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
136 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
137 } 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
|
138 accum.addField(offset, X87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
139 accum.addField(offset+8, X87Up); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
140 } else if (ty->ty == Tcomplex80) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
141 accum.addField(offset, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
142 // 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
|
143 accum.addField(offset+16, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
144 } else if (ty->ty == Tcomplex64) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
145 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
146 accum.addField(offset+8, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
147 } else if (ty->ty == Tcomplex32) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
148 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
149 accum.addField(offset+4, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
150 } else if (ty->isfloating()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
151 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
152 } else if (ty->size() > 16 || hasUnalignedFields(ty)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
153 // 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
|
154 // 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
|
155 // 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
|
156 accum.addField(offset, Memory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
157 } 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
|
158 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
|
159 d_uns64 eltsize = eltType->size(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
160 if (eltsize > 0) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
161 d_uns64 dim = ty->size() / eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
162 assert(dim <= 16 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
163 && "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
|
164 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
|
165 classifyType(accum, eltType, offset); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
166 offset += eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
167 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
168 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
169 } else if (ty->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
170 Array* fields = &((TypeStruct*) ty)->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
171 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
|
172 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
173 classifyType(accum, field->type, offset + field->offset); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
174 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
175 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
176 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
177 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
|
178 << ty->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
179 // 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
|
180 assert(offset == 0 || offset == 8 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
181 && "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
|
182 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
|
183 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
184 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
185 if (ty->size() > 8) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
186 accum.addField(offset+8, Integer); |
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 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
189 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
190 Classification classify(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
191 typedef std::map<Type*, Classification> ClassMap; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
192 static ClassMap cache; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
193 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
194 ClassMap::iterator it = cache.find(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
195 if (it != cache.end()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
196 return it->second; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
197 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
198 Classification cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
199 classifyType(cl, ty, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
200 cache[ty] = cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
201 return cl; |
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 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
204 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
205 /// 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
|
206 LLType* getAbiType(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
207 ty = ty->toBasetype(); |
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 // 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
|
210 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
211 if (keepUnchanged(ty)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
212 return 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
213 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
214 if (ty->ty != Tcomplex32 && ty->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
215 return 0; // Nothing to do, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
216 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
217 Classification cl = classify(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
218 assert(!cl.isMemory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
219 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
220 if (cl.classes[0] == NoClass) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
221 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
|
222 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
|
223 } |
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 // 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
|
226 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
227 std::vector<const LLType*> parts; |
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 unsigned size = ty->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
230 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
231 switch (cl.classes[0]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
232 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
233 unsigned bits = (size >= 8 ? 64 : (size * 8)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
234 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
235 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
236 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
237 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
238 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
239 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
|
240 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
241 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
242 case X87: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
243 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
|
244 /// 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
|
245 /// so just use that type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
246 return const_cast<LLType*>(LLType::X86_FP80Ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
247 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
248 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
249 assert(0 && "Unanticipated argument class"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
250 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
251 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
252 switch(cl.classes[1]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
253 case NoClass: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
254 assert(parts.size() == 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
255 // 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
|
256 // Just use the element type instead. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
257 return const_cast<LLType*>(parts[0]); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
258 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
259 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
260 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
261 assert(size > 8); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
262 unsigned bits = (size - 8) * 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
263 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
264 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
265 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
266 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
267 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
|
268 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
269 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
270 case X87Up: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
271 if(cl.classes[0] == X87) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
272 // 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
|
273 // processing the first half. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
274 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
275 // 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
|
276 // 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
|
277 // (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
|
278 parts.push_back(LLType::DoubleTy); |
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 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
281 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
282 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
283 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
|
284 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
285 return LLStructType::get(parts); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
289 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
290 // Implementation details for extern(D) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
291 namespace x86_64_D_cc { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
292 struct DRegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
293 unsigned ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
294 unsigned sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
295 unsigned x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
296 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
297 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
298 : ints(ints_), sse(sse_), x87(x87_) {} |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
299 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
300 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
301 // 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
|
302 // (Not a struct or static array) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
303 DRegCount regsNeededForSimpleType(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
304 DRegCount r(0, 0, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
305 switch(t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
306 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
307 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
308 assert(0 && "Not a simple type!"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
309 // 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
|
310 // bumped to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
311 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
|
312 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
313 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
314 // 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
|
315 case Tfloat32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
316 case Tfloat64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
317 case Timaginary32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
318 case Timaginary64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
319 r.sse = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
320 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
321 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
322 case Tcomplex32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
323 case Tcomplex64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
324 r.sse = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
325 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
326 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
327 // 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
|
328 case Tfloat80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
329 case Timaginary80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
330 r.x87 = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
331 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
332 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
333 case Tcomplex80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
334 r.x87 = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
335 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
336 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
337 // 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
|
338 // depending on its size. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
339 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
340 int needed = (t->size() + 7) / 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
341 assert(needed <= 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
342 r.ints = needed; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
343 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
344 } |
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 return r; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
347 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
348 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
349 // 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
|
350 // specified number of registers. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
351 // (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
|
352 // reasons other than it not fitting) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
353 // 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
|
354 // 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
|
355 // If false is returned, 'left' is garbage. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
356 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
357 // 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
|
358 // so keep it in memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
359 if (hasUnalignedFields(t)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
360 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
361 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
362 Array* fields = &t->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
363 d_uns64 nextbyte = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
364 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
|
365 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
366 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
367 // 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
|
368 // without overlapping fields. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
369 if (field->offset < nextbyte) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
370 // 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
|
371 return false; |
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 nextbyte = field->offset + field->type->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
374 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
375 switch (field->type->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
376 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
377 if (!shouldPassStructInRegs((TypeStruct*) field->type, left)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
378 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
379 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
380 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
381 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
382 // Don't return static arrays in registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
383 // (indexing registers doesn't work well) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
384 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
385 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
386 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
387 DRegCount needed = regsNeededForSimpleType(field->type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
388 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
|
389 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
390 left.ints -= needed.ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
391 left.sse -= needed.sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
392 left.x87 -= needed.x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
393 break; |
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 } |
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 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
398 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
399 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
400 // 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
|
401 // calling convention. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
402 bool retStructInRegs(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
403 // '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
|
404 DRegCount state(2, 2, 2); |
1348
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
405 #if 1 //LLVM_REV < 67588 |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
406 // (If uncommenting the LLVM_REV line above, also uncomment llvm-version #include |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
407 |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
408 // LLVM before trunk r67588 doesn't allow a second int to be an i1 or |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
409 // i8. (See <http://llvm.org/PR3861>) |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
410 // Rather than complicating shouldPassStructInRegs(), just disallow |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
411 // second integers for now. |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
412 // FIXME: Disabling this for older LLVM only makes the abi dependent on |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
413 // LLVM revision, which seems like a bad idea. We could extend |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
414 // i8 parts to i16 to work around this issue until 2.6... |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
415 // TODO: Remove this workaround when support for LLVM 2.5 is dropped. |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
416 state.ints = 1; |
f3b92d26ad0f
Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents:
1346
diff
changeset
|
417 #endif |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
418 return shouldPassStructInRegs(st, state); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
421 // 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
|
422 // bump it to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
423 bool passStructTypeDirectly(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
424 // 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
|
425 // pass it directly. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
426 // 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
|
427 // 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
|
428 // parameters. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
429 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
430 return shouldPassStructInRegs(st, state); |
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 // 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
|
433 // 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
|
434 /* |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
435 // 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
|
436 // 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
|
437 RegCount state(5, 8, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
438 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
439 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
440 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
441 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
442 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
443 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
444 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
445 //////////////////////////////////////////////////////////////////////////////// |
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 /// 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
|
449 struct X86_64_C_struct_rewrite : ABIRewrite { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
450 // Get struct from ABI-mangled representation |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
451 LLValue* get(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
452 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
453 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
454 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
455 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
456 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
457 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
458 LLValue* rval = v->getRVal(); |
1350
15e9762bb620
Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1348
diff
changeset
|
459 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
460 DtoStore(rval, lval); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
463 const LLType* pTy = getPtrToType(DtoType(dty)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
464 return DtoLoad(DtoBitCast(lval, pTy), "get-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
465 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
466 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
467 // 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
|
468 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
|
469 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
470 const LLType* pTy = getPtrToType(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
471 DtoStore(rval, DtoBitCast(lval, pTy)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
472 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
473 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
474 // 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
|
475 LLValue* put(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
476 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
477 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
478 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
479 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
480 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
481 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
482 LLValue* rval = v->getRVal(); |
1350
15e9762bb620
Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1348
diff
changeset
|
483 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
484 DtoStore(rval, lval); |
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 LLType* abiTy = getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
488 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
|
489 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
490 const LLType* pTy = getPtrToType(abiTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
491 return DtoLoad(DtoBitCast(lval, pTy), "put-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
492 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
493 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
494 /// 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
|
495 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
|
496 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
497 return getAbiType(dty); |
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 }; |
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 |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
502 /// Removes padding fields for (non-union-containing!) structs |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
503 struct RemoveStructPadding : ABIRewrite { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
504 /// get a rewritten value back to its original form |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
505 virtual LLValue* get(Type* dty, DValue* v) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
506 LLValue* lval = DtoAlloca(dty, ".rewritetmp"); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
507 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
508 // Make sure the padding is zero, so struct comparisons work. |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
509 // TODO: Only do this if there's padding, and/or only initialize padding. |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
510 DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty)))); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
511 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
512 DtoPaddedStruct(dty, v->getRVal(), lval); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
513 return lval; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
514 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
515 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
516 /// get a rewritten value back to its original form and store result in provided lvalue |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
517 /// this one is optional and defaults to calling the one above |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
518 virtual void getL(Type* dty, DValue* v, llvm::Value* lval) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
519 DtoPaddedStruct(dty, v->getRVal(), lval); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
520 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
521 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
522 /// put out rewritten value |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
523 virtual LLValue* put(Type* dty, DValue* v) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
524 return DtoUnpaddedStruct(dty, v->getRVal()); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
525 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
526 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
527 /// return the transformed type for this rewrite |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
528 virtual const LLType* type(Type* dty, const LLType* t) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
529 return DtoUnpaddedStructType(dty); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
530 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
531 }; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
532 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
533 |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
534 struct RegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
535 unsigned char int_regs, sse_regs; |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
538 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
539 struct X86_64TargetABI : TargetABI { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
540 X86_64_C_struct_rewrite struct_rewrite; |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
541 RemoveStructPadding remove_padding; |
1047
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 void newFunctionType(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
544 funcTypeStack.push_back(FuncTypeData(tf->linkage)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
545 } |
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 bool returnInArg(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
548 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
549 bool passByVal(Type* t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
550 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
551 void rewriteFunctionType(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
552 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
553 void doneWithFunctionType() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
554 funcTypeStack.pop_back(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
555 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
556 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
557 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
558 struct FuncTypeData { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
559 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
|
560 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
|
561 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
562 FuncTypeData(LINK linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
563 : linkage(linkage_) |
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 state.int_regs = 6; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
566 state.sse_regs = 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
567 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
568 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
569 std::vector<FuncTypeData> funcTypeStack; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
570 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
571 LINK linkage() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
572 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
573 return funcTypeStack.back().linkage; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
574 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
575 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
576 RegCount& state() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
577 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
578 return funcTypeStack.back().state; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
579 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
580 |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
581 void fixup_D(IrFuncTyArg& arg); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
582 void fixup(IrFuncTyArg& arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
583 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
584 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
585 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
586 // The public getter for abi.cpp |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
587 TargetABI* getX86_64TargetABI() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
588 return new X86_64TargetABI; |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
591 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
592 bool X86_64TargetABI::returnInArg(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
593 assert(linkage() == tf->linkage); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
594 Type* rt = tf->next->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
595 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
596 if (tf->linkage == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
597 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
|
598 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
599 // 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
|
600 if (rt->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
601 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
602 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
603 // 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
|
604 // 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
|
605 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
|
606 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
607 if (rt == Type::tvoid || keepUnchanged(rt)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
608 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
609 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
610 Classification cl = classify(rt); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
611 return cl.isMemory; |
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 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
614 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
615 bool X86_64TargetABI::passByVal(Type* t) { |
1049 | 616 t = t->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
617 if (linkage() == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
618 if (t->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
619 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
620 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
621 // 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
|
622 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
|
623 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
624 // 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
|
625 // 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
|
626 Classification cl = classify(t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
627 if (cl.isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
628 return true; |
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 // 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
|
631 RegCount wanted = { 0, 0 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
632 for (int i = 0 ; i < 2; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
633 if (cl.classes[i] == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
634 wanted.int_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
635 else if (cl.classes[i] == Sse) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
636 wanted.sse_regs++; |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
639 // See if they're available: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
640 RegCount& state = this->state(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
641 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
|
642 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
643 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
644 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
645 if (keepUnchanged(t)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
646 // 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
|
647 // 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
|
648 // automatically spilling the rest to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
649 if (wanted.int_regs > state.int_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
650 state.int_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
651 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
652 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
653 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
654 if (wanted.sse_regs > state.sse_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
655 state.sse_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
656 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
657 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
658 } else if (t->iscomplex() || t->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
659 // 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
|
660 // available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
661 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
662 // 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
|
663 // (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
|
664 // 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
|
665 // more easily break it up? |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
666 // 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
|
667 // 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
|
668 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
669 } else { |
1048 | 670 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
|
671 && "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
|
672 // 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
|
673 assert(!isaStruct(DtoType(t))); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
674 } |
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 // 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
|
677 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
678 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
679 } |
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 // Helper function for rewriteFunctionType. |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
682 // Structs passed or returned in registers are passed here |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
683 // to get their padding removed (if necessary). |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
684 void X86_64TargetABI::fixup_D(IrFuncTyArg& arg) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
685 assert(arg.type->ty == Tstruct); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
686 LLType* abiTy = DtoUnpaddedStructType(arg.type); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
687 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
688 if (abiTy && abiTy != arg.ltype) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
689 arg.ltype = abiTy; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
690 arg.rewrite = &remove_padding; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
691 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
692 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
693 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
694 // Helper function for rewriteFunctionType. |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
695 // 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
|
696 // to get the rewrite applied (if necessary). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
697 void X86_64TargetABI::fixup(IrFuncTyArg& arg) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
698 LLType* abiTy = getAbiType(arg.type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
699 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
700 if (abiTy && abiTy != arg.ltype) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
701 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
|
702 arg.ltype = abiTy; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
703 arg.rewrite = &struct_rewrite; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
704 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
705 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
706 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
707 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) { |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
708 IrFuncTy& fty = tf->fty; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
709 |
1353
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
710 if (tf->linkage == LINKd) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
711 if (!fty.arg_sret) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
712 Type* rt = fty.ret->type->toBasetype(); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
713 if (rt->ty == Tstruct) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
714 Logger::println("x86-64 D ABI: Transforming return type"); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
715 fixup_D(*fty.ret); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
716 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
717 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
718 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
719 Logger::println("x86-64 D ABI: Transforming arguments"); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
720 LOG_SCOPE; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
721 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
722 for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) { |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
723 IrFuncTyArg& arg = **I; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
724 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
725 if (Logger::enabled()) |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
726 Logger::cout() << "Arg: " << arg.type->toChars() << '\n'; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
727 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
728 // Arguments that are in memory are of no interest to us. |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
729 if (arg.byref) |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
730 continue; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
731 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
732 Type* ty = arg.type->toBasetype(); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
733 if (ty->ty == Tstruct) |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
734 fixup_D(arg); |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
735 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
736 if (Logger::enabled()) |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
737 Logger::cout() << "New arg type: " << *arg.ltype << '\n'; |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
738 } |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
739 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
740 } else { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
741 // 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
|
742 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
743 if (!fty.arg_sret) { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
744 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
|
745 Type* rt = fty.ret->type->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
746 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
|
747 fixup(*fty.ret); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
748 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
749 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
750 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
751 Logger::println("x86-64 ABI: Transforming arguments"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
752 LOG_SCOPE; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
753 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
754 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
|
755 IrFuncTyArg& arg = **I; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
756 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
757 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
758 Logger::cout() << "Arg: " << arg.type->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
759 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
760 // 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
|
761 if (arg.byref) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
762 continue; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
763 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
764 Type* ty = arg.type->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
765 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
766 fixup(arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
767 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
768 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
769 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
|
770 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
771 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
772 } |