annotate gen/abi-x86-64.cpp @ 1083:c1e9f612e2e2

Fix for dual operand form of fistp, also make reg ST(0) explicit and fix lindquists previous code that allowed dual operand form of fstp but dissallowed the single operand form accidently
author Kelly Wilson <wilsonk cpsc.ucalgary.ca>
date Tue, 10 Mar 2009 06:23:26 -0600
parents 40d7f9b7357f
children f2f13f111e2e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
1 /* TargetABI implementation for x86-64.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
2 * Written for LDC by Frits van Bommel in 2009.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
3 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
4 * extern(D) follows no particular external ABI, but tries to be smart about
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
5 * passing structs and returning them. It should probably be reviewed if the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
6 * way LLVM implements fastcc on this platform ever changes.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
7 * (Specifically, the number of return registers of various types is hardcoded)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
8 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
9 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
10 * extern(C) implements the C calling convention for x86-64, as found in
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
11 * http://www.x86-64.org/documentation/abi-0.99.pdf
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
12 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
13 * Note:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
14 * Where a discrepancy was found between llvm-gcc and the ABI documentation,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
15 * llvm-gcc behavior was used for compatibility (after it was verified that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
16 * regular gcc has the same behavior).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
17 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
18 * LLVM gets it right for most types, but complex numbers and structs need some
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
19 * help. To make sure it gets those right we essentially bitcast small structs
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
20 * to a type to which LLVM assigns the appropriate registers, and pass that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
21 * instead. Structs that are required to be passed in memory are explicitly
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
22 * marked with the ByVal attribute to ensure no part of them ends up in
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
23 * registers when only a subset of the desired registers are available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
24 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
25 * We don't perform the same transformation for D-specific types that contain
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
26 * multiple parts, such as dynamic arrays and delegates. They're passed as if
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
27 * the parts were passed as separate parameters. This helps make things like
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
28 * printf("%.*s", o.toString()) work as expected; if we didn't do this that
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
29 * wouldn't work if there were 4 other integer/pointer arguments before the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
30 * toString() call because the string got bumped to memory with one integer
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
31 * register still free. Keeping it untransformed puts the length in a register
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
32 * and the pointer in memory, as printf expects it.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
33 */
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
34
1063
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
35 #include "mtype.h"
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
36 #include "declaration.h"
40d7f9b7357f Fixed some #includes to be correct for both D1 and D2
Frits van Bommel <fvbommel wxs.nl>
parents: 1054
diff changeset
37 #include "aggregate.h"
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
38
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
39 #include "gen/llvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
40 #include "gen/tollvm.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
41 #include "gen/logger.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
42 #include "gen/dvalue.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
43 #include "gen/llvmhelpers.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
44 #include "gen/abi.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
45 #include "gen/abi-x86-64.h"
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) {
1054
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
156 Type* eltType = ty->nextOf();
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
157 d_uns64 eltsize = eltType->size();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
158 if (eltsize > 0) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
159 d_uns64 dim = ty->size() / eltsize;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
160 assert(dim <= 16
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
161 && "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
162 for (d_uns64 i = 0; i < dim; i++) {
1054
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
163 classifyType(accum, eltType, offset);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
164 offset += eltsize;
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
167 } else if (ty->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
168 Array* fields = &((TypeStruct*) ty)->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
169 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
170 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
171 classifyType(accum, field->type, offset + field->offset);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
172 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
173 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
174 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
175 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
176 << ty->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
177 // 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
178 assert(offset == 0 || offset == 8
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
179 && "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
180 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
181
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
182 accum.addField(offset, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
183 if (ty->size() > 8)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
184 accum.addField(offset+8, Integer);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
188 Classification classify(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
189 typedef std::map<Type*, Classification> ClassMap;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
190 static ClassMap cache;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
191
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
192 ClassMap::iterator it = cache.find(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
193 if (it != cache.end()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
194 return it->second;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
195 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
196 Classification cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
197 classifyType(cl, ty, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
198 cache[ty] = cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
199 return cl;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
203 /// 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
204 LLType* getAbiType(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
205 ty = ty->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
206
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
207 // 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
208
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
209 if (keepUnchanged(ty))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
210 return 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
211
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
212 if (ty->ty != Tcomplex32 && ty->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
213 return 0; // Nothing to do,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
214
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
215 Classification cl = classify(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
216 assert(!cl.isMemory);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
217
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
218 if (cl.classes[0] == NoClass) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
219 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
220 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
221 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
222
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
223 // 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
224
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
225 std::vector<const LLType*> parts;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
226
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
227 unsigned size = ty->size();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
228
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
229 switch (cl.classes[0]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
230 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
231 unsigned bits = (size >= 8 ? 64 : (size * 8));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
232 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
233 break;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
236 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
237 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
238 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
239
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
240 case X87:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
241 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
242 /// 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
243 /// so just use that type.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
244 return const_cast<LLType*>(LLType::X86_FP80Ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
245
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
246 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
247 assert(0 && "Unanticipated argument class");
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
250 switch(cl.classes[1]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
251 case NoClass:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
252 assert(parts.size() == 1);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
253 // 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
254 // Just use the element type instead.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
255 return const_cast<LLType*>(parts[0]);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
256 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
257
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
258 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
259 assert(size > 8);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
260 unsigned bits = (size - 8) * 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
261 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
262 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
263 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
264 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
265 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
266 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
267
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
268 case X87Up:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
269 if(cl.classes[0] == X87) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
270 // 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
271 // processing the first half.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
272 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
273 // 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
274 // 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
275 // (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
276 parts.push_back(LLType::DoubleTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
277 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
278 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
279
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
280 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
281 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
282 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
283 return LLStructType::get(parts);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
288 // Implementation details for extern(D)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
289 namespace x86_64_D_cc {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
290 struct DRegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
291 unsigned ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
292 unsigned sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
293 unsigned x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
294
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
295 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
296 : ints(ints_), sse(sse_), x87(x87_) {}
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
299 // 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
300 // (Not a struct or static array)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
301 DRegCount regsNeededForSimpleType(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
302 DRegCount r(0, 0, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
303 switch(t->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
304 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
305 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
306 assert(0 && "Not a simple type!");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
307 // 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
308 // bumped to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
309 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
310 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
311
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
312 // 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
313 case Tfloat32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
314 case Tfloat64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
315 case Timaginary32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
316 case Timaginary64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
317 r.sse = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
318 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
319
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
320 case Tcomplex32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
321 case Tcomplex64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
322 r.sse = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
323 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
324
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
325 // 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
326 case Tfloat80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
327 case Timaginary80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
328 r.x87 = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
329 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
330
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
331 case Tcomplex80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
332 r.x87 = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
333 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
334
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
335 // 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
336 // depending on its size.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
337 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
338 int needed = (t->size() + 7) / 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
339 assert(needed <= 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
340 r.ints = needed;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
341 break;
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
344 return r;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
347 // 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
348 // specified number of registers.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
349 // (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
350 // reasons other than it not fitting)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
351 // 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
352 // 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
353 // If false is returned, 'left' is garbage.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
354 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
355 // 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
356 // so keep it in memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
357 if (hasUnalignedFields(t))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
358 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
359
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
360 Array* fields = &t->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
361 d_uns64 nextbyte = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
362 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
363 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
364
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
365 // 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
366 // without overlapping fields.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
367 if (field->offset < nextbyte) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
368 // 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
369 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
370 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
371 nextbyte = field->offset + field->type->size();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
372
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
373 switch (field->type->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
374 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
375 if (!shouldPassStructInRegs((TypeStruct*) field->type, left))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
376 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
377 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
378
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
379 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
380 // Don't return static arrays in registers
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
381 // (indexing registers doesn't work well)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
382 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
383
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
384 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
385 DRegCount needed = regsNeededForSimpleType(field->type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
386 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
387 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
388 left.ints -= needed.ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
389 left.sse -= needed.sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
390 left.x87 -= needed.x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
391 break;
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
395 return true;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
398 // 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
399 // calling convention.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
400 bool retStructInRegs(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
401 // '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
402 DRegCount state(2, 2, 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
403 return shouldPassStructInRegs(st, state);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
406 // 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
407 // bump it to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
408 bool passStructTypeDirectly(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
409 // 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
410 // pass it directly.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
411 // 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
412 // 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
413 // parameters.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
414 DRegCount state(2, 2, 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
415 return shouldPassStructInRegs(st, state);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
416
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
417 // 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
418 // 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
419 /*
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
420 // 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
421 // 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
422 RegCount state(5, 8, 0);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
433 /// 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
434 struct X86_64_C_struct_rewrite : ABIRewrite {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
435 // Get struct from ABI-mangled representation
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
436 LLValue* get(Type* dty, DValue* v)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
437 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
438 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
439 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
440 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
441 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
442 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
443 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
444 lval = DtoAlloca(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
445 DtoStore(rval, lval);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
448 const LLType* pTy = getPtrToType(DtoType(dty));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
449 return DtoLoad(DtoBitCast(lval, pTy), "get-result");
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
452 // 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
453 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
454 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
455 const LLType* pTy = getPtrToType(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
456 DtoStore(rval, DtoBitCast(lval, pTy));
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
459 // 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
460 LLValue* put(Type* dty, DValue* v)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
461 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
462 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
463 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
464 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
465 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
466 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
467 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
468 lval = DtoAlloca(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
469 DtoStore(rval, lval);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
472 LLType* abiTy = getAbiType(dty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
473 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
474
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
475 const LLType* pTy = getPtrToType(abiTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
476 return DtoLoad(DtoBitCast(lval, pTy), "put-result");
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
479 /// 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
480 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
481 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
482 return getAbiType(dty);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
487 struct RegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
488 unsigned char int_regs, sse_regs;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
492 struct X86_64TargetABI : TargetABI {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
493 X86_64_C_struct_rewrite struct_rewrite;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
494
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
495 void newFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
496 funcTypeStack.push_back(FuncTypeData(tf->linkage));
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
499 bool returnInArg(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
500
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
501 bool passByVal(Type* t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
502
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
503 void rewriteFunctionType(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
504
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
505 void doneWithFunctionType() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
506 funcTypeStack.pop_back();
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
509 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
510 struct FuncTypeData {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
511 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
512 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
513
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
514 FuncTypeData(LINK linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
515 : linkage(linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
516 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
517 state.int_regs = 6;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
518 state.sse_regs = 8;
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 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
521 std::vector<FuncTypeData> funcTypeStack;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
522
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
523 LINK linkage() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
524 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
525 return funcTypeStack.back().linkage;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
528 RegCount& state() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
529 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
530 return funcTypeStack.back().state;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
531 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
532
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
533 void fixup(IrFuncTyArg& arg);
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
537 // The public getter for abi.cpp
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
538 TargetABI* getX86_64TargetABI() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
539 return new X86_64TargetABI;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
543 bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
544 assert(linkage() == tf->linkage);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
545 Type* rt = tf->next->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
546
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
547 if (tf->linkage == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
548 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
549
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
550 // 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
551 if (rt->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
552 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
553
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
554 // 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
555 // 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
556 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
557 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
558 if (rt == Type::tvoid || keepUnchanged(rt))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
559 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
560
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
561 Classification cl = classify(rt);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
562 return cl.isMemory;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
566 bool X86_64TargetABI::passByVal(Type* t) {
1049
afe271b0e271 Two small bugfixes:
Frits van Bommel <fvbommel wxs.nl>
parents: 1048
diff changeset
567 t = t->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
568 if (linkage() == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
569 if (t->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
570 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
571
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
572 // 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
573 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
574 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
575 // 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
576 // 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
577 Classification cl = classify(t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
578 if (cl.isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
579 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
580
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
581 // 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
582 RegCount wanted = { 0, 0 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
583 for (int i = 0 ; i < 2; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
584 if (cl.classes[i] == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
585 wanted.int_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
586 else if (cl.classes[i] == Sse)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
587 wanted.sse_regs++;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
590 // See if they're available:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
591 RegCount& state = this->state();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
592 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
593 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
594 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
595 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
596 if (keepUnchanged(t)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
597 // 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
598 // 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
599 // automatically spilling the rest to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
600 if (wanted.int_regs > state.int_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
601 state.int_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
602 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
603 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
604
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
605 if (wanted.sse_regs > state.sse_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
606 state.sse_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
607 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
608 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
609 } else if (t->iscomplex() || t->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
610 // 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
611 // available.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
612
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
613 // 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
614 // (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
615 // 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
616 // more easily break it up?
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
617 // 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
618 // 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
619 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
620 } else {
1048
f9333daa1bf5 Fix a typo
Frits van Bommel <fvbommel wxs.nl>
parents: 1047
diff changeset
621 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
622 && "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
623 // 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
624 assert(!isaStruct(DtoType(t)));
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
627 // 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
628 return false;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
632 // Helper function for rewriteFunctionType.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
633 // 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
634 // to get the rewrite applied (if necessary).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
635 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
636 LLType* abiTy = getAbiType(arg.type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
637
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
638 if (abiTy && abiTy != arg.ltype) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
639 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
640 arg.ltype = abiTy;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
641 arg.rewrite = &struct_rewrite;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
645 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
646 // 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
647
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
648 if (tf->linkage != LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
649 // 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
650
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
651 IrFuncTy& fty = tf->fty;
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
652
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
653 if (!fty.arg_sret) {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
654 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
655 Type* rt = fty.ret->type->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
656 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
657 fixup(*fty.ret);
1047
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
661 Logger::println("x86-64 ABI: Transforming arguments");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
662 LOG_SCOPE;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
663
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
664 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
665 IrFuncTyArg& arg = **I;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
666
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
667 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
668 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
669
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
670 // 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
671 if (arg.byref)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
672 continue;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
673
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
674 Type* ty = arg.type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
675
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
676 fixup(arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
677
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
678 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
679 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
680 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
681 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
682 }