Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: src/IceTargetLoweringX8664.cpp

Issue 1257643004: Subzero. Buildable, non-functional TargetLoweringX8664. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceTargetLoweringX8664.cpp - lowering for x86-64 -------===// 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 /// 9 ///
10 /// \file 10 /// \file
11 /// Implements the Target Lowering for x86-64. 11 /// This file implements the TargetLoweringX8664 class, which
12 /// consists almost entirely of the lowering sequence for each
13 /// high-level instruction.
12 /// 14 ///
13 //===----------------------------------------------------------------------===// 15 //===----------------------------------------------------------------------===//
14 16
15 #include "IceDefs.h"
16 #include "IceTargetLoweringX8664.h" 17 #include "IceTargetLoweringX8664.h"
17 18
19 #include "IceTargetLoweringX8664Traits.h"
20 #include "IceTargetLoweringX86Base.h"
21
18 namespace Ice { 22 namespace Ice {
19 23
20 TargetX8664 *TargetX8664::create(Cfg *) { 24 namespace X86Internal {
21 llvm::report_fatal_error("Not yet implemented"); 25 const MachineTraits<TargetX8664>::TableFcmpType
26 MachineTraits<TargetX8664>::TableFcmp[] = {
27 #define X(val, dflt, swapS, C1, C2, swapV, pred) \
28 { \
29 dflt, swapS, X8664::Traits::Cond::C1, X8664::Traits::Cond::C2, swapV, \
30 X8664::Traits::Cond::pred \
31 } \
32 ,
33 FCMPX8664_TABLE
34 #undef X
35 };
36
37 const size_t MachineTraits<TargetX8664>::TableFcmpSize =
38 llvm::array_lengthof(TableFcmp);
39
40 const MachineTraits<TargetX8664>::TableIcmp32Type
41 MachineTraits<TargetX8664>::TableIcmp32[] = {
42 #define X(val, C_32, C1_64, C2_64, C3_64) \
43 { X8664::Traits::Cond::C_32 } \
44 ,
45 ICMPX8664_TABLE
46 #undef X
47 };
48
49 const size_t MachineTraits<TargetX8664>::TableIcmp32Size =
50 llvm::array_lengthof(TableIcmp32);
51
52 const MachineTraits<TargetX8664>::TableIcmp64Type
53 MachineTraits<TargetX8664>::TableIcmp64[] = {
54 #define X(val, C_32, C1_64, C2_64, C3_64) \
55 { \
56 X8664::Traits::Cond::C1_64, X8664::Traits::Cond::C2_64, \
57 X8664::Traits::Cond::C3_64 \
58 } \
59 ,
60 ICMPX8664_TABLE
61 #undef X
62 };
63
64 const size_t MachineTraits<TargetX8664>::TableIcmp64Size =
65 llvm::array_lengthof(TableIcmp64);
66
67 const MachineTraits<TargetX8664>::TableTypeX8664AttributesType
68 MachineTraits<TargetX8664>::TableTypeX8664Attributes[] = {
69 #define X(tag, elementty, cvt, sdss, pack, width, fld) \
70 { elementty } \
71 ,
72 ICETYPEX8664_TABLE
73 #undef X
74 };
75
76 const size_t MachineTraits<TargetX8664>::TableTypeX8664AttributesSize =
77 llvm::array_lengthof(TableTypeX8664Attributes);
78
79 const uint32_t MachineTraits<TargetX8664>::X86_STACK_ALIGNMENT_BYTES = 16;
80 const char *MachineTraits<TargetX8664>::TargetName = "X8664";
81
82 } // end of namespace X86Internal
83
84 namespace {
85 template <typename T> struct PoolTypeConverter {};
86
87 template <> struct PoolTypeConverter<float> {
88 typedef uint32_t PrimitiveIntType;
89 typedef ConstantFloat IceType;
90 static const Type Ty = IceType_f32;
91 static const char *TypeName;
92 static const char *AsmTag;
93 static const char *PrintfString;
94 };
95 const char *PoolTypeConverter<float>::TypeName = "float";
96 const char *PoolTypeConverter<float>::AsmTag = ".long";
97 const char *PoolTypeConverter<float>::PrintfString = "0x%x";
98
99 template <> struct PoolTypeConverter<double> {
100 typedef uint64_t PrimitiveIntType;
101 typedef ConstantDouble IceType;
102 static const Type Ty = IceType_f64;
103 static const char *TypeName;
104 static const char *AsmTag;
105 static const char *PrintfString;
106 };
107 const char *PoolTypeConverter<double>::TypeName = "double";
108 const char *PoolTypeConverter<double>::AsmTag = ".quad";
109 const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
110
111 // Add converter for int type constant pooling
112 template <> struct PoolTypeConverter<uint32_t> {
113 typedef uint32_t PrimitiveIntType;
114 typedef ConstantInteger32 IceType;
115 static const Type Ty = IceType_i32;
116 static const char *TypeName;
117 static const char *AsmTag;
118 static const char *PrintfString;
119 };
120 const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
121 const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
122 const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
123
124 // Add converter for int type constant pooling
125 template <> struct PoolTypeConverter<uint16_t> {
126 typedef uint32_t PrimitiveIntType;
127 typedef ConstantInteger32 IceType;
128 static const Type Ty = IceType_i16;
129 static const char *TypeName;
130 static const char *AsmTag;
131 static const char *PrintfString;
132 };
133 const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
134 const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
135 const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
136
137 // Add converter for int type constant pooling
138 template <> struct PoolTypeConverter<uint8_t> {
139 typedef uint32_t PrimitiveIntType;
140 typedef ConstantInteger32 IceType;
141 static const Type Ty = IceType_i8;
142 static const char *TypeName;
143 static const char *AsmTag;
144 static const char *PrintfString;
145 };
146 const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
147 const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
148 const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
149 } // end of anonymous namespace
150
151 template <typename T>
152 void TargetDataX8664::emitConstantPool(GlobalContext *Ctx) {
153 if (!BuildDefs::dump())
154 return;
155 Ostream &Str = Ctx->getStrEmit();
156 Type Ty = T::Ty;
157 SizeT Align = typeAlignInBytes(Ty);
158 ConstantList Pool = Ctx->getConstantPool(Ty);
159
160 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
161 << "\n";
162 Str << "\t.align\t" << Align << "\n";
163
164 // If reorder-pooled-constants option is set to true, we need to shuffle the
165 // constant pool before emitting it.
166 if (Ctx->getFlags().shouldReorderPooledConstants())
167 RandomShuffle(Pool.begin(), Pool.end(), [Ctx](uint64_t N) {
168 return (uint32_t)Ctx->getRNG().next(N);
169 });
170
171 for (Constant *C : Pool) {
172 if (!C->getShouldBePooled())
173 continue;
174 typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
175 typename T::IceType::PrimType Value = Const->getValue();
176 // Use memcpy() to copy bits from Value into RawValue in a way
177 // that avoids breaking strict-aliasing rules.
178 typename T::PrimitiveIntType RawValue;
179 memcpy(&RawValue, &Value, sizeof(Value));
180 char buf[30];
181 int CharsPrinted =
182 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
183 assert(CharsPrinted >= 0 &&
184 (size_t)CharsPrinted < llvm::array_lengthof(buf));
185 (void)CharsPrinted; // avoid warnings if asserts are disabled
186 Const->emitPoolLabel(Str);
187 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
188 << Value << "\n";
189 }
22 } 190 }
23 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &, 191
24 const IceString &) { 192 void TargetDataX8664::lowerConstants() {
25 llvm::report_fatal_error("Not yet implemented"); 193 if (Ctx->getFlags().getDisableTranslation())
194 return;
195 // No need to emit constants from the int pool since (for x86) they
196 // are embedded as immediates in the instructions, just emit float/double.
197 switch (Ctx->getFlags().getOutFileType()) {
198 case FT_Elf: {
199 ELFObjectWriter *Writer = Ctx->getObjectWriter();
200
201 Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
202 Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
203 Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
204
205 Writer->writeConstantPool<ConstantFloat>(IceType_f32);
206 Writer->writeConstantPool<ConstantDouble>(IceType_f64);
207 } break;
208 case FT_Asm:
209 case FT_Iasm: {
210 OstreamLocker L(Ctx);
211
212 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
213 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
214 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
215
216 emitConstantPool<PoolTypeConverter<float>>(Ctx);
217 emitConstantPool<PoolTypeConverter<double>>(Ctx);
218 } break;
219 }
26 } 220 }
27 221
28 void TargetDataX8664::lowerConstants() { 222 void TargetDataX8664::lowerGlobals(const VariableDeclarationList &Vars,
29 llvm::report_fatal_error("Not yet implemented"); 223 const IceString &SectionSuffix) {
224 switch (Ctx->getFlags().getOutFileType()) {
225 case FT_Elf: {
226 ELFObjectWriter *Writer = Ctx->getObjectWriter();
227 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix);
228 } break;
229 case FT_Asm:
230 case FT_Iasm: {
231 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
232 OstreamLocker L(Ctx);
233 for (const VariableDeclaration *Var : Vars) {
234 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
235 emitGlobal(*Var, SectionSuffix);
236 }
237 }
238 } break;
239 }
30 } 240 }
31 241
242 // In some cases, there are x-macros tables for both high-level and
243 // low-level instructions/operands that use the same enum key value.
244 // The tables are kept separate to maintain a proper separation
245 // between abstraction layers. There is a risk that the tables could
246 // get out of sync if enum values are reordered or if entries are
247 // added or deleted. The following dummy namespaces use
248 // static_asserts to ensure everything is kept in sync.
249
250 namespace {
251 // Validate the enum values in FCMPX8664_TABLE.
252 namespace dummy1 {
253 // Define a temporary set of enum values based on low-level table
254 // entries.
255 enum _tmp_enum {
256 #define X(val, dflt, swapS, C1, C2, swapV, pred) _tmp_##val,
257 FCMPX8664_TABLE
258 #undef X
259 _num
260 };
261 // Define a set of constants based on high-level table entries.
262 #define X(tag, str) static const int _table1_##tag = InstFcmp::tag;
263 ICEINSTFCMP_TABLE
264 #undef X
265 // Define a set of constants based on low-level table entries, and
266 // ensure the table entry keys are consistent.
267 #define X(val, dflt, swapS, C1, C2, swapV, pred) \
268 static const int _table2_##val = _tmp_##val; \
269 static_assert( \
270 _table1_##val == _table2_##val, \
271 "Inconsistency between FCMPX8664_TABLE and ICEINSTFCMP_TABLE");
272 FCMPX8664_TABLE
273 #undef X
274 // Repeat the static asserts with respect to the high-level table
275 // entries in case the high-level table has extra entries.
276 #define X(tag, str) \
277 static_assert( \
278 _table1_##tag == _table2_##tag, \
279 "Inconsistency between FCMPX8664_TABLE and ICEINSTFCMP_TABLE");
280 ICEINSTFCMP_TABLE
281 #undef X
282 } // end of namespace dummy1
283
284 // Validate the enum values in ICMPX8664_TABLE.
285 namespace dummy2 {
286 // Define a temporary set of enum values based on low-level table
287 // entries.
288 enum _tmp_enum {
289 #define X(val, C_32, C1_64, C2_64, C3_64) _tmp_##val,
290 ICMPX8664_TABLE
291 #undef X
292 _num
293 };
294 // Define a set of constants based on high-level table entries.
295 #define X(tag, str) static const int _table1_##tag = InstIcmp::tag;
296 ICEINSTICMP_TABLE
297 #undef X
298 // Define a set of constants based on low-level table entries, and
299 // ensure the table entry keys are consistent.
300 #define X(val, C_32, C1_64, C2_64, C3_64) \
301 static const int _table2_##val = _tmp_##val; \
302 static_assert( \
303 _table1_##val == _table2_##val, \
304 "Inconsistency between ICMPX8664_TABLE and ICEINSTICMP_TABLE");
305 ICMPX8664_TABLE
306 #undef X
307 // Repeat the static asserts with respect to the high-level table
308 // entries in case the high-level table has extra entries.
309 #define X(tag, str) \
310 static_assert( \
311 _table1_##tag == _table2_##tag, \
312 "Inconsistency between ICMPX8664_TABLE and ICEINSTICMP_TABLE");
313 ICEINSTICMP_TABLE
314 #undef X
315 } // end of namespace dummy2
316
317 // Validate the enum values in ICETYPEX8664_TABLE.
318 namespace dummy3 {
319 // Define a temporary set of enum values based on low-level table
320 // entries.
321 enum _tmp_enum {
322 #define X(tag, elementty, cvt, sdss, pack, width, fld) _tmp_##tag,
323 ICETYPEX8664_TABLE
324 #undef X
325 _num
326 };
327 // Define a set of constants based on high-level table entries.
328 #define X(tag, sizeLog2, align, elts, elty, str) \
329 static const int _table1_##tag = tag;
330 ICETYPE_TABLE
331 #undef X
332 // Define a set of constants based on low-level table entries, and
333 // ensure the table entry keys are consistent.
334 #define X(tag, elementty, cvt, sdss, pack, width, fld) \
335 static const int _table2_##tag = _tmp_##tag; \
336 static_assert(_table1_##tag == _table2_##tag, \
337 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
338 ICETYPEX8664_TABLE
339 #undef X
340 // Repeat the static asserts with respect to the high-level table
341 // entries in case the high-level table has extra entries.
342 #define X(tag, sizeLog2, align, elts, elty, str) \
343 static_assert(_table1_##tag == _table2_##tag, \
344 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE");
345 ICETYPE_TABLE
346 #undef X
347 } // end of namespace dummy3
348 } // end of anonymous namespace
349
32 } // end of namespace Ice 350 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698