Mercurial > projects > ldc
annotate gen/abi-x86-64.cpp @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 8d086d552909 |
children |
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 |
1569
755abafbf25d
Push the context through StructType::get.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1502
diff
changeset
|
39 #include "gen/irstate.h" |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
40 #include "gen/llvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
41 #include "gen/tollvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
42 #include "gen/logger.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
43 #include "gen/dvalue.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
44 #include "gen/llvmhelpers.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
45 #include "gen/abi.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
46 #include "gen/abi-x86-64.h" |
1359
34f2fd925de3
Intrinsics shouldn't see struct padding, so use a special TargetABI for them
Frits van Bommel <fvbommel wxs.nl>
parents:
1354
diff
changeset
|
47 #include "gen/abi-generic.h" |
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)); |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
234 parts.push_back(LLIntegerType::get(gIR->context(), bits)); |
1047
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: |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
239 parts.push_back(size <= 4 ? LLType::getFloatTy(gIR->context()) : LLType::getDoubleTy(gIR->context())); |
1047
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. |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
246 return const_cast<LLType*>(LLType::getX86_FP80Ty(gIR->context())); |
1047
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; |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
263 parts.push_back(LLIntegerType::get(gIR->context(), bits)); |
1047
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: |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
267 parts.push_back(size <= 12 ? LLType::getFloatTy(gIR->context()) : LLType::getDoubleTy(gIR->context())); |
1047
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; }) |
1571
8d086d552909
IntegerType is now contextifed.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1569
diff
changeset
|
278 parts.push_back(LLType::getDoubleTy(gIR->context())); |
1047
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 } |
1569
755abafbf25d
Push the context through StructType::get.
Benjamin Kramer <benny.kra@gmail.com>
parents:
1502
diff
changeset
|
285 return LLStructType::get(gIR->context(), parts); |
1047
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); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
405 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
406 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
407 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
408 // 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
|
409 // bump it to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
410 bool passStructTypeDirectly(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
411 // 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
|
412 // pass it directly. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
413 // 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
|
414 // 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
|
415 // parameters. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
416 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
417 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
418 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
419 // 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
|
420 // 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
|
421 /* |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
422 // 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
|
423 // 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
|
424 RegCount state(5, 8, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
425 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
426 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
427 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
428 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
429 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
430 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
431 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
432 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
433 |
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 /// 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
|
436 struct X86_64_C_struct_rewrite : ABIRewrite { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
437 // Get struct from ABI-mangled representation |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
438 LLValue* get(Type* dty, DValue* v) |
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 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
441 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
442 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
443 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
444 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
445 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
|
446 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
447 DtoStore(rval, lval); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
448 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
449 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
450 const LLType* pTy = getPtrToType(DtoType(dty)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
451 return DtoLoad(DtoBitCast(lval, pTy), "get-result"); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
454 // 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
|
455 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
|
456 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
457 const LLType* pTy = getPtrToType(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
458 DtoStore(rval, DtoBitCast(lval, pTy)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
459 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
460 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
461 // 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
|
462 LLValue* put(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
463 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
464 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
465 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
466 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
467 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
468 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
469 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
|
470 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
471 DtoStore(rval, lval); |
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 LLType* abiTy = getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
475 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
|
476 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
477 const LLType* pTy = getPtrToType(abiTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
478 return DtoLoad(DtoBitCast(lval, pTy), "put-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
479 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
480 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
481 /// 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
|
482 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
|
483 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
484 return getAbiType(dty); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
488 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
489 struct RegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
490 unsigned char int_regs, sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
491 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
492 |
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 struct X86_64TargetABI : TargetABI { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
495 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
|
496 RemoveStructPadding remove_padding; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
497 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
498 void newFunctionType(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
499 funcTypeStack.push_back(FuncTypeData(tf->linkage)); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
502 bool returnInArg(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
503 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
504 bool passByVal(Type* t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
505 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
506 void rewriteFunctionType(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
507 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
508 void doneWithFunctionType() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
509 funcTypeStack.pop_back(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
510 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
511 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
512 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
513 struct FuncTypeData { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
514 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
|
515 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
|
516 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
517 FuncTypeData(LINK linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
518 : linkage(linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
519 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
520 state.int_regs = 6; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
521 state.sse_regs = 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
522 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
523 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
524 std::vector<FuncTypeData> funcTypeStack; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
525 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
526 LINK linkage() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
527 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
528 return funcTypeStack.back().linkage; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
529 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
530 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
531 RegCount& state() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
532 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
533 return funcTypeStack.back().state; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
534 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
535 |
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
|
536 void fixup_D(IrFuncTyArg& arg); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
537 void fixup(IrFuncTyArg& arg); |
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
540 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
541 // The public getter for abi.cpp |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
542 TargetABI* getX86_64TargetABI() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
543 return new X86_64TargetABI; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
544 } |
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 X86_64TargetABI::returnInArg(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
548 assert(linkage() == tf->linkage); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
549 Type* rt = tf->next->toBasetype(); |
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 if (tf->linkage == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
552 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
|
553 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
554 // 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
|
555 if (rt->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
556 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
557 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
558 // 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
|
559 // 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
|
560 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
|
561 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
562 if (rt == Type::tvoid || keepUnchanged(rt)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
563 return false; |
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 Classification cl = classify(rt); |
1410
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
566 if (cl.isMemory) { |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
567 assert(state().int_regs > 0 |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
568 && "No int registers available when determining sret-ness?"); |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
569 // An sret parameter takes an integer register. |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
570 state().int_regs--; |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
571 return true; |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
572 } |
cc2d8a7388c7
Count the sret register as well when keeping track of how many integer registers
Frits van Bommel <fvbommel wxs.nl>
parents:
1399
diff
changeset
|
573 return false; |
1047
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 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
577 bool X86_64TargetABI::passByVal(Type* t) { |
1049 | 578 t = t->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
579 if (linkage() == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
580 if (t->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
581 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
582 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
583 // 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
|
584 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
|
585 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
586 // 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
|
587 // 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
|
588 Classification cl = classify(t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
589 if (cl.isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
590 return true; |
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 // 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
|
593 RegCount wanted = { 0, 0 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
594 for (int i = 0 ; i < 2; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
595 if (cl.classes[i] == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
596 wanted.int_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
597 else if (cl.classes[i] == Sse) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
598 wanted.sse_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
599 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
600 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
601 // See if they're available: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
602 RegCount& state = this->state(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
603 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
|
604 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
605 state.sse_regs -= wanted.sse_regs; |
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 (keepUnchanged(t)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
608 // 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
|
609 // 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
|
610 // automatically spilling the rest to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
611 if (wanted.int_regs > state.int_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
612 state.int_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
613 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
614 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
615 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
616 if (wanted.sse_regs > state.sse_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
617 state.sse_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
618 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
619 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
620 } else if (t->iscomplex() || t->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
621 // 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
|
622 // available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
623 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
624 // 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
|
625 // (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
|
626 // 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
|
627 // more easily break it up? |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
628 // 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
|
629 // 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
|
630 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
631 } else { |
1048 | 632 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
|
633 && "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
|
634 // 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
|
635 assert(!isaStruct(DtoType(t))); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
636 } |
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 // 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
|
639 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
640 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
641 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
642 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
643 // 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
|
644 // 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
|
645 // 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
|
646 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
|
647 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
|
648 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
|
649 |
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
|
650 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
|
651 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
|
652 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
|
653 } |
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
|
654 } |
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
|
655 |
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
|
656 // Helper function for rewriteFunctionType. |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
657 // 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
|
658 // to get the rewrite applied (if necessary). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
659 void X86_64TargetABI::fixup(IrFuncTyArg& arg) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
660 LLType* abiTy = getAbiType(arg.type); |
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 if (abiTy && abiTy != arg.ltype) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
663 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
|
664 arg.ltype = abiTy; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
665 arg.rewrite = &struct_rewrite; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
666 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
667 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
668 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
669 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
|
670 IrFuncTy& fty = tf->fty; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
671 |
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
|
672 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
|
673 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
|
674 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
|
675 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
|
676 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
|
677 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
|
678 } |
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
|
679 } |
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
|
680 |
1439
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
681 if (fty.arg_this) { |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
682 fty.arg_this->attrs |= llvm::Attribute::Nest; |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
683 } |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
684 if (fty.arg_nest) { |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
685 fty.arg_nest->attrs |= llvm::Attribute::Nest; |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
686 } |
679ac907c82f
Add `nest` attribute to `this` parameters on x86-64. This is a free extra
Frits van Bommel <fvbommel wxs.nl>
parents:
1410
diff
changeset
|
687 |
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
|
688 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
|
689 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
|
690 |
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 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
|
692 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
|
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 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
|
695 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
|
696 |
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
|
697 // 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
|
698 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
|
699 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
|
700 |
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
|
701 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
|
702 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
|
703 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
|
704 |
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
|
705 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
|
706 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
|
707 } |
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 |
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
|
709 } else { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
710 // 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
|
711 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
712 if (!fty.arg_sret) { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
713 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
|
714 Type* rt = fty.ret->type->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
715 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
|
716 fixup(*fty.ret); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
717 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
718 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
719 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
720 Logger::println("x86-64 ABI: Transforming arguments"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
721 LOG_SCOPE; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
722 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
723 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
|
724 IrFuncTyArg& arg = **I; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
725 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
726 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
727 Logger::cout() << "Arg: " << arg.type->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
728 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
729 // 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
|
730 if (arg.byref) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
731 continue; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
732 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
733 Type* ty = arg.type->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
734 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
735 fixup(arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
736 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
737 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
|
738 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
739 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
740 } |