annotate gen/abi-x86-64.cpp @ 1047:6bb04dbee21f

Some calling convention work for x86-64: - Implement x86-64 extern(C), hopefully correctly. - Tried to be a bit smarter about extern(D) while I was there. Interestingly, this code seems to be generating more efficient code than gcc and llvm-gcc in some edge cases, like returning a `{ [7 x i8] }` loaded from a stack slot from an extern(C) function. (gcc generates 7 1-byte loads, while this code generates a 4-byte, a 2-byte and a 1-byte load) I also added some changes to make sure structs being returned from functions or passed in as parameters are stored in memory where the rest of the backend seems to expect them to be. These should be removed when support for first-class aggregates improves.
author Frits van Bommel <fvbommel wxs.nl>
date Fri, 06 Mar 2009 16:00:47 +0100
parents
children f9333daa1bf5
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
35 #include "dmd/mtype.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
36 #include "dmd/declaration.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
37 #include "dmd/aggregate.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
38
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
39 #include "gen/llvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
40 #include "gen/tollvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
41 #include "gen/logger.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
42 #include "gen/dvalue.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
43 #include "gen/llvmhelpers.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
44 #include "gen/abi.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
45 #include "gen/abi-x86-64.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
46 #include "ir/irfunction.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
47
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
48 #include <cassert>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
49 #include <map>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
50 #include <string>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
51 #include <utility>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
52
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
53 // Implementation details for extern(C)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
54 namespace {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
55 /**
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
56 * This function helps filter out things that look like structs to C,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
57 * but should be passed to C in separate arguments anyway.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
58 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
59 * (e.g. dynamic arrays are passed as separate length and ptr. This
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
60 * is both less work and makes printf("%.*s", o.toString()) work)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
61 */
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
62 inline bool keepUnchanged(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
63 switch (t->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
64 case Tarray: // dynamic array
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
65 case Taarray: // assoc array
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
66 case Tdelegate:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
67 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
68
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
69 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
70 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
71 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
72 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
73
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
74 enum ArgClass {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
75 Integer, Sse, SseUp, X87, X87Up, ComplexX87, NoClass, Memory
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
76 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
77
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
78 struct Classification {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
79 bool isMemory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
80 ArgClass classes[2];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
81
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
82 Classification() : isMemory(false) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
83 classes[0] = NoClass;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
84 classes[1] = NoClass;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
85 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
86
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
87 void addField(unsigned offset, ArgClass cl) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
88 if (isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
89 return;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
90
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
91 // Note that we don't need to bother checking if it crosses 8 bytes.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
92 // We don't get here with unaligned fields, and anything that can be
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
93 // big enough to cross 8 bytes (cdoubles, reals, structs and arrays)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
94 // is special-cased in classifyType()
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
95 int idx = (offset < 8 ? 0 : 1);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
96
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
97 ArgClass nw = merge(classes[idx], cl);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
98 if (nw != classes[idx]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
99 classes[idx] = nw;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
100
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
101 if (nw == Memory) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
102 classes[1-idx] = Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
103 isMemory = true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
104 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
105 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
106 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
107
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
108 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
109 ArgClass merge(ArgClass accum, ArgClass cl) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
110 if (accum == cl)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
111 return accum;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
112 if (accum == NoClass)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
113 return cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
114 if (cl == NoClass)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
115 return accum;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
116 if (accum == Memory || cl == Memory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
117 return Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
118 if (accum == Integer || cl == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
119 return Integer;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
120 if (accum == X87 || accum == X87Up || accum == ComplexX87 ||
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
121 cl == X87 || cl == X87Up || cl == ComplexX87)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
122 return Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
123 return Sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
124 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
125 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
126
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
127 void classifyType(Classification& accum, Type* ty, d_uns64 offset) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
128 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
129 Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
130
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
131 ty = ty->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
132
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
133 if (ty->isintegral() || ty->ty == Tpointer) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
134 accum.addField(offset, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
135 } else if (ty->ty == Tfloat80 || ty->ty == Timaginary80) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
136 accum.addField(offset, X87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
137 accum.addField(offset+8, X87Up);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
138 } else if (ty->ty == Tcomplex80) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
139 accum.addField(offset, ComplexX87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
140 // make sure other half knows about it too:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
141 accum.addField(offset+16, ComplexX87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
142 } else if (ty->ty == Tcomplex64) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
143 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
144 accum.addField(offset+8, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
145 } else if (ty->ty == Tcomplex32) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
146 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
147 accum.addField(offset+4, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
148 } else if (ty->isfloating()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
149 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
150 } else if (ty->size() > 16 || hasUnalignedFields(ty)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
151 // This isn't creal, yet is > 16 bytes, so pass in memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
152 // Must be after creal case but before arrays and structs,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
153 // the other types that can get bigger than 16 bytes
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
154 accum.addField(offset, Memory);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
155 } else if (ty->ty == Tsarray) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
156 d_uns64 eltsize = ty->next->size();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
157 if (eltsize > 0) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
158 d_uns64 dim = ty->size() / eltsize;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
159 assert(dim <= 16
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
160 && "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
161 for (d_uns64 i = 0; i < dim; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
162 classifyType(accum, ty->next, offset);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
163 offset += eltsize;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
164 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
165 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
166 } else if (ty->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
167 Array* fields = &((TypeStruct*) ty)->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
168 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
169 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
170 classifyType(accum, field->type, offset + field->offset);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
171 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
172 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
173 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
174 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
175 << ty->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
176 // 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
177 assert(offset == 0 || offset == 8
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
178 && "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
179 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
180
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
181 accum.addField(offset, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
182 if (ty->size() > 8)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
183 accum.addField(offset+8, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
184 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
185 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
186
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
187 Classification classify(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
188 typedef std::map<Type*, Classification> ClassMap;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
189 static ClassMap cache;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
190
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
191 ClassMap::iterator it = cache.find(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
192 if (it != cache.end()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
193 return it->second;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
194 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
195 Classification cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
196 classifyType(cl, ty, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
197 cache[ty] = cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
198 return cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
199 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
200 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
201
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
202 /// 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
203 LLType* getAbiType(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
204 ty = ty->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
205
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
206 // 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
207
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
208 if (keepUnchanged(ty))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
209 return 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
210
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
211 if (ty->ty != Tcomplex32 && ty->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
212 return 0; // Nothing to do,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
213
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
214 Classification cl = classify(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
215 assert(!cl.isMemory);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
216
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
217 if (cl.classes[0] == NoClass) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
218 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
219 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
220 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
221
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
222 // 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
223
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
224 std::vector<const LLType*> parts;
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 unsigned size = ty->size();
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 switch (cl.classes[0]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
229 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
230 unsigned bits = (size >= 8 ? 64 : (size * 8));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
231 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
232 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
233 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
234
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
235 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
236 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
237 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
238
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
239 case X87:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
240 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
241 /// 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
242 /// so just use that type.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
243 return const_cast<LLType*>(LLType::X86_FP80Ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
244
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
245 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
246 assert(0 && "Unanticipated argument class");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
247 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
248
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
249 switch(cl.classes[1]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
250 case NoClass:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
251 assert(parts.size() == 1);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
252 // 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
253 // Just use the element type instead.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
254 return const_cast<LLType*>(parts[0]);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
255 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
256
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
257 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
258 assert(size > 8);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
259 unsigned bits = (size - 8) * 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
260 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
261 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
262 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
263 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
264 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
265 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
266
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
267 case X87Up:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
268 if(cl.classes[0] == X87) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
269 // 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
270 // processing the first half.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
271 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
272 // 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
273 // 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
274 // (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
275 parts.push_back(LLType::DoubleTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
276 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
277 break;
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 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
280 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
281 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
282 return LLStructType::get(parts);
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 }
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 // Implementation details for extern(D)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
288 namespace x86_64_D_cc {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
289 struct DRegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
290 unsigned ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
291 unsigned sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
292 unsigned x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
293
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
294 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
295 : ints(ints_), sse(sse_), x87(x87_) {}
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
296 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
297
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
298 // 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
299 // (Not a struct or static array)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
300 DRegCount regsNeededForSimpleType(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
301 DRegCount r(0, 0, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
302 switch(t->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
303 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
304 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
305 assert(0 && "Not a simple type!");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
306 // 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
307 // bumped to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
308 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
309 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
310
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
311 // 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
312 case Tfloat32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
313 case Tfloat64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
314 case Timaginary32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
315 case Timaginary64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
316 r.sse = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
317 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
318
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
319 case Tcomplex32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
320 case Tcomplex64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
321 r.sse = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
322 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
323
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
324 // 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
325 case Tfloat80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
326 case Timaginary80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
327 r.x87 = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
328 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
329
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
330 case Tcomplex80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
331 r.x87 = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
332 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
333
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
334 // 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
335 // depending on its size.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
336 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
337 int needed = (t->size() + 7) / 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
338 assert(needed <= 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
339 r.ints = needed;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
340 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
341 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
342 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
343 return r;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
344 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
345
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
346 // 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
347 // specified number of registers.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
348 // (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
349 // reasons other than it not fitting)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
350 // 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
351 // 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
352 // If false is returned, 'left' is garbage.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
353 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
354 // 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
355 // so keep it in memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
356 if (hasUnalignedFields(t))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
357 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
358
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
359 Array* fields = &t->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
360 d_uns64 nextbyte = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
361 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
362 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
363
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
364 // 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
365 // without overlapping fields.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
366 if (field->offset < nextbyte) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
367 // 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
368 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
369 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
370 nextbyte = field->offset + field->type->size();
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 switch (field->type->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
373 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
374 if (!shouldPassStructInRegs((TypeStruct*) field->type, left))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
375 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
376 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
377
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
378 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
379 // Don't return static arrays in registers
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
380 // (indexing registers doesn't work well)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
381 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
382
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
383 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
384 DRegCount needed = regsNeededForSimpleType(field->type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
385 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
386 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
387 left.ints -= needed.ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
388 left.sse -= needed.sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
389 left.x87 -= needed.x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
390 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
391 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
392 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
393 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
394 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
395 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
396
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
397 // 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
398 // calling convention.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
399 bool retStructInRegs(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
400 // '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
401 DRegCount state(2, 2, 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
402 return shouldPassStructInRegs(st, state);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
403 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
404
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
405 // 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
406 // bump it to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
407 bool passStructTypeDirectly(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
408 // 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
409 // pass it directly.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
410 // 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
411 // 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
412 // parameters.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
413 DRegCount state(2, 2, 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
414 return shouldPassStructInRegs(st, state);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
415
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
416 // 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
417 // 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
418 /*
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
419 // 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
420 // 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
421 RegCount state(5, 8, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
422 */
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
423 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
424 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
425
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
426 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
427 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
428 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
429 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
430
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
431
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
432 /// 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
433 struct X86_64_C_struct_rewrite : ABIRewrite {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
434 // Get struct from ABI-mangled representation
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
435 LLValue* get(Type* dty, DValue* v)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
436 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
437 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
438 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
439 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
440 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
441 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
442 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
443 lval = DtoAlloca(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
444 DtoStore(rval, lval);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
445 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
446
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
447 const LLType* pTy = getPtrToType(DtoType(dty));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
448 return DtoLoad(DtoBitCast(lval, pTy), "get-result");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
449 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
450
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
451 // 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
452 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
453 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
454 const LLType* pTy = getPtrToType(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
455 DtoStore(rval, DtoBitCast(lval, pTy));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
456 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
457
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
458 // 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
459 LLValue* put(Type* dty, DValue* v)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
460 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
461 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
462 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
463 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
464 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
465 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
466 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
467 lval = DtoAlloca(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
468 DtoStore(rval, lval);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
469 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
470
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
471 LLType* abiTy = getAbiType(dty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
472 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
473
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
474 const LLType* pTy = getPtrToType(abiTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
475 return DtoLoad(DtoBitCast(lval, pTy), "put-result");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
476 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
477
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
478 /// 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
479 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
480 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
481 return getAbiType(dty);
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 };
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 struct RegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
487 unsigned char int_regs, sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
488 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
489
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
490
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
491 struct X86_64TargetABI : TargetABI {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
492 X86_64_C_struct_rewrite struct_rewrite;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
493
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
494 void newFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
495 funcTypeStack.push_back(FuncTypeData(tf->linkage));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
496 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
497
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
498 bool returnInArg(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
499
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
500 bool passByVal(Type* t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
501
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
502 void rewriteFunctionType(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
503
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
504 void doneWithFunctionType() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
505 funcTypeStack.pop_back();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
506 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
507
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
508 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
509 struct FuncTypeData {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
510 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
511 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
512
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
513 FuncTypeData(LINK linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
514 : linkage(linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
515 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
516 state.int_regs = 6;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
517 state.sse_regs = 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
518 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
519 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
520 std::vector<FuncTypeData> funcTypeStack;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
521
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
522 LINK linkage() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
523 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
524 return funcTypeStack.back().linkage;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
525 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
526
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
527 RegCount& state() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
528 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
529 return funcTypeStack.back().state;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
530 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
531
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
532 void fixup(IrFuncTyArg& arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
533 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
534
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
535
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
536 // The public getter for abi.cpp
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
537 TargetABI* getX86_64TargetABI() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
538 return new X86_64TargetABI;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
539 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
540
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
541
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
542 bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
543 assert(linkage() == tf->linkage);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
544 Type* rt = tf->next->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
545
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
546 if (tf->linkage == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
547 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
548
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
549 // 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
550 if (rt->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
551 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
552
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
553 // 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
554 // 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
555 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
556 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
557 if (rt == Type::tvoid || keepUnchanged(rt))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
558 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
559
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
560 Classification cl = classify(rt);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
561 return cl.isMemory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
562 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
563 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
564
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
565 bool X86_64TargetABI::passByVal(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
566 if (linkage() == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
567 if (t->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
568 return false;
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 // 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
571 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
572 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
573 // 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
574 // 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
575 Classification cl = classify(t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
576 if (cl.isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
577 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
578
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
579 // 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
580 RegCount wanted = { 0, 0 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
581 for (int i = 0 ; i < 2; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
582 if (cl.classes[i] == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
583 wanted.int_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
584 else if (cl.classes[i] == Sse)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
585 wanted.sse_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
586 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
587
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
588 // See if they're available:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
589 RegCount& state = this->state();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
590 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
591 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
592 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
593 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
594 if (keepUnchanged(t)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
595 // 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
596 // 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
597 // automatically spilling the rest to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
598 if (wanted.int_regs > state.int_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
599 state.int_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
600 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
601 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
602
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
603 if (wanted.sse_regs > state.sse_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
604 state.sse_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
605 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
606 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
607 } else if (t->iscomplex() || t->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
608 // 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
609 // available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
610
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
611 // 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
612 // (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
613 // 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
614 // more easily break it up?
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
615 // 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
616 // 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
617 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
618 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
619 assert(t == Type::tfloat80 || t == Type::timaginary80 || t->size() < 8
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
620 && "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
621 // 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
622 assert(!isaStruct(DtoType(t)));
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 // 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
626 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
627 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
628 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
629
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
630 // Helper function for rewriteFunctionType.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
631 // 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
632 // to get the rewrite applied (if necessary).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
633 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
634 LLType* abiTy = getAbiType(arg.type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
635
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
636 if (abiTy && abiTy != arg.ltype) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
637 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
638 arg.ltype = abiTy;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
639 arg.rewrite = &struct_rewrite;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
640 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
641 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
642
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
643 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
644 // extern(D) is handled entirely by passByVal and returnInArg
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
645
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
646 if (tf->linkage != LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
647 // 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
648
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
649 IrFuncTy* fty = tf->fty;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
650
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
651 if (!fty->arg_sret) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
652 Logger::println("x86-64 ABI: Transforming return type");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
653 Type* rt = fty->ret->type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
654 if (rt != Type::tvoid)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
655 fixup(*fty->ret);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
656 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
657
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
658
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
659 Logger::println("x86-64 ABI: Transforming arguments");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
660 LOG_SCOPE;
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 for (IrFuncTy::ArgIter I = fty->args.begin(), E = fty->args.end(); I != E; ++I) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
663 IrFuncTyArg& arg = **I;
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 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
666 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
667
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
668 // 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
669 if (arg.byref)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
670 continue;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
671
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
672 Type* ty = arg.type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
673
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
674 fixup(arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
675
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
676 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
677 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
678 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
679 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
680 }