Mercurial > projects > ldc
annotate gen/abi-x86-64.cpp @ 1541:1e7a09548e67
Target.addPassesToEmitFile takes a formatted_raw_ostream now
Build fix for LLVM r75670
author | Benjamin Kramer <benny.kra@gmail.com> |
---|---|
date | Tue, 14 Jul 2009 23:06:31 +0200 |
parents | 2292878925f4 |
children | 755abafbf25d |
rev | line source |
---|---|
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
1 /* TargetABI implementation for x86-64. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
2 * Written for LDC by Frits van Bommel in 2009. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
3 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
4 * extern(D) follows no particular external ABI, but tries to be smart about |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
5 * passing structs and returning them. It should probably be reviewed if the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
6 * way LLVM implements fastcc on this platform ever changes. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
7 * (Specifically, the number of return registers of various types is hardcoded) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
8 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
9 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
10 * extern(C) implements the C calling convention for x86-64, as found in |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
11 * http://www.x86-64.org/documentation/abi-0.99.pdf |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
12 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
13 * Note: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
14 * Where a discrepancy was found between llvm-gcc and the ABI documentation, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
15 * llvm-gcc behavior was used for compatibility (after it was verified that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
16 * regular gcc has the same behavior). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
17 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
18 * LLVM gets it right for most types, but complex numbers and structs need some |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
19 * help. To make sure it gets those right we essentially bitcast small structs |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
20 * to a type to which LLVM assigns the appropriate registers, and pass that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
21 * instead. Structs that are required to be passed in memory are explicitly |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
22 * marked with the ByVal attribute to ensure no part of them ends up in |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
23 * registers when only a subset of the desired registers are available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
24 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
25 * We don't perform the same transformation for D-specific types that contain |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
26 * multiple parts, such as dynamic arrays and delegates. They're passed as if |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
27 * the parts were passed as separate parameters. This helps make things like |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
28 * printf("%.*s", o.toString()) work as expected; if we didn't do this that |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
29 * wouldn't work if there were 4 other integer/pointer arguments before the |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
30 * toString() call because the string got bumped to memory with one integer |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
31 * register still free. Keeping it untransformed puts the length in a register |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
32 * and the pointer in memory, as printf expects it. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
33 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
34 |
1063
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
35 #include "mtype.h" |
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
36 #include "declaration.h" |
40d7f9b7357f
Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents:
1054
diff
changeset
|
37 #include "aggregate.h" |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
38 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
39 #include "gen/llvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
40 #include "gen/tollvm.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
41 #include "gen/logger.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
42 #include "gen/dvalue.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
43 #include "gen/llvmhelpers.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
44 #include "gen/abi.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
45 #include "gen/abi-x86-64.h" |
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
|
46 #include "gen/abi-generic.h" |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
47 #include "ir/irfunction.h" |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
48 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
49 #include <cassert> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
50 #include <map> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
51 #include <string> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
52 #include <utility> |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
53 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
54 // Implementation details for extern(C) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
55 namespace { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
56 /** |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
57 * 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
|
58 * 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
|
59 * |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
60 * (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
|
61 * 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
|
62 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
63 inline bool keepUnchanged(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
64 switch (t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
65 case Tarray: // dynamic array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
66 case Taarray: // assoc array |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
67 case Tdelegate: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
68 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
69 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
70 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
71 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
72 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
73 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
74 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
75 enum ArgClass { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
76 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
|
77 }; |
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 struct Classification { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
80 bool isMemory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
81 ArgClass classes[2]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
82 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
83 Classification() : isMemory(false) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
84 classes[0] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
85 classes[1] = NoClass; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
86 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
87 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
88 void addField(unsigned offset, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
89 if (isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
90 return; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
91 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
92 // 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
|
93 // 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
|
94 // 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
|
95 // is special-cased in classifyType() |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
96 int idx = (offset < 8 ? 0 : 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
97 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
98 ArgClass nw = merge(classes[idx], cl); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
99 if (nw != classes[idx]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
100 classes[idx] = nw; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
101 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
102 if (nw == Memory) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
103 classes[1-idx] = Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
104 isMemory = true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
105 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
106 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
107 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
108 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
109 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
110 ArgClass merge(ArgClass accum, ArgClass cl) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
111 if (accum == cl) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
112 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
113 if (accum == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
114 return cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
115 if (cl == NoClass) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
116 return accum; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
117 if (accum == Memory || cl == Memory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
118 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
119 if (accum == Integer || cl == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
120 return Integer; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
121 if (accum == X87 || accum == X87Up || accum == ComplexX87 || |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
122 cl == X87 || cl == X87Up || cl == ComplexX87) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
123 return Memory; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
124 return Sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
125 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
126 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
127 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
128 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
|
129 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
130 Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
131 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
132 ty = ty->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
133 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
134 if (ty->isintegral() || ty->ty == Tpointer) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
135 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
136 } 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
|
137 accum.addField(offset, X87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
138 accum.addField(offset+8, X87Up); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
139 } else if (ty->ty == Tcomplex80) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
140 accum.addField(offset, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
141 // 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
|
142 accum.addField(offset+16, ComplexX87); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
143 } else if (ty->ty == Tcomplex64) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
144 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
145 accum.addField(offset+8, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
146 } else if (ty->ty == Tcomplex32) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
147 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
148 accum.addField(offset+4, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
149 } else if (ty->isfloating()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
150 accum.addField(offset, Sse); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
151 } else if (ty->size() > 16 || hasUnalignedFields(ty)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
152 // 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
|
153 // 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
|
154 // 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
|
155 accum.addField(offset, Memory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
156 } 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
|
157 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
|
158 d_uns64 eltsize = eltType->size(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
159 if (eltsize > 0) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
160 d_uns64 dim = ty->size() / eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
161 assert(dim <= 16 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
162 && "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
|
163 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
|
164 classifyType(accum, eltType, offset); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
165 offset += eltsize; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
166 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
167 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
168 } else if (ty->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
169 Array* fields = &((TypeStruct*) ty)->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
170 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
|
171 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
172 classifyType(accum, field->type, offset + field->offset); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
173 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
174 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
175 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
176 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
|
177 << ty->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
178 // 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
|
179 assert(offset == 0 || offset == 8 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
180 && "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
|
181 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
|
182 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
183 accum.addField(offset, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
184 if (ty->size() > 8) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
185 accum.addField(offset+8, Integer); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
186 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
187 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
188 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
189 Classification classify(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
190 typedef std::map<Type*, Classification> ClassMap; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
191 static ClassMap cache; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
192 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
193 ClassMap::iterator it = cache.find(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
194 if (it != cache.end()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
195 return it->second; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
196 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
197 Classification cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
198 classifyType(cl, ty, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
199 cache[ty] = cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
200 return cl; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
201 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
202 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
203 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
204 /// 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
|
205 LLType* getAbiType(Type* ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
206 ty = ty->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
207 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
208 // 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
|
209 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
210 if (keepUnchanged(ty)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
211 return 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
212 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
213 if (ty->ty != Tcomplex32 && ty->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
214 return 0; // Nothing to do, |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
215 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
216 Classification cl = classify(ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
217 assert(!cl.isMemory); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
218 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
219 if (cl.classes[0] == NoClass) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
220 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
|
221 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
|
222 } |
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 // 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
|
225 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
226 std::vector<const LLType*> parts; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
227 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
228 unsigned size = ty->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
229 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
230 switch (cl.classes[0]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
231 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
232 unsigned bits = (size >= 8 ? 64 : (size * 8)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
233 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
234 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
235 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
236 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
237 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
238 parts.push_back(size <= 4 ? LLType::FloatTy : LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
239 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
240 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
241 case X87: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
242 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
|
243 /// 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
|
244 /// so just use that type. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
245 return const_cast<LLType*>(LLType::X86_FP80Ty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
246 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
247 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
248 assert(0 && "Unanticipated argument class"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
249 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
250 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
251 switch(cl.classes[1]) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
252 case NoClass: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
253 assert(parts.size() == 1); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
254 // 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
|
255 // Just use the element type instead. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
256 return const_cast<LLType*>(parts[0]); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
257 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
258 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
259 case Integer: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
260 assert(size > 8); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
261 unsigned bits = (size - 8) * 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
262 parts.push_back(LLIntegerType::get(bits)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
263 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
264 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
265 case Sse: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
266 parts.push_back(size <= 12 ? LLType::FloatTy : LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
267 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
268 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
269 case X87Up: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
270 if(cl.classes[0] == X87) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
271 // 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
|
272 // processing the first half. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
273 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
274 // 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
|
275 // 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
|
276 // (This triggers for types like union { real r; byte b; }) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
277 parts.push_back(LLType::DoubleTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
278 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
279 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
280 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
281 default: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
282 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
|
283 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
284 return LLStructType::get(parts); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
285 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
286 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
287 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
288 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
289 // Implementation details for extern(D) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
290 namespace x86_64_D_cc { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
291 struct DRegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
292 unsigned ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
293 unsigned sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
294 unsigned x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
295 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
296 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
297 : ints(ints_), sse(sse_), x87(x87_) {} |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
298 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
299 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
300 // 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
|
301 // (Not a struct or static array) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
302 DRegCount regsNeededForSimpleType(Type* t) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
303 DRegCount r(0, 0, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
304 switch(t->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
305 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
306 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
307 assert(0 && "Not a simple type!"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
308 // 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
|
309 // bumped to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
310 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
|
311 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
312 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
313 // 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
|
314 case Tfloat32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
315 case Tfloat64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
316 case Timaginary32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
317 case Timaginary64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
318 r.sse = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
319 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
320 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
321 case Tcomplex32: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
322 case Tcomplex64: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
323 r.sse = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
324 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
325 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
326 // 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
|
327 case Tfloat80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
328 case Timaginary80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
329 r.x87 = 1; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
330 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
331 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
332 case Tcomplex80: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
333 r.x87 = 2; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
334 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
335 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
336 // 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
|
337 // depending on its size. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
338 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
339 int needed = (t->size() + 7) / 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
340 assert(needed <= 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
341 r.ints = needed; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
342 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
343 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
344 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
345 return r; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
346 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
347 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
348 // 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
|
349 // specified number of registers. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
350 // (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
|
351 // reasons other than it not fitting) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
352 // 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
|
353 // 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
|
354 // If false is returned, 'left' is garbage. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
355 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
356 // 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
|
357 // so keep it in memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
358 if (hasUnalignedFields(t)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
359 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
360 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
361 Array* fields = &t->sym->fields; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
362 d_uns64 nextbyte = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
363 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
|
364 VarDeclaration* field = (VarDeclaration*) fields->data[i]; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
365 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
366 // 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
|
367 // without overlapping fields. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
368 if (field->offset < nextbyte) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
369 // 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
|
370 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
371 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
372 nextbyte = field->offset + field->type->size(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
373 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
374 switch (field->type->ty) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
375 case Tstruct: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
376 if (!shouldPassStructInRegs((TypeStruct*) field->type, left)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
377 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
378 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
379 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
380 case Tsarray: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
381 // Don't return static arrays in registers |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
382 // (indexing registers doesn't work well) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
383 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
384 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
385 default: { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
386 DRegCount needed = regsNeededForSimpleType(field->type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
387 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
|
388 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
389 left.ints -= needed.ints; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
390 left.sse -= needed.sse; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
391 left.x87 -= needed.x87; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
392 break; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
393 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
394 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
395 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
396 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
397 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
398 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
399 // 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
|
400 // calling convention. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
401 bool retStructInRegs(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
402 // '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
|
403 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
404 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
405 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
406 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
407 // 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
|
408 // bump it to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
409 bool passStructTypeDirectly(TypeStruct* st) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
410 // 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
|
411 // pass it directly. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
412 // 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
|
413 // 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
|
414 // parameters. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
415 DRegCount state(2, 2, 2); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
416 return shouldPassStructInRegs(st, state); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
417 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
418 // 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
|
419 // 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
|
420 /* |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
421 // 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
|
422 // 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
|
423 RegCount state(5, 8, 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
424 */ |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
425 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
426 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
427 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
428 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
429 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
430 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
431 //////////////////////////////////////////////////////////////////////////////// |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
432 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
433 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
434 /// 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
|
435 struct X86_64_C_struct_rewrite : ABIRewrite { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
436 // Get struct from ABI-mangled representation |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
437 LLValue* get(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
438 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
439 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
440 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
441 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
442 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
443 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
444 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
|
445 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
446 DtoStore(rval, lval); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
447 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
448 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
449 const LLType* pTy = getPtrToType(DtoType(dty)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
450 return DtoLoad(DtoBitCast(lval, pTy), "get-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
451 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
452 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
453 // 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
|
454 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
|
455 LLValue* rval = v->getRVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
456 const LLType* pTy = getPtrToType(rval->getType()); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
457 DtoStore(rval, DtoBitCast(lval, pTy)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
458 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
459 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
460 // 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
|
461 LLValue* put(Type* dty, DValue* v) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
462 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
463 LLValue* lval; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
464 if (v->isLVal()) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
465 lval = v->getLVal(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
466 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
467 // No memory location, create one. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
468 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
|
469 lval = DtoRawAlloca(rval->getType(), 0); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
470 DtoStore(rval, lval); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
471 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
472 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
473 LLType* abiTy = getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
474 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
|
475 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
476 const LLType* pTy = getPtrToType(abiTy); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
477 return DtoLoad(DtoBitCast(lval, pTy), "put-result"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
478 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
479 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
480 /// 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
|
481 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
|
482 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
483 return getAbiType(dty); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
484 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
485 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
486 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
487 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
488 struct RegCount { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
489 unsigned char int_regs, sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
490 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
491 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
492 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
493 struct X86_64TargetABI : TargetABI { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
494 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
|
495 RemoveStructPadding remove_padding; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
496 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
497 void newFunctionType(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
498 funcTypeStack.push_back(FuncTypeData(tf->linkage)); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
499 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
500 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
501 bool returnInArg(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
502 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
503 bool passByVal(Type* t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
504 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
505 void rewriteFunctionType(TypeFunction* tf); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
506 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
507 void doneWithFunctionType() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
508 funcTypeStack.pop_back(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
509 } |
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 private: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
512 struct FuncTypeData { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
513 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
|
514 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
|
515 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
516 FuncTypeData(LINK linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
517 : linkage(linkage_) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
518 { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
519 state.int_regs = 6; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
520 state.sse_regs = 8; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
521 } |
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 std::vector<FuncTypeData> funcTypeStack; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
524 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
525 LINK linkage() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
526 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
527 return funcTypeStack.back().linkage; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
528 } |
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 RegCount& state() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
531 assert(funcTypeStack.size() != 0); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
532 return funcTypeStack.back().state; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
533 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
534 |
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
|
535 void fixup_D(IrFuncTyArg& arg); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
536 void fixup(IrFuncTyArg& arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
537 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
538 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
539 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
540 // The public getter for abi.cpp |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
541 TargetABI* getX86_64TargetABI() { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
542 return new X86_64TargetABI; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
543 } |
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 bool X86_64TargetABI::returnInArg(TypeFunction* tf) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
547 assert(linkage() == tf->linkage); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
548 Type* rt = tf->next->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
549 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
550 if (tf->linkage == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
551 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
|
552 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
553 // 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
|
554 if (rt->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
555 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
556 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
557 // 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
|
558 // 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
|
559 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
|
560 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
561 if (rt == Type::tvoid || keepUnchanged(rt)) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
562 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
563 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
564 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
|
565 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
|
566 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
|
567 && "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
|
568 // 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
|
569 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
|
570 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
|
571 } |
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 return false; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
573 } |
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 bool X86_64TargetABI::passByVal(Type* t) { |
1049 | 577 t = t->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
578 if (linkage() == LINKd) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
579 if (t->ty != Tstruct) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
580 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
581 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
582 // 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
|
583 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
|
584 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
585 // 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
|
586 // 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
|
587 Classification cl = classify(t); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
588 if (cl.isMemory) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
589 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
590 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
591 // 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
|
592 RegCount wanted = { 0, 0 }; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
593 for (int i = 0 ; i < 2; i++) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
594 if (cl.classes[i] == Integer) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
595 wanted.int_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
596 else if (cl.classes[i] == Sse) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
597 wanted.sse_regs++; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
598 } |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
599 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
600 // See if they're available: |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
601 RegCount& state = this->state(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
602 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
|
603 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
604 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
605 } else { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
606 if (keepUnchanged(t)) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
607 // 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
|
608 // 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
|
609 // automatically spilling the rest to memory. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
610 if (wanted.int_regs > state.int_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
611 state.int_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
612 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
613 state.int_regs -= wanted.int_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
614 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
615 if (wanted.sse_regs > state.sse_regs) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
616 state.sse_regs = 0; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
617 else |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
618 state.sse_regs -= wanted.sse_regs; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
619 } else if (t->iscomplex() || t->ty == Tstruct) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
620 // 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
|
621 // available. |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
622 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
623 // 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
|
624 // (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
|
625 // 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
|
626 // more easily break it up? |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
627 // 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
|
628 // 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
|
629 return true; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
630 } else { |
1048 | 631 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
|
632 && "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
|
633 // 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
|
634 assert(!isaStruct(DtoType(t))); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
635 } |
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 // 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
|
638 return false; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
639 } |
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 // 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
|
643 // 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
|
644 // 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
|
645 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
|
646 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
|
647 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
|
648 |
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 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
|
650 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
|
651 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
|
652 } |
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 // Helper function for rewriteFunctionType. |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
656 // 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
|
657 // to get the rewrite applied (if necessary). |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
658 void X86_64TargetABI::fixup(IrFuncTyArg& arg) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
659 LLType* abiTy = getAbiType(arg.type); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
660 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
661 if (abiTy && abiTy != arg.ltype) { |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
662 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
|
663 arg.ltype = abiTy; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
664 arg.rewrite = &struct_rewrite; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
665 } |
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 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
|
669 IrFuncTy& fty = tf->fty; |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
670 |
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
|
671 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
|
672 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
|
673 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
|
674 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
|
675 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
|
676 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
|
677 } |
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 |
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
|
680 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
|
681 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
|
682 } |
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 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
|
684 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
|
685 } |
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 |
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
|
687 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
|
688 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
|
689 |
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 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
|
691 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
|
692 |
45aca7e7cc88
Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents:
1350
diff
changeset
|
693 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
|
694 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
|
695 |
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 // 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
|
697 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
|
698 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
|
699 |
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 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
|
701 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
|
702 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
|
703 |
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 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
|
705 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
|
706 } |
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 } else { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
709 // 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
|
710 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
711 if (!fty.arg_sret) { |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
712 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
|
713 Type* rt = fty.ret->type->toBasetype(); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
714 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
|
715 fixup(*fty.ret); |
1047
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
716 } |
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 Logger::println("x86-64 ABI: Transforming arguments"); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
720 LOG_SCOPE; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
721 |
1051
dc608dc33081
Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents:
1049
diff
changeset
|
722 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
|
723 IrFuncTyArg& arg = **I; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
724 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
725 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
726 Logger::cout() << "Arg: " << arg.type->toChars() << '\n'; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
727 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
728 // 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
|
729 if (arg.byref) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
730 continue; |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
731 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
732 Type* ty = arg.type->toBasetype(); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
733 |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
734 fixup(arg); |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
735 if (Logger::enabled()) |
6bb04dbee21f
Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff
changeset
|
736 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
|
737 } |
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 } |