blob: 7024d1447f21ea33c203c281b6e1cf23072b2f77 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===//
2//
3// The Subzero Code Generator
4//
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07005//===----------------------------------------------------------------------===//
6//
7// This file implements the TargetLoweringX8632 class, which
8// consists almost entirely of the lowering sequence for each
Jim Stichnoth70d0a052014-11-14 15:53:46 -08009// high-level instruction.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070010//
11//===----------------------------------------------------------------------===//
12
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070013#include "IceTargetLoweringX8632.h"
John Porto7e93c622015-06-23 10:58:57 -070014
15#include "IceTargetLoweringX86Base.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070016
17namespace Ice {
John Porto7e93c622015-06-23 10:58:57 -070018namespace X86Internal {
19template <> struct MachineTraits<TargetX8632> {
20 using InstructionSet = TargetX8632::X86InstructionSet;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070021
John Porto7e93c622015-06-23 10:58:57 -070022 // The following table summarizes the logic for lowering the fcmp
23 // instruction. There is one table entry for each of the 16 conditions.
24 //
25 // The first four columns describe the case when the operands are
26 // floating point scalar values. A comment in lowerFcmp() describes the
27 // lowering template. In the most general case, there is a compare
28 // followed by two conditional branches, because some fcmp conditions
29 // don't map to a single x86 conditional branch. However, in many cases
30 // it is possible to swap the operands in the comparison and have a
31 // single conditional branch. Since it's quite tedious to validate the
32 // table by hand, good execution tests are helpful.
33 //
34 // The last two columns describe the case when the operands are vectors
35 // of floating point values. For most fcmp conditions, there is a clear
36 // mapping to a single x86 cmpps instruction variant. Some fcmp
37 // conditions require special code to handle and these are marked in the
38 // table with a Cmpps_Invalid predicate.
39 static const struct TableFcmpType {
40 uint32_t Default;
41 bool SwapScalarOperands;
42 CondX86::BrCond C1, C2;
43 bool SwapVectorOperands;
44 CondX86::CmppsCond Predicate;
45 } TableFcmp[];
46 static const size_t TableFcmpSize;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070047
John Porto7e93c622015-06-23 10:58:57 -070048 // The following table summarizes the logic for lowering the icmp instruction
49 // for i32 and narrower types. Each icmp condition has a clear mapping to an
50 // x86 conditional branch instruction.
51
52 static const struct TableIcmp32Type {
53 CondX86::BrCond Mapping;
54 } TableIcmp32[];
55 static const size_t TableIcmp32Size;
56
57 // The following table summarizes the logic for lowering the icmp instruction
58 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
59 // conditional branches are needed. For the other conditions, three separate
60 // conditional branches are needed.
61 static const struct TableIcmp64Type {
62 CondX86::BrCond C1, C2, C3;
63 } TableIcmp64[];
64 static const size_t TableIcmp64Size;
65
66 static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
67 size_t Index = static_cast<size_t>(Cond);
68 assert(Index < TableIcmp32Size);
69 return TableIcmp32[Index].Mapping;
70 }
71
72 static const struct TableTypeX8632AttributesType {
73 Type InVectorElementType;
74 } TableTypeX8632Attributes[];
75 static const size_t TableTypeX8632AttributesSize;
76
77 // Return the type which the elements of the vector have in the X86
78 // representation of the vector.
79 static Type getInVectorElementType(Type Ty) {
80 assert(isVectorType(Ty));
81 size_t Index = static_cast<size_t>(Ty);
82 (void)Index;
83 assert(Index < TableTypeX8632AttributesSize);
84 return TableTypeX8632Attributes[Ty].InVectorElementType;
85 }
86
87 // The maximum number of arguments to pass in XMM registers
John Porto36087cd2015-06-24 16:16:13 -070088 static const uint32_t X86_MAX_XMM_ARGS = 4;
John Porto7e93c622015-06-23 10:58:57 -070089 // The number of bits in a byte
John Porto36087cd2015-06-24 16:16:13 -070090 static const uint32_t X86_CHAR_BIT = 8;
John Porto7e93c622015-06-23 10:58:57 -070091 // Stack alignment
92 static const uint32_t X86_STACK_ALIGNMENT_BYTES;
93 // Size of the return address on the stack
John Porto36087cd2015-06-24 16:16:13 -070094 static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
John Porto7e93c622015-06-23 10:58:57 -070095 // The number of different NOP instructions
John Porto36087cd2015-06-24 16:16:13 -070096 static const uint32_t X86_NUM_NOP_VARIANTS = 5;
John Porto7e93c622015-06-23 10:58:57 -070097
98 // Value is in bytes. Return Value adjusted to the next highest multiple
99 // of the stack alignment.
100 static uint32_t applyStackAlignment(uint32_t Value) {
101 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
102 }
103};
104
105const MachineTraits<TargetX8632>::TableFcmpType
106 MachineTraits<TargetX8632>::TableFcmp[] = {
Matt Walace0ca8f2014-07-24 12:34:20 -0700107#define X(val, dflt, swapS, C1, C2, swapV, pred) \
Jan Voungbd385e42014-09-18 18:18:10 -0700108 { dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700109 ,
John Porto7e93c622015-06-23 10:58:57 -0700110 FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700111#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800112};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700113
John Porto36087cd2015-06-24 16:16:13 -0700114const size_t MachineTraits<TargetX8632>::TableFcmpSize =
John Porto7e93c622015-06-23 10:58:57 -0700115 llvm::array_lengthof(TableFcmp);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700116
John Porto7e93c622015-06-23 10:58:57 -0700117const MachineTraits<TargetX8632>::TableIcmp32Type
118 MachineTraits<TargetX8632>::TableIcmp32[] = {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700119#define X(val, C_32, C1_64, C2_64, C3_64) \
Jan Voungbd385e42014-09-18 18:18:10 -0700120 { CondX86::C_32 } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700121 ,
John Porto7e93c622015-06-23 10:58:57 -0700122 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700123#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800124};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700125
John Porto36087cd2015-06-24 16:16:13 -0700126const size_t MachineTraits<TargetX8632>::TableIcmp32Size =
John Porto7e93c622015-06-23 10:58:57 -0700127 llvm::array_lengthof(TableIcmp32);
128
129const MachineTraits<TargetX8632>::TableIcmp64Type
130 MachineTraits<TargetX8632>::TableIcmp64[] = {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700131#define X(val, C_32, C1_64, C2_64, C3_64) \
Jan Voungbd385e42014-09-18 18:18:10 -0700132 { CondX86::C1_64, CondX86::C2_64, CondX86::C3_64 } \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700133 ,
John Porto7e93c622015-06-23 10:58:57 -0700134 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700135#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800136};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700137
John Porto36087cd2015-06-24 16:16:13 -0700138const size_t MachineTraits<TargetX8632>::TableIcmp64Size =
John Porto7e93c622015-06-23 10:58:57 -0700139 llvm::array_lengthof(TableIcmp64);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700140
John Porto7e93c622015-06-23 10:58:57 -0700141const MachineTraits<TargetX8632>::TableTypeX8632AttributesType
142 MachineTraits<TargetX8632>::TableTypeX8632Attributes[] = {
Jim Stichnothbca2f652014-11-01 10:13:54 -0700143#define X(tag, elementty, cvt, sdss, pack, width, fld) \
Matt Wala49889232014-07-18 12:45:09 -0700144 { elementty } \
145 ,
John Porto7e93c622015-06-23 10:58:57 -0700146 ICETYPEX8632_TABLE
Matt Wala49889232014-07-18 12:45:09 -0700147#undef X
Jim Stichnothdd842db2015-01-27 12:53:53 -0800148};
John Porto7e93c622015-06-23 10:58:57 -0700149
John Porto36087cd2015-06-24 16:16:13 -0700150const size_t MachineTraits<TargetX8632>::TableTypeX8632AttributesSize =
Matt Wala49889232014-07-18 12:45:09 -0700151 llvm::array_lengthof(TableTypeX8632Attributes);
152
John Porto7e93c622015-06-23 10:58:57 -0700153const uint32_t MachineTraits<TargetX8632>::X86_STACK_ALIGNMENT_BYTES = 16;
154} // end of namespace X86Internal
155
156TargetX8632 *TargetX8632::create(Cfg *Func) {
157 return X86Internal::TargetX86Base<TargetX8632>::create(Func);
Matt Wala49889232014-07-18 12:45:09 -0700158}
159
John Porto7e93c622015-06-23 10:58:57 -0700160TargetDataX8632::TargetDataX8632(GlobalContext *Ctx)
161 : TargetDataLowering(Ctx) {}
Matt Wala105b7042014-08-11 19:56:19 -0700162
John Porto7e93c622015-06-23 10:58:57 -0700163namespace {
164template <typename T> struct PoolTypeConverter {};
165
166template <> struct PoolTypeConverter<float> {
167 typedef uint32_t PrimitiveIntType;
168 typedef ConstantFloat IceType;
169 static const Type Ty = IceType_f32;
170 static const char *TypeName;
171 static const char *AsmTag;
172 static const char *PrintfString;
173};
174const char *PoolTypeConverter<float>::TypeName = "float";
175const char *PoolTypeConverter<float>::AsmTag = ".long";
176const char *PoolTypeConverter<float>::PrintfString = "0x%x";
177
178template <> struct PoolTypeConverter<double> {
179 typedef uint64_t PrimitiveIntType;
180 typedef ConstantDouble IceType;
181 static const Type Ty = IceType_f64;
182 static const char *TypeName;
183 static const char *AsmTag;
184 static const char *PrintfString;
185};
186const char *PoolTypeConverter<double>::TypeName = "double";
187const char *PoolTypeConverter<double>::AsmTag = ".quad";
188const char *PoolTypeConverter<double>::PrintfString = "0x%llx";
189
190// Add converter for int type constant pooling
191template <> struct PoolTypeConverter<uint32_t> {
192 typedef uint32_t PrimitiveIntType;
193 typedef ConstantInteger32 IceType;
194 static const Type Ty = IceType_i32;
195 static const char *TypeName;
196 static const char *AsmTag;
197 static const char *PrintfString;
198};
199const char *PoolTypeConverter<uint32_t>::TypeName = "i32";
200const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
201const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
202
203// Add converter for int type constant pooling
204template <> struct PoolTypeConverter<uint16_t> {
205 typedef uint32_t PrimitiveIntType;
206 typedef ConstantInteger32 IceType;
207 static const Type Ty = IceType_i16;
208 static const char *TypeName;
209 static const char *AsmTag;
210 static const char *PrintfString;
211};
212const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
213const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
214const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
215
216// Add converter for int type constant pooling
217template <> struct PoolTypeConverter<uint8_t> {
218 typedef uint32_t PrimitiveIntType;
219 typedef ConstantInteger32 IceType;
220 static const Type Ty = IceType_i8;
221 static const char *TypeName;
222 static const char *AsmTag;
223 static const char *PrintfString;
224};
225const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
226const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
227const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
228} // end of anonymous namespace
229
230template <typename T>
231void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700232 if (!BuildDefs::dump())
John Porto7e93c622015-06-23 10:58:57 -0700233 return;
234 Ostream &Str = Ctx->getStrEmit();
235 Type Ty = T::Ty;
236 SizeT Align = typeAlignInBytes(Ty);
237 ConstantList Pool = Ctx->getConstantPool(Ty);
238
239 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align
240 << "\n";
241 Str << "\t.align\t" << Align << "\n";
Qining Lu7cd53512015-06-26 09:36:00 -0700242
243 // If reorder-pooled-constants option is set to true, we need to shuffle the
244 // constant pool before emitting it.
245 if (Ctx->getFlags().shouldReorderPooledConstants())
246 RandomShuffle(Pool.begin(), Pool.end(), [Ctx](uint64_t N) {
247 return (uint32_t)Ctx->getRNG().next(N);
248 });
249
John Porto7e93c622015-06-23 10:58:57 -0700250 for (Constant *C : Pool) {
251 if (!C->getShouldBePooled())
252 continue;
253 typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
254 typename T::IceType::PrimType Value = Const->getValue();
255 // Use memcpy() to copy bits from Value into RawValue in a way
256 // that avoids breaking strict-aliasing rules.
257 typename T::PrimitiveIntType RawValue;
258 memcpy(&RawValue, &Value, sizeof(Value));
259 char buf[30];
260 int CharsPrinted =
261 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue);
262 assert(CharsPrinted >= 0 &&
263 (size_t)CharsPrinted < llvm::array_lengthof(buf));
264 (void)CharsPrinted; // avoid warnings if asserts are disabled
265 Const->emitPoolLabel(Str);
266 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
267 << Value << "\n";
268 }
Matt Wala105b7042014-08-11 19:56:19 -0700269}
Matt Wala45a06232014-07-09 16:33:22 -0700270
John Porto7e93c622015-06-23 10:58:57 -0700271void TargetDataX8632::lowerConstants() {
272 if (Ctx->getFlags().getDisableTranslation())
273 return;
274 // No need to emit constants from the int pool since (for x86) they
275 // are embedded as immediates in the instructions, just emit float/double.
276 switch (Ctx->getFlags().getOutFileType()) {
277 case FT_Elf: {
278 ELFObjectWriter *Writer = Ctx->getObjectWriter();
279
280 Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
281 Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
282 Writer->writeConstantPool<ConstantInteger32>(IceType_i32);
283
284 Writer->writeConstantPool<ConstantFloat>(IceType_f32);
285 Writer->writeConstantPool<ConstantDouble>(IceType_f64);
286 } break;
287 case FT_Asm:
288 case FT_Iasm: {
289 OstreamLocker L(Ctx);
290
291 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
292 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
293 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
294
295 emitConstantPool<PoolTypeConverter<float>>(Ctx);
296 emitConstantPool<PoolTypeConverter<double>>(Ctx);
297 } break;
298 }
299}
300
301void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars,
302 const IceString &SectionSuffix) {
303 switch (Ctx->getFlags().getOutFileType()) {
304 case FT_Elf: {
305 ELFObjectWriter *Writer = Ctx->getObjectWriter();
306 Writer->writeDataSection(Vars, llvm::ELF::R_386_32, SectionSuffix);
307 } break;
308 case FT_Asm:
309 case FT_Iasm: {
310 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly();
311 OstreamLocker L(Ctx);
312 for (const VariableDeclaration *Var : Vars) {
313 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) {
314 emitGlobal(*Var, SectionSuffix);
315 }
316 }
317 } break;
318 }
319}
320
321TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx)
322 : TargetHeaderLowering(Ctx) {}
323
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700324// In some cases, there are x-macros tables for both high-level and
325// low-level instructions/operands that use the same enum key value.
326// The tables are kept separate to maintain a proper separation
Jim Stichnothfac55172014-10-01 13:06:21 -0700327// between abstraction layers. There is a risk that the tables could
328// get out of sync if enum values are reordered or if entries are
329// added or deleted. The following dummy namespaces use
330// static_asserts to ensure everything is kept in sync.
331
John Porto7e93c622015-06-23 10:58:57 -0700332namespace {
Jim Stichnothfac55172014-10-01 13:06:21 -0700333// Validate the enum values in FCMPX8632_TABLE.
334namespace dummy1 {
335// Define a temporary set of enum values based on low-level table
336// entries.
337enum _tmp_enum {
Matt Walace0ca8f2014-07-24 12:34:20 -0700338#define X(val, dflt, swapS, C1, C2, swapV, pred) _tmp_##val,
Jim Stichnothfac55172014-10-01 13:06:21 -0700339 FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700340#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700341 _num
342};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700343// Define a set of constants based on high-level table entries.
344#define X(tag, str) static const int _table1_##tag = InstFcmp::tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800345ICEINSTFCMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700346#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700347// Define a set of constants based on low-level table entries, and
348// ensure the table entry keys are consistent.
Matt Walace0ca8f2014-07-24 12:34:20 -0700349#define X(val, dflt, swapS, C1, C2, swapV, pred) \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700350 static const int _table2_##val = _tmp_##val; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700351 static_assert( \
352 _table1_##val == _table2_##val, \
353 "Inconsistency between FCMPX8632_TABLE and ICEINSTFCMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800354FCMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700355#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700356// Repeat the static asserts with respect to the high-level table
357// entries in case the high-level table has extra entries.
358#define X(tag, str) \
359 static_assert( \
360 _table1_##tag == _table2_##tag, \
361 "Inconsistency between FCMPX8632_TABLE and ICEINSTFCMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800362ICEINSTFCMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700363#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700364} // end of namespace dummy1
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700365
Jim Stichnothfac55172014-10-01 13:06:21 -0700366// Validate the enum values in ICMPX8632_TABLE.
367namespace dummy2 {
368// Define a temporary set of enum values based on low-level table
369// entries.
370enum _tmp_enum {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700371#define X(val, C_32, C1_64, C2_64, C3_64) _tmp_##val,
Jim Stichnothfac55172014-10-01 13:06:21 -0700372 ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700373#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700374 _num
375};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700376// Define a set of constants based on high-level table entries.
377#define X(tag, str) static const int _table1_##tag = InstIcmp::tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800378ICEINSTICMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700379#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700380// Define a set of constants based on low-level table entries, and
381// ensure the table entry keys are consistent.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700382#define X(val, C_32, C1_64, C2_64, C3_64) \
383 static const int _table2_##val = _tmp_##val; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700384 static_assert( \
385 _table1_##val == _table2_##val, \
386 "Inconsistency between ICMPX8632_TABLE and ICEINSTICMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800387ICMPX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700388#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700389// Repeat the static asserts with respect to the high-level table
390// entries in case the high-level table has extra entries.
391#define X(tag, str) \
392 static_assert( \
393 _table1_##tag == _table2_##tag, \
394 "Inconsistency between ICMPX8632_TABLE and ICEINSTICMP_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800395ICEINSTICMP_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700396#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700397} // end of namespace dummy2
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700398
Jim Stichnothfac55172014-10-01 13:06:21 -0700399// Validate the enum values in ICETYPEX8632_TABLE.
400namespace dummy3 {
401// Define a temporary set of enum values based on low-level table
402// entries.
403enum _tmp_enum {
Jim Stichnothbca2f652014-11-01 10:13:54 -0700404#define X(tag, elementty, cvt, sdss, pack, width, fld) _tmp_##tag,
Jim Stichnothfac55172014-10-01 13:06:21 -0700405 ICETYPEX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700406#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700407 _num
408};
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700409// Define a set of constants based on high-level table entries.
Matt Wala928f1292014-07-07 16:50:46 -0700410#define X(tag, size, align, elts, elty, str) \
411 static const int _table1_##tag = tag;
JF Bastien8427ea22015-01-27 12:56:49 -0800412ICETYPE_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700413#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700414// Define a set of constants based on low-level table entries, and
415// ensure the table entry keys are consistent.
Jim Stichnothbca2f652014-11-01 10:13:54 -0700416#define X(tag, elementty, cvt, sdss, pack, width, fld) \
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700417 static const int _table2_##tag = _tmp_##tag; \
Jim Stichnothfac55172014-10-01 13:06:21 -0700418 static_assert(_table1_##tag == _table2_##tag, \
419 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800420ICETYPEX8632_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700421#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700422// Repeat the static asserts with respect to the high-level table
423// entries in case the high-level table has extra entries.
Matt Wala928f1292014-07-07 16:50:46 -0700424#define X(tag, size, align, elts, elty, str) \
Jim Stichnothfac55172014-10-01 13:06:21 -0700425 static_assert(_table1_##tag == _table2_##tag, \
426 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE");
JF Bastien8427ea22015-01-27 12:56:49 -0800427ICETYPE_TABLE
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700428#undef X
Jim Stichnothfac55172014-10-01 13:06:21 -0700429} // end of namespace dummy3
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700430} // end of anonymous namespace
431
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700432} // end of namespace Ice