annotate gen/abi-x86-64.cpp @ 1350:15e9762bb620

Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
author Tomas Lindquist Olsen <tomas.l.olsen gmail com>
date Thu, 14 May 2009 13:26:40 +0200
parents f3b92d26ad0f
children 45aca7e7cc88
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"
1348
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
46 //#include "gen/llvm-version.h" // only use is commented out.
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
47 #include "ir/irfunction.h"
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
48
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
49 #include <cassert>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
50 #include <map>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
51 #include <string>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
52 #include <utility>
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
53
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
54 // Implementation details for extern(C)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
55 namespace {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
56 /**
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
57 * This function helps filter out things that look like structs to C,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
58 * but should be passed to C in separate arguments anyway.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
59 *
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
60 * (e.g. dynamic arrays are passed as separate length and ptr. This
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
61 * is both less work and makes printf("%.*s", o.toString()) work)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
62 */
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
63 inline bool keepUnchanged(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
64 switch (t->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
65 case Tarray: // dynamic array
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
66 case Taarray: // assoc array
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
67 case Tdelegate:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
68 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
69
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
70 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
71 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
72 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
73 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
74
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
75 enum ArgClass {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
76 Integer, Sse, SseUp, X87, X87Up, ComplexX87, NoClass, Memory
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
77 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
78
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
79 struct Classification {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
80 bool isMemory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
81 ArgClass classes[2];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
82
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
83 Classification() : isMemory(false) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
84 classes[0] = NoClass;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
85 classes[1] = NoClass;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
86 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
87
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
88 void addField(unsigned offset, ArgClass cl) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
89 if (isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
90 return;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
91
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
92 // Note that we don't need to bother checking if it crosses 8 bytes.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
93 // We don't get here with unaligned fields, and anything that can be
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
94 // big enough to cross 8 bytes (cdoubles, reals, structs and arrays)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
95 // is special-cased in classifyType()
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
96 int idx = (offset < 8 ? 0 : 1);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
97
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
98 ArgClass nw = merge(classes[idx], cl);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
99 if (nw != classes[idx]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
100 classes[idx] = nw;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
101
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
102 if (nw == Memory) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
103 classes[1-idx] = Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
104 isMemory = true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
105 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
106 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
107 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
108
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
109 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
110 ArgClass merge(ArgClass accum, ArgClass cl) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
111 if (accum == cl)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
112 return accum;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
113 if (accum == NoClass)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
114 return cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
115 if (cl == NoClass)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
116 return accum;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
117 if (accum == Memory || cl == Memory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
118 return Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
119 if (accum == Integer || cl == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
120 return Integer;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
121 if (accum == X87 || accum == X87Up || accum == ComplexX87 ||
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
122 cl == X87 || cl == X87Up || cl == ComplexX87)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
123 return Memory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
124 return Sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
125 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
126 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
127
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
128 void classifyType(Classification& accum, Type* ty, d_uns64 offset) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
129 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
130 Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
131
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
132 ty = ty->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
133
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
134 if (ty->isintegral() || ty->ty == Tpointer) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
135 accum.addField(offset, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
136 } else if (ty->ty == Tfloat80 || ty->ty == Timaginary80) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
137 accum.addField(offset, X87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
138 accum.addField(offset+8, X87Up);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
139 } else if (ty->ty == Tcomplex80) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
140 accum.addField(offset, ComplexX87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
141 // make sure other half knows about it too:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
142 accum.addField(offset+16, ComplexX87);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
143 } else if (ty->ty == Tcomplex64) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
144 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
145 accum.addField(offset+8, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
146 } else if (ty->ty == Tcomplex32) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
147 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
148 accum.addField(offset+4, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
149 } else if (ty->isfloating()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
150 accum.addField(offset, Sse);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
151 } else if (ty->size() > 16 || hasUnalignedFields(ty)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
152 // This isn't creal, yet is > 16 bytes, so pass in memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
153 // Must be after creal case but before arrays and structs,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
154 // the other types that can get bigger than 16 bytes
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
155 accum.addField(offset, Memory);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
156 } else if (ty->ty == Tsarray) {
1054
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
157 Type* eltType = ty->nextOf();
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
158 d_uns64 eltsize = eltType->size();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
159 if (eltsize > 0) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
160 d_uns64 dim = ty->size() / eltsize;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
161 assert(dim <= 16
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
162 && "Array of non-empty type <= 16 bytes but > 16 elements?");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
163 for (d_uns64 i = 0; i < dim; i++) {
1054
a3d7288c4473 Future-proof the code to classify static array members of structs.
Frits van Bommel <fvbommel wxs.nl>
parents: 1051
diff changeset
164 classifyType(accum, eltType, offset);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
165 offset += eltsize;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
166 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
167 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
168 } else if (ty->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
169 Array* fields = &((TypeStruct*) ty)->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
170 for (size_t i = 0; i < fields->dim; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
171 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
172 classifyType(accum, field->type, offset + field->offset);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
173 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
174 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
175 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
176 Logger::cout() << "x86-64 ABI: Implicitly handled type: "
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
177 << ty->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
178 // arrays, delegates, etc. (pointer-sized fields, <= 16 bytes)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
179 assert(offset == 0 || offset == 8
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
180 && "must be aligned and doesn't fit otherwise");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
181 assert(ty->size() % 8 == 0 && "Not a multiple of pointer size?");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
182
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
183 accum.addField(offset, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
184 if (ty->size() > 8)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
185 accum.addField(offset+8, Integer);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
186 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
187 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
188
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
189 Classification classify(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
190 typedef std::map<Type*, Classification> ClassMap;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
191 static ClassMap cache;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
192
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
193 ClassMap::iterator it = cache.find(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
194 if (it != cache.end()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
195 return it->second;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
196 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
197 Classification cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
198 classifyType(cl, ty, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
199 cache[ty] = cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
200 return cl;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
201 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
202 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
203
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
204 /// Returns the type to pass as, or null if no transformation is needed.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
205 LLType* getAbiType(Type* ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
206 ty = ty->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
207
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
208 // First, check if there's any need of a transformation:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
209
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
210 if (keepUnchanged(ty))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
211 return 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
212
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
213 if (ty->ty != Tcomplex32 && ty->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
214 return 0; // Nothing to do,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
215
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
216 Classification cl = classify(ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
217 assert(!cl.isMemory);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
218
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
219 if (cl.classes[0] == NoClass) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
220 assert(cl.classes[1] == NoClass && "Non-empty struct with empty first half?");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
221 return 0; // Empty structs should also be handled correctly by LLVM
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
222 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
223
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
224 // Okay, we may need to transform. Figure out a canonical type:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
225
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
226 std::vector<const LLType*> parts;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
227
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
228 unsigned size = ty->size();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
229
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
230 switch (cl.classes[0]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
231 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
232 unsigned bits = (size >= 8 ? 64 : (size * 8));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
233 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
234 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
235 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
236
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
237 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
238 parts.push_back(size <= 4 ? LLType::FloatTy : LLType::DoubleTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
239 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
240
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
241 case X87:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
242 assert(cl.classes[1] == X87Up && "Upper half of real not X87Up?");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
243 /// The type only contains a single real/ireal field,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
244 /// so just use that type.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
245 return const_cast<LLType*>(LLType::X86_FP80Ty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
246
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
247 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
248 assert(0 && "Unanticipated argument class");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
249 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
250
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
251 switch(cl.classes[1]) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
252 case NoClass:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
253 assert(parts.size() == 1);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
254 // No need to use a single-element struct type.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
255 // Just use the element type instead.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
256 return const_cast<LLType*>(parts[0]);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
257 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
258
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
259 case Integer: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
260 assert(size > 8);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
261 unsigned bits = (size - 8) * 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
262 parts.push_back(LLIntegerType::get(bits));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
263 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
264 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
265 case Sse:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
266 parts.push_back(size <= 12 ? LLType::FloatTy : LLType::DoubleTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
267 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
268
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
269 case X87Up:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
270 if(cl.classes[0] == X87) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
271 // This won't happen: it was short-circuited while
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
272 // processing the first half.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
273 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
274 // I can't find this anywhere in the ABI documentation,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
275 // but this is what gcc does (both regular and llvm-gcc).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
276 // (This triggers for types like union { real r; byte b; })
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
277 parts.push_back(LLType::DoubleTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
278 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
279 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
280
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
281 default:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
282 assert(0 && "Unanticipated argument class for second half");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
283 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
284 return LLStructType::get(parts);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
285 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
286 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
287
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
288
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
289 // Implementation details for extern(D)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
290 namespace x86_64_D_cc {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
291 struct DRegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
292 unsigned ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
293 unsigned sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
294 unsigned x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
295
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
296 DRegCount(unsigned ints_, unsigned sse_, unsigned x87_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
297 : ints(ints_), sse(sse_), x87(x87_) {}
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
298 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
299
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
300 // Count the number of registers needed for a simple type.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
301 // (Not a struct or static array)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
302 DRegCount regsNeededForSimpleType(Type* t) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
303 DRegCount r(0, 0, 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
304 switch(t->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
305 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
306 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
307 assert(0 && "Not a simple type!");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
308 // Return huge numbers if assertions are disabled, so it'll always get
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
309 // bumped to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
310 r.ints = r.sse = r.x87 = (unsigned)-1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
311 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
312
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
313 // Floats, doubles and such are passed in SSE registers
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
314 case Tfloat32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
315 case Tfloat64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
316 case Timaginary32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
317 case Timaginary64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
318 r.sse = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
319 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
320
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
321 case Tcomplex32:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
322 case Tcomplex64:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
323 r.sse = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
324 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
325
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
326 // Reals, ireals and creals are passed in x87 registers
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
327 case Tfloat80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
328 case Timaginary80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
329 r.x87 = 1;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
330 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
331
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
332 case Tcomplex80:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
333 r.x87 = 2;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
334 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
335
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
336 // Anything else is passed in one or two integer registers,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
337 // depending on its size.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
338 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
339 int needed = (t->size() + 7) / 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
340 assert(needed <= 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
341 r.ints = needed;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
342 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
343 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
344 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
345 return r;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
346 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
347
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
348 // Returns true if it's possible (and a good idea) to pass the struct in the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
349 // specified number of registers.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
350 // (May return false if it's a bad idea to pass the type in registers for
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
351 // reasons other than it not fitting)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
352 // Note that if true is returned, 'left' is also modified to contain the
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
353 // number of registers left. This property is used in the recursive case.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
354 // If false is returned, 'left' is garbage.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
355 bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
356 // If it has unaligned fields, there's probably a reason for it,
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
357 // so keep it in memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
358 if (hasUnalignedFields(t))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
359 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
360
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
361 Array* fields = &t->sym->fields;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
362 d_uns64 nextbyte = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
363 for (d_uns64 i = 0; i < fields->dim; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
364 VarDeclaration* field = (VarDeclaration*) fields->data[i];
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
365
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
366 // This depends on ascending order of field offsets in structs
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
367 // without overlapping fields.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
368 if (field->offset < nextbyte) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
369 // Don't return unions (or structs containing them) in registers.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
370 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
371 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
372 nextbyte = field->offset + field->type->size();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
373
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
374 switch (field->type->ty) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
375 case Tstruct:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
376 if (!shouldPassStructInRegs((TypeStruct*) field->type, left))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
377 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
378 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
379
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
380 case Tsarray:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
381 // Don't return static arrays in registers
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
382 // (indexing registers doesn't work well)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
383 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
384
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
385 default: {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
386 DRegCount needed = regsNeededForSimpleType(field->type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
387 if (needed.ints > left.ints || needed.sse > left.sse || needed.x87 > left.x87)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
388 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
389 left.ints -= needed.ints;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
390 left.sse -= needed.sse;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
391 left.x87 -= needed.x87;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
392 break;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
393 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
394 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
395 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
396 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
397 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
398
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
399 // Returns true if the struct fits in return registers in the x86-64 fastcc
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
400 // calling convention.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
401 bool retStructInRegs(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
402 // 'fastcc' allows returns in up to two registers of each kind:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
403 DRegCount state(2, 2, 2);
1348
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
404 #if 1 //LLVM_REV < 67588
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
405 // (If uncommenting the LLVM_REV line above, also uncomment llvm-version #include
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
406
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
407 // LLVM before trunk r67588 doesn't allow a second int to be an i1 or
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
408 // i8. (See <http://llvm.org/PR3861>)
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
409 // Rather than complicating shouldPassStructInRegs(), just disallow
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
410 // second integers for now.
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
411 // FIXME: Disabling this for older LLVM only makes the abi dependent on
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
412 // LLVM revision, which seems like a bad idea. We could extend
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
413 // i8 parts to i16 to work around this issue until 2.6...
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
414 // TODO: Remove this workaround when support for LLVM 2.5 is dropped.
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
415 state.ints = 1;
f3b92d26ad0f Revert [1346] for now, it breaks because of padding :(
Frits van Bommel <fvbommel wxs.nl>
parents: 1346
diff changeset
416 #endif
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
417 return shouldPassStructInRegs(st, state);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
418 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
419
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
420 // 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
421 // bump it to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
422 bool passStructTypeDirectly(TypeStruct* st) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
423 // 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
424 // pass it directly.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
425 // 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
426 // 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
427 // parameters.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
428 DRegCount state(2, 2, 2);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
429 return shouldPassStructInRegs(st, state);
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 // 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
432 // 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
433 /*
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
434 // 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
435 // 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
436 RegCount state(5, 8, 0);
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 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
439 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
440
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
441 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
442 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
443 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
444 ////////////////////////////////////////////////////////////////////////////////
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
445
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
446
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
447 /// 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
448 struct X86_64_C_struct_rewrite : ABIRewrite {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
449 // Get struct from ABI-mangled representation
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
450 LLValue* get(Type* dty, DValue* v)
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 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
453 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
454 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
455 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
456 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
457 LLValue* rval = v->getRVal();
1350
15e9762bb620 Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents: 1348
diff changeset
458 lval = DtoRawAlloca(rval->getType(), 0);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
459 DtoStore(rval, lval);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
460 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
461
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
462 const LLType* pTy = getPtrToType(DtoType(dty));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
463 return DtoLoad(DtoBitCast(lval, pTy), "get-result");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
464 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
465
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
466 // 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
467 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
468 LLValue* rval = v->getRVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
469 const LLType* pTy = getPtrToType(rval->getType());
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
470 DtoStore(rval, DtoBitCast(lval, pTy));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
471 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
472
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
473 // 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
474 LLValue* put(Type* dty, DValue* v)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
475 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
476 LLValue* lval;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
477 if (v->isLVal()) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
478 lval = v->getLVal();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
479 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
480 // No memory location, create one.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
481 LLValue* rval = v->getRVal();
1350
15e9762bb620 Adds explicit alignment information for alloca instructions in general, there's a few cases that still needs to be looked at but this should catch the majority. Fixes ticket #293 .
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents: 1348
diff changeset
482 lval = DtoRawAlloca(rval->getType(), 0);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
483 DtoStore(rval, lval);
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 LLType* abiTy = getAbiType(dty);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
487 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
488
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
489 const LLType* pTy = getPtrToType(abiTy);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
490 return DtoLoad(DtoBitCast(lval, pTy), "put-result");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
491 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
492
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
493 /// 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
494 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
495 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
496 return getAbiType(dty);
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
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 struct RegCount {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
502 unsigned char int_regs, sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
503 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
504
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
505
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
506 struct X86_64TargetABI : TargetABI {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
507 X86_64_C_struct_rewrite struct_rewrite;
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 void newFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
510 funcTypeStack.push_back(FuncTypeData(tf->linkage));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
511 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
512
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
513 bool returnInArg(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
514
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
515 bool passByVal(Type* t);
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 void rewriteFunctionType(TypeFunction* tf);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
518
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
519 void doneWithFunctionType() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
520 funcTypeStack.pop_back();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
521 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
522
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
523 private:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
524 struct FuncTypeData {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
525 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
526 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
527
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
528 FuncTypeData(LINK linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
529 : linkage(linkage_)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
530 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
531 state.int_regs = 6;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
532 state.sse_regs = 8;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
533 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
534 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
535 std::vector<FuncTypeData> funcTypeStack;
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 LINK linkage() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
538 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
539 return funcTypeStack.back().linkage;
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 RegCount& state() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
543 assert(funcTypeStack.size() != 0);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
544 return funcTypeStack.back().state;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
545 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
546
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
547 void fixup(IrFuncTyArg& arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
548 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
549
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
550
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
551 // The public getter for abi.cpp
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
552 TargetABI* getX86_64TargetABI() {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
553 return new X86_64TargetABI;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
554 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
555
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
556
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
557 bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
558 assert(linkage() == tf->linkage);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
559 Type* rt = tf->next->toBasetype();
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 if (tf->linkage == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
562 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
563
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
564 // 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
565 if (rt->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
566 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
567
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
568 // 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
569 // 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
570 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
571 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
572 if (rt == Type::tvoid || keepUnchanged(rt))
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
573 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
574
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
575 Classification cl = classify(rt);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
576 return cl.isMemory;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
577 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
578 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
579
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
580 bool X86_64TargetABI::passByVal(Type* t) {
1049
afe271b0e271 Two small bugfixes:
Frits van Bommel <fvbommel wxs.nl>
parents: 1048
diff changeset
581 t = t->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
582 if (linkage() == LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
583 if (t->ty != Tstruct)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
584 return false;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
585
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
586 // 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
587 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
588 } else {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
589 // 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
590 // 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
591 Classification cl = classify(t);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
592 if (cl.isMemory)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
593 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
594
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
595 // 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
596 RegCount wanted = { 0, 0 };
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
597 for (int i = 0 ; i < 2; i++) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
598 if (cl.classes[i] == Integer)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
599 wanted.int_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
600 else if (cl.classes[i] == Sse)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
601 wanted.sse_regs++;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
602 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
603
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
604 // See if they're available:
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
605 RegCount& state = this->state();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
606 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
607 state.int_regs -= wanted.int_regs;
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 {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
610 if (keepUnchanged(t)) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
611 // 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
612 // 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
613 // automatically spilling the rest to memory.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
614 if (wanted.int_regs > state.int_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
615 state.int_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
616 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
617 state.int_regs -= wanted.int_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
618
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
619 if (wanted.sse_regs > state.sse_regs)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
620 state.sse_regs = 0;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
621 else
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
622 state.sse_regs -= wanted.sse_regs;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
623 } else if (t->iscomplex() || t->ty == Tstruct) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
624 // 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
625 // available.
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 // 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
628 // (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
629 // 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
630 // more easily break it up?
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
631 // 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
632 // 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
633 return true;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
634 } else {
1048
f9333daa1bf5 Fix a typo
Frits van Bommel <fvbommel wxs.nl>
parents: 1047
diff changeset
635 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
636 && "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
637 // 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
638 assert(!isaStruct(DtoType(t)));
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
639 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
640 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
641 // 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
642 return false;
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
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
646 // Helper function for rewriteFunctionType.
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
647 // 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
648 // to get the rewrite applied (if necessary).
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
649 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
650 LLType* abiTy = getAbiType(arg.type);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
651
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
652 if (abiTy && abiTy != arg.ltype) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
653 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
654 arg.ltype = abiTy;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
655 arg.rewrite = &struct_rewrite;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
656 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
657 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
658
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
659 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
660 // 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
661
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
662 if (tf->linkage != LINKd) {
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
663 // 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
664
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
665 IrFuncTy& fty = tf->fty;
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
666
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
667 if (!fty.arg_sret) {
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
668 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
669 Type* rt = fty.ret->type->toBasetype();
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
670 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
671 fixup(*fty.ret);
1047
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
672 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
673
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
674
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
675 Logger::println("x86-64 ABI: Transforming arguments");
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
676 LOG_SCOPE;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
677
1051
dc608dc33081 Make IrFuncTy a member of TypeFunction. Reset between modules compiled in the
Christian Kamm <kamm incasoftware de>
parents: 1049
diff changeset
678 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
679 IrFuncTyArg& arg = **I;
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 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
682 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
683
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
684 // 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
685 if (arg.byref)
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
686 continue;
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
687
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
688 Type* ty = arg.type->toBasetype();
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
689
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
690 fixup(arg);
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
691
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
692 if (Logger::enabled())
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
693 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
694 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
695 }
6bb04dbee21f Some calling convention work for x86-64:
Frits van Bommel <fvbommel wxs.nl>
parents:
diff changeset
696 }