annotate gen/abi-x86-64.cpp @ 1354:701d11a1e7b1

Re-apply [1346], which was reverted in [1348], now that padding should no longer be a problem. As noted before, this will break ABI-compatibility on x86-64, so recompile old code before linking with newly-compiled code if you're on x86-64. As an added bonus, I actually tested it this time :).
author Frits van Bommel <fvbommel wxs.nl>
date Thu, 14 May 2009 20:40:56 +0200
parents 45aca7e7cc88
children 34f2fd925de3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
1 /* TargetABI implementation for x86-64.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
2 * Written for LDC by Frits van Bommel in 2009.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
3 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
4 * extern(D) follows no particular external ABI, but tries to be smart about
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
5 * passing structs and returning them. It should probably be reviewed if the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
6 * way LLVM implements fastcc on this platform ever changes.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
7 * (Specifically, the number of return registers of various types is hardcoded)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
8 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
9 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
10 * extern(C) implements the C calling convention for x86-64, as found in
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
11 * http://www.x86-64.org/documentation/abi-0.99.pdf
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
12 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
13 * Note:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
14 * Where a discrepancy was found between llvm-gcc and the ABI documentation,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
15 * llvm-gcc behavior was used for compatibility (after it was verified that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
16 * regular gcc has the same behavior).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
17 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
18 * LLVM gets it right for most types, but complex numbers and structs need some
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
19 * help. To make sure it gets those right we essentially bitcast small structs
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
20 * to a type to which LLVM assigns the appropriate registers, and pass that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
21 * instead. Structs that are required to be passed in memory are explicitly
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
22 * marked with the ByVal attribute to ensure no part of them ends up in
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
23 * registers when only a subset of the desired registers are available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
24 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
25 * We don't perform the same transformation for D-specific types that contain
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
26 * multiple parts, such as dynamic arrays and delegates. They're passed as if
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
27 * the parts were passed as separate parameters. This helps make things like
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
28 * printf("%.*s", o.toString()) work as expected; if we didn't do this that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
29 * wouldn't work if there were 4 other integer/pointer arguments before the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
30 * toString() call because the string got bumped to memory with one integer
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
31 * register still free. Keeping it untransformed puts the length in a register
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
32 * and the pointer in memory, as printf expects it.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
33 */
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
34
1063
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
35 #include "mtype.h"
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
36 #include "declaration.h"
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
37 #include "aggregate.h"
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
38
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
39 #include "gen/llvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
40 #include "gen/tollvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
41 #include "gen/logger.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
42 #include "gen/dvalue.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
43 #include "gen/llvmhelpers.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
44 #include "gen/abi.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
45 #include "gen/abi-x86-64.h"
1353
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
46 #include "gen/structs.h"
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
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
488 /// Removes padding fields for (non-union-containing!) structs
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
489 struct RemoveStructPadding : ABIRewrite {
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
490 /// get a rewritten value back to its original form
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
491 virtual LLValue* get(Type* dty, DValue* v) {
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
492 LLValue* lval = DtoAlloca(dty, ".rewritetmp");
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
493
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
494 // Make sure the padding is zero, so struct comparisons work.
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
495 // TODO: Only do this if there's padding, and/or only initialize padding.
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
496 DtoMemSetZero(lval, DtoConstSize_t(getTypePaddedSize(DtoType(dty))));
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
497
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
498 DtoPaddedStruct(dty, v->getRVal(), lval);
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
499 return lval;
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
500 }
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
501
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
502 /// get a rewritten value back to its original form and store result in provided lvalue
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
503 /// this one is optional and defaults to calling the one above
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
504 virtual void getL(Type* dty, DValue* v, llvm::Value* lval) {
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
505 DtoPaddedStruct(dty, v->getRVal(), lval);
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
506 }
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
507
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
508 /// put out rewritten value
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
509 virtual LLValue* put(Type* dty, DValue* v) {
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
510 return DtoUnpaddedStruct(dty, v->getRVal());
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
511 }
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
512
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
513 /// return the transformed type for this rewrite
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
514 virtual const LLType* type(Type* dty, const LLType* t) {
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
515 return DtoUnpaddedStructType(dty);
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
516 }
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
517 };
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
518
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
519
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
520 struct RegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
521 unsigned char int_regs, sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
522 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
523
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
524
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
525 struct X86_64TargetABI : TargetABI {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
526 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
527 RemoveStructPadding remove_padding;
1047
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 void newFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
530 funcTypeStack.push_back(FuncTypeData(tf->linkage));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
531 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
532
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
533 bool returnInArg(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
534
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
535 bool passByVal(Type* t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
536
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
537 void rewriteFunctionType(TypeFunction* tf);
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 void doneWithFunctionType() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
540 funcTypeStack.pop_back();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
541 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
542
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
543 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
544 struct FuncTypeData {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
545 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
546 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
547
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
548 FuncTypeData(LINK linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
549 : linkage(linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
550 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
551 state.int_regs = 6;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
552 state.sse_regs = 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
553 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
554 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
555 std::vector<FuncTypeData> funcTypeStack;
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 LINK linkage() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
558 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
559 return funcTypeStack.back().linkage;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
560 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
561
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
562 RegCount& state() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
563 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
564 return funcTypeStack.back().state;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
565 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
566
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
567 void fixup_D(IrFuncTyArg& arg);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
568 void fixup(IrFuncTyArg& arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
569 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
570
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
571
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
572 // The public getter for abi.cpp
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
573 TargetABI* getX86_64TargetABI() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
574 return new X86_64TargetABI;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
575 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
576
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
577
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
578 bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
579 assert(linkage() == tf->linkage);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
580 Type* rt = tf->next->toBasetype();
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 if (tf->linkage == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
583 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
584
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
585 // 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
586 if (rt->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
587 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
588
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
589 // 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
590 // 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
591 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
592 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
593 if (rt == Type::tvoid || keepUnchanged(rt))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
594 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
595
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
596 Classification cl = classify(rt);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
597 return cl.isMemory;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
601 bool X86_64TargetABI::passByVal(Type* t) {
1049
afe271b0e271 Two small bugfixes:
Frits van Bommel <fvbommel wxs.nl>
parents: 1048
diff changeset
602 t = t->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
603 if (linkage() == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
604 if (t->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
605 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
606
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
607 // 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
608 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
609 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
610 // 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
611 // 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
612 Classification cl = classify(t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
613 if (cl.isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
614 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
615
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
616 // 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
617 RegCount wanted = { 0, 0 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
618 for (int i = 0 ; i < 2; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
619 if (cl.classes[i] == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
620 wanted.int_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
621 else if (cl.classes[i] == Sse)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
622 wanted.sse_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
623 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
624
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
625 // See if they're available:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
626 RegCount& state = this->state();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
627 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
628 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
629 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
630 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
631 if (keepUnchanged(t)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
632 // 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
633 // 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
634 // automatically spilling the rest to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
635 if (wanted.int_regs > state.int_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
636 state.int_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
637 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
638 state.int_regs -= wanted.int_regs;
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 if (wanted.sse_regs > state.sse_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
641 state.sse_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
642 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
643 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
644 } else if (t->iscomplex() || t->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
645 // 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
646 // available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
647
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
648 // 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
649 // (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
650 // 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
651 // more easily break it up?
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
652 // 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
653 // 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
654 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
655 } else {
1048
f9333daa1bf5 Fix a typo
Frits van Bommel <fvbommel wxs.nl>
parents: 1047
diff changeset
656 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
657 && "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
658 // 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
659 assert(!isaStruct(DtoType(t)));
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
662 // 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
663 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
664 }
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 // 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
668 // 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
669 // 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
670 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
671 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
672 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
673
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 (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
675 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
676 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
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
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
680 // Helper function for rewriteFunctionType.
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
681 // 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
682 // to get the rewrite applied (if necessary).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
683 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
684 LLType* abiTy = getAbiType(arg.type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
685
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
686 if (abiTy && abiTy != arg.ltype) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
687 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
688 arg.ltype = abiTy;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
689 arg.rewrite = &struct_rewrite;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
690 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
691 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
692
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
693 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
694 IrFuncTy& fty = tf->fty;
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
695
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
696 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
697 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
698 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
699 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
700 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
701 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
702 }
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
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::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
706 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
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 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
709 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
710
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
711 if (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
712 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
713
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
714 // 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
715 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
716 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
717
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
718 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
719 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
720 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
721
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
722 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
723 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
724 }
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
725
45aca7e7cc88 Remove struct padding when passing or returning in registers on x86-64 (extern(D) only)
Frits van Bommel <fvbommel wxs.nl>
parents: 1350
diff changeset
726 } else {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
727 // 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
728
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
729 if (!fty.arg_sret) {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
730 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
731 Type* rt = fty.ret->type->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
732 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
733 fixup(*fty.ret);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
734 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
735
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
736
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
737 Logger::println("x86-64 ABI: Transforming arguments");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
738 LOG_SCOPE;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
739
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
740 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
741 IrFuncTyArg& arg = **I;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
742
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
743 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
744 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
745
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
746 // 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
747 if (arg.byref)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
748 continue;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
749
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
750 Type* ty = arg.type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
751
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
752 fixup(arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
753
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
754 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
755 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
756 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
757 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
758 }