Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 1 | //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
| 2 | // |
| 3 | // The Subzero Code Generator |
| 4 | // |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 5 | //===----------------------------------------------------------------------===// |
| 6 | // |
| 7 | // This file implements the TargetLoweringX8632 class, which |
| 8 | // consists almost entirely of the lowering sequence for each |
Jim Stichnoth | 70d0a05 | 2014-11-14 15:53:46 -0800 | [diff] [blame] | 9 | // high-level instruction. |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 13 | #include "IceTargetLoweringX8632.h" |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 14 | |
| 15 | #include "IceTargetLoweringX86Base.h" |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 16 | |
| 17 | namespace Ice { |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 18 | namespace X86Internal { |
| 19 | template <> struct MachineTraits<TargetX8632> { |
| 20 | using InstructionSet = TargetX8632::X86InstructionSet; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 21 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 22 | // 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 Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 47 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 48 | // 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 Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 88 | static const uint32_t X86_MAX_XMM_ARGS = 4; |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 89 | // The number of bits in a byte |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 90 | static const uint32_t X86_CHAR_BIT = 8; |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 91 | // Stack alignment |
| 92 | static const uint32_t X86_STACK_ALIGNMENT_BYTES; |
| 93 | // Size of the return address on the stack |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 94 | static const uint32_t X86_RET_IP_SIZE_BYTES = 4; |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 95 | // The number of different NOP instructions |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 96 | static const uint32_t X86_NUM_NOP_VARIANTS = 5; |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 97 | |
| 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 | |
| 105 | const MachineTraits<TargetX8632>::TableFcmpType |
| 106 | MachineTraits<TargetX8632>::TableFcmp[] = { |
Matt Wala | ce0ca8f | 2014-07-24 12:34:20 -0700 | [diff] [blame] | 107 | #define X(val, dflt, swapS, C1, C2, swapV, pred) \ |
Jan Voung | bd385e4 | 2014-09-18 18:18:10 -0700 | [diff] [blame] | 108 | { dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred } \ |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 109 | , |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 110 | FCMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 111 | #undef X |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 112 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 113 | |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 114 | const size_t MachineTraits<TargetX8632>::TableFcmpSize = |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 115 | llvm::array_lengthof(TableFcmp); |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 116 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 117 | const MachineTraits<TargetX8632>::TableIcmp32Type |
| 118 | MachineTraits<TargetX8632>::TableIcmp32[] = { |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 119 | #define X(val, C_32, C1_64, C2_64, C3_64) \ |
Jan Voung | bd385e4 | 2014-09-18 18:18:10 -0700 | [diff] [blame] | 120 | { CondX86::C_32 } \ |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 121 | , |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 122 | ICMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 123 | #undef X |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 124 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 125 | |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 126 | const size_t MachineTraits<TargetX8632>::TableIcmp32Size = |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 127 | llvm::array_lengthof(TableIcmp32); |
| 128 | |
| 129 | const MachineTraits<TargetX8632>::TableIcmp64Type |
| 130 | MachineTraits<TargetX8632>::TableIcmp64[] = { |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 131 | #define X(val, C_32, C1_64, C2_64, C3_64) \ |
Jan Voung | bd385e4 | 2014-09-18 18:18:10 -0700 | [diff] [blame] | 132 | { CondX86::C1_64, CondX86::C2_64, CondX86::C3_64 } \ |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 133 | , |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 134 | ICMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 135 | #undef X |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 136 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 137 | |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 138 | const size_t MachineTraits<TargetX8632>::TableIcmp64Size = |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 139 | llvm::array_lengthof(TableIcmp64); |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 140 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 141 | const MachineTraits<TargetX8632>::TableTypeX8632AttributesType |
| 142 | MachineTraits<TargetX8632>::TableTypeX8632Attributes[] = { |
Jim Stichnoth | bca2f65 | 2014-11-01 10:13:54 -0700 | [diff] [blame] | 143 | #define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
Matt Wala | 4988923 | 2014-07-18 12:45:09 -0700 | [diff] [blame] | 144 | { elementty } \ |
| 145 | , |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 146 | ICETYPEX8632_TABLE |
Matt Wala | 4988923 | 2014-07-18 12:45:09 -0700 | [diff] [blame] | 147 | #undef X |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 148 | }; |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 149 | |
John Porto | 36087cd | 2015-06-24 16:16:13 -0700 | [diff] [blame] | 150 | const size_t MachineTraits<TargetX8632>::TableTypeX8632AttributesSize = |
Matt Wala | 4988923 | 2014-07-18 12:45:09 -0700 | [diff] [blame] | 151 | llvm::array_lengthof(TableTypeX8632Attributes); |
| 152 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 153 | const uint32_t MachineTraits<TargetX8632>::X86_STACK_ALIGNMENT_BYTES = 16; |
| 154 | } // end of namespace X86Internal |
| 155 | |
| 156 | TargetX8632 *TargetX8632::create(Cfg *Func) { |
| 157 | return X86Internal::TargetX86Base<TargetX8632>::create(Func); |
Matt Wala | 4988923 | 2014-07-18 12:45:09 -0700 | [diff] [blame] | 158 | } |
| 159 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 160 | TargetDataX8632::TargetDataX8632(GlobalContext *Ctx) |
| 161 | : TargetDataLowering(Ctx) {} |
Matt Wala | 105b704 | 2014-08-11 19:56:19 -0700 | [diff] [blame] | 162 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 163 | namespace { |
| 164 | template <typename T> struct PoolTypeConverter {}; |
| 165 | |
| 166 | template <> 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 | }; |
| 174 | const char *PoolTypeConverter<float>::TypeName = "float"; |
| 175 | const char *PoolTypeConverter<float>::AsmTag = ".long"; |
| 176 | const char *PoolTypeConverter<float>::PrintfString = "0x%x"; |
| 177 | |
| 178 | template <> 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 | }; |
| 186 | const char *PoolTypeConverter<double>::TypeName = "double"; |
| 187 | const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
| 188 | const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
| 189 | |
| 190 | // Add converter for int type constant pooling |
| 191 | template <> 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 | }; |
| 199 | const char *PoolTypeConverter<uint32_t>::TypeName = "i32"; |
| 200 | const char *PoolTypeConverter<uint32_t>::AsmTag = ".long"; |
| 201 | const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x"; |
| 202 | |
| 203 | // Add converter for int type constant pooling |
| 204 | template <> 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 | }; |
| 212 | const char *PoolTypeConverter<uint16_t>::TypeName = "i16"; |
| 213 | const char *PoolTypeConverter<uint16_t>::AsmTag = ".short"; |
| 214 | const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x"; |
| 215 | |
| 216 | // Add converter for int type constant pooling |
| 217 | template <> 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 | }; |
| 225 | const char *PoolTypeConverter<uint8_t>::TypeName = "i8"; |
| 226 | const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte"; |
| 227 | const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x"; |
| 228 | } // end of anonymous namespace |
| 229 | |
| 230 | template <typename T> |
| 231 | void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { |
Jim Stichnoth | 20b71f5 | 2015-06-24 15:52:24 -0700 | [diff] [blame] | 232 | if (!BuildDefs::dump()) |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 233 | 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 Lu | 7cd5351 | 2015-06-26 09:36:00 -0700 | [diff] [blame] | 242 | |
| 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 Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 250 | 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 Wala | 105b704 | 2014-08-11 19:56:19 -0700 | [diff] [blame] | 269 | } |
Matt Wala | 45a0623 | 2014-07-09 16:33:22 -0700 | [diff] [blame] | 270 | |
John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 271 | void 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 | |
| 301 | void 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 | |
| 321 | TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) |
| 322 | : TargetHeaderLowering(Ctx) {} |
| 323 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 324 | // 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 Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 327 | // 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 Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 332 | namespace { |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 333 | // Validate the enum values in FCMPX8632_TABLE. |
| 334 | namespace dummy1 { |
| 335 | // Define a temporary set of enum values based on low-level table |
| 336 | // entries. |
| 337 | enum _tmp_enum { |
Matt Wala | ce0ca8f | 2014-07-24 12:34:20 -0700 | [diff] [blame] | 338 | #define X(val, dflt, swapS, C1, C2, swapV, pred) _tmp_##val, |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 339 | FCMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 340 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 341 | _num |
| 342 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 343 | // Define a set of constants based on high-level table entries. |
| 344 | #define X(tag, str) static const int _table1_##tag = InstFcmp::tag; |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 345 | ICEINSTFCMP_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 346 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 347 | // Define a set of constants based on low-level table entries, and |
| 348 | // ensure the table entry keys are consistent. |
Matt Wala | ce0ca8f | 2014-07-24 12:34:20 -0700 | [diff] [blame] | 349 | #define X(val, dflt, swapS, C1, C2, swapV, pred) \ |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 350 | static const int _table2_##val = _tmp_##val; \ |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 351 | static_assert( \ |
| 352 | _table1_##val == _table2_##val, \ |
| 353 | "Inconsistency between FCMPX8632_TABLE and ICEINSTFCMP_TABLE"); |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 354 | FCMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 355 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 356 | // 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 Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 362 | ICEINSTFCMP_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 363 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 364 | } // end of namespace dummy1 |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 365 | |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 366 | // Validate the enum values in ICMPX8632_TABLE. |
| 367 | namespace dummy2 { |
| 368 | // Define a temporary set of enum values based on low-level table |
| 369 | // entries. |
| 370 | enum _tmp_enum { |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 371 | #define X(val, C_32, C1_64, C2_64, C3_64) _tmp_##val, |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 372 | ICMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 373 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 374 | _num |
| 375 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 376 | // Define a set of constants based on high-level table entries. |
| 377 | #define X(tag, str) static const int _table1_##tag = InstIcmp::tag; |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 378 | ICEINSTICMP_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 379 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 380 | // Define a set of constants based on low-level table entries, and |
| 381 | // ensure the table entry keys are consistent. |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 382 | #define X(val, C_32, C1_64, C2_64, C3_64) \ |
| 383 | static const int _table2_##val = _tmp_##val; \ |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 384 | static_assert( \ |
| 385 | _table1_##val == _table2_##val, \ |
| 386 | "Inconsistency between ICMPX8632_TABLE and ICEINSTICMP_TABLE"); |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 387 | ICMPX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 388 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 389 | // 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 Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 395 | ICEINSTICMP_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 396 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 397 | } // end of namespace dummy2 |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 398 | |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 399 | // Validate the enum values in ICETYPEX8632_TABLE. |
| 400 | namespace dummy3 { |
| 401 | // Define a temporary set of enum values based on low-level table |
| 402 | // entries. |
| 403 | enum _tmp_enum { |
Jim Stichnoth | bca2f65 | 2014-11-01 10:13:54 -0700 | [diff] [blame] | 404 | #define X(tag, elementty, cvt, sdss, pack, width, fld) _tmp_##tag, |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 405 | ICETYPEX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 406 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 407 | _num |
| 408 | }; |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 409 | // Define a set of constants based on high-level table entries. |
Matt Wala | 928f129 | 2014-07-07 16:50:46 -0700 | [diff] [blame] | 410 | #define X(tag, size, align, elts, elty, str) \ |
| 411 | static const int _table1_##tag = tag; |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 412 | ICETYPE_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 413 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 414 | // Define a set of constants based on low-level table entries, and |
| 415 | // ensure the table entry keys are consistent. |
Jim Stichnoth | bca2f65 | 2014-11-01 10:13:54 -0700 | [diff] [blame] | 416 | #define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 417 | static const int _table2_##tag = _tmp_##tag; \ |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 418 | static_assert(_table1_##tag == _table2_##tag, \ |
| 419 | "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 420 | ICETYPEX8632_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 421 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 422 | // Repeat the static asserts with respect to the high-level table |
| 423 | // entries in case the high-level table has extra entries. |
Matt Wala | 928f129 | 2014-07-07 16:50:46 -0700 | [diff] [blame] | 424 | #define X(tag, size, align, elts, elty, str) \ |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 425 | static_assert(_table1_##tag == _table2_##tag, \ |
| 426 | "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
JF Bastien | 8427ea2 | 2015-01-27 12:56:49 -0800 | [diff] [blame] | 427 | ICETYPE_TABLE |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 428 | #undef X |
Jim Stichnoth | fac5517 | 2014-10-01 13:06:21 -0700 | [diff] [blame] | 429 | } // end of namespace dummy3 |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 430 | } // end of anonymous namespace |
| 431 | |
Jim Stichnoth | 5bc2b1d | 2014-05-22 13:38:48 -0700 | [diff] [blame] | 432 | } // end of namespace Ice |