annotate gen/abi-x86-64.cpp @ 1051:dc608dc33081

Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the same LDC call.
author Christian Kamm <kamm incasoftware de>
date Sat, 07 Mar 2009 14:25:30 +0100
parents afe271b0e271
children a3d7288c4473
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) {
1049
afe271b0e271 Two small bugfixes:
Frits van Bommel <fvbommel wxs.nl>
parents: 1048
diff changeset
566 t = t->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
567 if (linkage() == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
568 if (t->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
569 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
570
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
571 // 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
572 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
573 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
574 // 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
575 // 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
576 Classification cl = classify(t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
577 if (cl.isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
578 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
579
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
580 // 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
581 RegCount wanted = { 0, 0 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
582 for (int i = 0 ; i < 2; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
583 if (cl.classes[i] == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
584 wanted.int_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
585 else if (cl.classes[i] == Sse)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
586 wanted.sse_regs++;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
589 // See if they're available:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
590 RegCount& state = this->state();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
591 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
592 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
593 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
594 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
595 if (keepUnchanged(t)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
596 // 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
597 // 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
598 // automatically spilling the rest to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
599 if (wanted.int_regs > state.int_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
600 state.int_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
601 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
602 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
603
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
604 if (wanted.sse_regs > state.sse_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
605 state.sse_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
606 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
607 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
608 } else if (t->iscomplex() || t->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
609 // 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
610 // available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
611
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
612 // 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
613 // (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
614 // 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
615 // more easily break it up?
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
616 // 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
617 // 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
618 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
619 } else {
1048
f9333daa1bf5 Fix a typo
Frits van Bommel <fvbommel wxs.nl>
parents: 1047
diff changeset
620 assert(t == Type::tfloat80 || t == Type::timaginary80 || t->size() <= 8
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
621 && "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
622 // 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
623 assert(!isaStruct(DtoType(t)));
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
626 // 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
627 return false;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
631 // Helper function for rewriteFunctionType.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
632 // 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
633 // to get the rewrite applied (if necessary).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
634 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
635 LLType* abiTy = getAbiType(arg.type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
636
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
637 if (abiTy && abiTy != arg.ltype) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
638 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
639 arg.ltype = abiTy;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
640 arg.rewrite = &struct_rewrite;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
644 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
645 // 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
646
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
647 if (tf->linkage != LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
648 // 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
649
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
650 IrFuncTy& fty = tf->fty;
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
651
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
652 if (!fty.arg_sret) {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
653 Logger::println("x86-64 ABI: Transforming return type");
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
654 Type* rt = fty.ret->type->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
655 if (rt != Type::tvoid)
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
656 fixup(*fty.ret);
1047
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
660 Logger::println("x86-64 ABI: Transforming arguments");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
661 LOG_SCOPE;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
662
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
663 for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
664 IrFuncTyArg& arg = **I;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
665
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
666 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
667 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
668
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
669 // 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
670 if (arg.byref)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
671 continue;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
672
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
673 Type* ty = arg.type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
674
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
675 fixup(arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
676
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
677 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
678 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
679 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
680 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
681 }