OLD | NEW |
---|---|
1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// |
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 |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "IceLiveness.h" | 26 #include "IceLiveness.h" |
27 #include "IceOperand.h" | 27 #include "IceOperand.h" |
28 #include "IcePhiLoweringImpl.h" | 28 #include "IcePhiLoweringImpl.h" |
29 #include "IceUtils.h" | 29 #include "IceUtils.h" |
30 #include "IceInstX86Base.h" | 30 #include "IceInstX86Base.h" |
31 #include "llvm/Support/MathExtras.h" | 31 #include "llvm/Support/MathExtras.h" |
32 | 32 |
33 #include <stack> | 33 #include <stack> |
34 | 34 |
35 namespace Ice { | 35 namespace Ice { |
36 namespace X86 { | |
37 template <typename T> struct PoolTypeConverter {}; | |
38 | |
39 template <> struct PoolTypeConverter<float> { | |
40 using PrimitiveIntType = uint32_t; | |
41 using IceType = ConstantFloat; | |
42 static const Type Ty = IceType_f32; | |
43 static const char *TypeName; | |
44 static const char *AsmTag; | |
45 static const char *PrintfString; | |
46 }; | |
47 | |
48 template <> struct PoolTypeConverter<double> { | |
49 using PrimitiveIntType = uint64_t; | |
50 using IceType = ConstantDouble; | |
51 static const Type Ty = IceType_f64; | |
52 static const char *TypeName; | |
53 static const char *AsmTag; | |
54 static const char *PrintfString; | |
55 }; | |
56 | |
57 // Add converter for int type constant pooling | |
58 template <> struct PoolTypeConverter<uint32_t> { | |
59 using PrimitiveIntType = uint32_t; | |
60 using IceType = ConstantInteger32; | |
61 static const Type Ty = IceType_i32; | |
62 static const char *TypeName; | |
63 static const char *AsmTag; | |
64 static const char *PrintfString; | |
65 }; | |
66 | |
67 // Add converter for int type constant pooling | |
68 template <> struct PoolTypeConverter<uint16_t> { | |
69 using PrimitiveIntType = uint32_t; | |
70 using IceType = ConstantInteger32; | |
71 static const Type Ty = IceType_i16; | |
72 static const char *TypeName; | |
73 static const char *AsmTag; | |
74 static const char *PrintfString; | |
75 }; | |
76 | |
77 // Add converter for int type constant pooling | |
78 template <> struct PoolTypeConverter<uint8_t> { | |
79 using PrimitiveIntType = uint32_t; | |
80 using IceType = ConstantInteger32; | |
81 static const Type Ty = IceType_i8; | |
82 static const char *TypeName; | |
83 static const char *AsmTag; | |
84 static const char *PrintfString; | |
85 }; | |
86 } // end of namespace X86 | |
87 | |
36 namespace X86NAMESPACE { | 88 namespace X86NAMESPACE { |
37 | 89 |
38 /// A helper class to ease the settings of RandomizationPoolingPause to disable | 90 /// A helper class to ease the settings of RandomizationPoolingPause to disable |
39 /// constant blinding or pooling for some translation phases. | 91 /// constant blinding or pooling for some translation phases. |
40 class BoolFlagSaver { | 92 class BoolFlagSaver { |
41 BoolFlagSaver() = delete; | 93 BoolFlagSaver() = delete; |
42 BoolFlagSaver(const BoolFlagSaver &) = delete; | 94 BoolFlagSaver(const BoolFlagSaver &) = delete; |
43 BoolFlagSaver &operator=(const BoolFlagSaver &) = delete; | 95 BoolFlagSaver &operator=(const BoolFlagSaver &) = delete; |
44 | 96 |
45 public: | 97 public: |
(...skipping 7176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7222 0, MemOperand->getSegmentRegister()); | 7274 0, MemOperand->getSegmentRegister()); |
7223 _lea(RegTemp, CalculateOperand); | 7275 _lea(RegTemp, CalculateOperand); |
7224 } | 7276 } |
7225 X86OperandMem *NewMemOperand = X86OperandMem::create( | 7277 X86OperandMem *NewMemOperand = X86OperandMem::create( |
7226 Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(), | 7278 Func, MemOperand->getType(), RegTemp, nullptr, MemOperand->getIndex(), |
7227 MemOperand->getShift(), MemOperand->getSegmentRegister()); | 7279 MemOperand->getShift(), MemOperand->getSegmentRegister()); |
7228 return NewMemOperand; | 7280 return NewMemOperand; |
7229 } | 7281 } |
7230 } | 7282 } |
7231 } | 7283 } |
7284 | |
7285 template <typename TraitsType> | |
7286 void TargetX86Base<TraitsType>::emitJumpTable( | |
7287 const Cfg *Func, const InstJumpTable *JumpTable) const { | |
7288 if (!BuildDefs::dump()) | |
7289 return; | |
7290 Ostream &Str = Ctx->getStrEmit(); | |
7291 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | |
7292 const IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | |
7293 const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; | |
7294 Str << "\t.section\t" << Prefix << MangledName | |
7295 << "$jumptable,\"a\",@progbits\n"; | |
7296 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
7297 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | |
7298 | |
7299 // On X86 ILP32 pointers are 32-bit hence the use of .long | |
7300 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | |
7301 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | |
7302 Str << "\n"; | |
7303 } | |
7304 | |
7305 template <typename TraitsType> | |
7306 template <typename T> | |
7307 void TargetDataX86<TraitsType>::emitConstantPool(GlobalContext *Ctx) { | |
7308 if (!BuildDefs::dump()) | |
7309 return; | |
7310 Ostream &Str = Ctx->getStrEmit(); | |
7311 Type Ty = T::Ty; | |
7312 SizeT Align = typeAlignInBytes(Ty); | |
7313 ConstantList Pool = Ctx->getConstantPool(Ty); | |
7314 | |
7315 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | |
7316 << "\n"; | |
7317 Str << "\t.align\t" << Align << "\n"; | |
7318 | |
7319 // If reorder-pooled-constants option is set to true, we need to shuffle the | |
7320 // constant pool before emitting it. | |
7321 if (Ctx->getFlags().shouldReorderPooledConstants() && !Pool.empty()) { | |
7322 // Use the constant's kind value as the salt for creating random number | |
7323 // generator. | |
7324 Operand::OperandKind K = (*Pool.begin())->getKind(); | |
7325 RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), | |
7326 RPE_PooledConstantReordering, K); | |
7327 RandomShuffle(Pool.begin(), Pool.end(), | |
7328 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); | |
7329 } | |
7330 | |
7331 for (Constant *C : Pool) { | |
7332 if (!C->getShouldBePooled()) | |
7333 continue; | |
7334 auto *Const = llvm::cast<typename T::IceType>(C); | |
7335 typename T::IceType::PrimType Value = Const->getValue(); | |
7336 // Use memcpy() to copy bits from Value into RawValue in a way that avoids | |
7337 // breaking strict-aliasing rules. | |
7338 typename T::PrimitiveIntType RawValue; | |
7339 memcpy(&RawValue, &Value, sizeof(Value)); | |
7340 char buf[30]; | |
7341 int CharsPrinted = | |
7342 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | |
7343 assert(CharsPrinted >= 0 && | |
Jim Stichnoth
2016/01/22 05:52:10
This is better split into two separate asserts.
sehr
2016/01/22 07:06:23
Done.
| |
7344 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | |
7345 (void)CharsPrinted; // avoid warnings if asserts are disabled | |
7346 Const->emitPoolLabel(Str, Ctx); | |
7347 Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t/* " << T::TypeName << " " | |
7348 << Value << " */\n"; | |
7349 } | |
7350 } | |
7351 | |
7352 template <typename TraitsType> | |
7353 void TargetDataX86<TraitsType>::lowerConstants() { | |
7354 if (Ctx->getFlags().getDisableTranslation()) | |
7355 return; | |
7356 // No need to emit constants from the int pool since (for x86) they are | |
Jim Stichnoth
2016/01/22 05:52:10
This comment seems wrong and should probably be de
sehr
2016/01/22 07:06:23
Deleted.
| |
7357 // embedded as immediates in the instructions, just emit float/double. | |
7358 switch (Ctx->getFlags().getOutFileType()) { | |
7359 case FT_Elf: { | |
7360 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | |
7361 | |
7362 Writer->writeConstantPool<ConstantInteger32>(IceType_i8); | |
7363 Writer->writeConstantPool<ConstantInteger32>(IceType_i16); | |
7364 Writer->writeConstantPool<ConstantInteger32>(IceType_i32); | |
7365 | |
7366 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | |
7367 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | |
7368 } break; | |
7369 case FT_Asm: | |
7370 case FT_Iasm: { | |
7371 OstreamLocker L(Ctx); | |
7372 | |
7373 emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx); | |
7374 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | |
7375 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | |
7376 | |
7377 emitConstantPool<PoolTypeConverter<float>>(Ctx); | |
7378 emitConstantPool<PoolTypeConverter<double>>(Ctx); | |
7379 } break; | |
7380 } | |
7381 } | |
7382 | |
7383 template <typename TraitsType> | |
7384 void TargetDataX86<TraitsType>::lowerJumpTables() { | |
7385 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
7386 switch (Ctx->getFlags().getOutFileType()) { | |
7387 case FT_Elf: { | |
7388 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | |
7389 for (const JumpTableData &JT : Ctx->getJumpTables()) | |
7390 Writer->writeJumpTable(JT, Traits::FK_Abs, IsPIC); | |
7391 } break; | |
7392 case FT_Asm: | |
7393 // Already emitted from Cfg | |
7394 break; | |
7395 case FT_Iasm: { | |
7396 if (!BuildDefs::dump()) | |
7397 return; | |
7398 Ostream &Str = Ctx->getStrEmit(); | |
7399 const IceString Prefix = IsPIC ? ".data.rel.ro." : ".rodata."; | |
7400 for (const JumpTableData &JT : Ctx->getJumpTables()) { | |
7401 Str << "\t.section\t" << Prefix << JT.getFunctionName() | |
7402 << "$jumptable,\"a\",@progbits\n"; | |
7403 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | |
7404 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | |
7405 | |
7406 // On X8664 ILP32 pointers are 32-bit hence the use of .long | |
7407 for (intptr_t TargetOffset : JT.getTargetOffsets()) | |
7408 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | |
7409 Str << "\n"; | |
7410 } | |
7411 } break; | |
7412 } | |
7413 } | |
7414 | |
7415 template <typename TraitsType> | |
7416 void TargetDataX86<TraitsType>::lowerGlobals( | |
7417 const VariableDeclarationList &Vars, const IceString &SectionSuffix) { | |
7418 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
7419 switch (Ctx->getFlags().getOutFileType()) { | |
7420 case FT_Elf: { | |
7421 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | |
7422 Writer->writeDataSection(Vars, Traits::FK_Abs, SectionSuffix, IsPIC); | |
7423 } break; | |
7424 case FT_Asm: | |
7425 case FT_Iasm: { | |
7426 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); | |
7427 OstreamLocker L(Ctx); | |
7428 for (const VariableDeclaration *Var : Vars) { | |
7429 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | |
7430 emitGlobal(*Var, SectionSuffix); | |
7431 } | |
7432 } | |
7433 } break; | |
7434 } | |
7435 } | |
7232 } // end of namespace X86NAMESPACE | 7436 } // end of namespace X86NAMESPACE |
7233 } // end of namespace Ice | 7437 } // end of namespace Ice |
7234 | 7438 |
7235 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 7439 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |