OLD | NEW |
1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 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 |
(...skipping 14 matching lines...) Expand all Loading... |
25 std::unique_ptr<::Ice::TargetDataLowering> | 25 std::unique_ptr<::Ice::TargetDataLowering> |
26 createTargetDataLowering(::Ice::GlobalContext *Ctx) { | 26 createTargetDataLowering(::Ice::GlobalContext *Ctx) { |
27 return ::Ice::X8632::TargetDataX8632::create(Ctx); | 27 return ::Ice::X8632::TargetDataX8632::create(Ctx); |
28 } | 28 } |
29 | 29 |
30 std::unique_ptr<::Ice::TargetHeaderLowering> | 30 std::unique_ptr<::Ice::TargetHeaderLowering> |
31 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) { | 31 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) { |
32 return ::Ice::X8632::TargetHeaderX8632::create(Ctx); | 32 return ::Ice::X8632::TargetHeaderX8632::create(Ctx); |
33 } | 33 } |
34 | 34 |
35 void staticInit() { ::Ice::X8632::TargetX8632::staticInit(); } | 35 void staticInit(const ::Ice::ClFlags &Flags) { |
| 36 ::Ice::X8632::TargetX8632::staticInit(Flags); |
| 37 } |
36 } // end of namespace X8632 | 38 } // end of namespace X8632 |
37 | 39 |
38 namespace Ice { | 40 namespace Ice { |
39 namespace X8632 { | 41 namespace X8632 { |
40 | 42 |
41 //------------------------------------------------------------------------------ | 43 //------------------------------------------------------------------------------ |
42 // ______ ______ ______ __ ______ ______ | 44 // ______ ______ ______ __ ______ ______ |
43 // /\__ _\ /\ == \ /\ __ \ /\ \ /\__ _\ /\ ___\ | 45 // /\__ _\ /\ == \ /\ __ \ /\ \ /\__ _\ /\ ___\ |
44 // \/_/\ \/ \ \ __< \ \ __ \ \ \ \ \/_/\ \/ \ \___ \ | 46 // \/_/\ \/ \ \ __< \ \ __ \ \ \ \ \/_/\ \/ \ \___ \ |
45 // \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_\ \ \_\ \/\_____\ | 47 // \ \_\ \ \_\ \_\ \ \_\ \_\ \ \_\ \ \_\ \/\_____\ |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 | 107 |
106 template <> | 108 template <> |
107 std::array<llvm::SmallBitVector, | 109 std::array<llvm::SmallBitVector, |
108 TargetX86Base<X8632::Traits>::Traits::RegisterSet::Reg_NUM> | 110 TargetX86Base<X8632::Traits>::Traits::RegisterSet::Reg_NUM> |
109 TargetX86Base<X8632::Traits>::RegisterAliases = {{}}; | 111 TargetX86Base<X8632::Traits>::RegisterAliases = {{}}; |
110 | 112 |
111 template <> | 113 template <> |
112 llvm::SmallBitVector | 114 llvm::SmallBitVector |
113 TargetX86Base<X8632::Traits>::ScratchRegs = llvm::SmallBitVector(); | 115 TargetX86Base<X8632::Traits>::ScratchRegs = llvm::SmallBitVector(); |
114 | 116 |
| 117 template <> |
| 118 FixupKind TargetX86Base<X8632::Traits>::PcRelFixup = |
| 119 TargetX86Base<X8632::Traits>::Traits::FK_PcRel; |
| 120 |
| 121 template <> |
| 122 FixupKind TargetX86Base<X8632::Traits>::AbsFixup = |
| 123 TargetX86Base<X8632::Traits>::Traits::FK_Abs; |
| 124 |
115 //------------------------------------------------------------------------------ | 125 //------------------------------------------------------------------------------ |
116 // __ ______ __ __ ______ ______ __ __ __ ______ | 126 // __ ______ __ __ ______ ______ __ __ __ ______ |
117 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ | 127 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ |
118 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ | 128 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ |
119 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ | 129 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ |
120 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ | 130 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ |
121 // | 131 // |
122 //------------------------------------------------------------------------------ | 132 //------------------------------------------------------------------------------ |
123 void TargetX8632::lowerCall(const InstCall *Instr) { | 133 void TargetX8632::lowerCall(const InstCall *Instr) { |
124 // x86-32 calling convention: | 134 // x86-32 calling convention: |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 case IceType_v8i1: | 243 case IceType_v8i1: |
234 case IceType_v16i1: | 244 case IceType_v16i1: |
235 case IceType_v16i8: | 245 case IceType_v16i8: |
236 case IceType_v8i16: | 246 case IceType_v8i16: |
237 case IceType_v4i32: | 247 case IceType_v4i32: |
238 case IceType_v4f32: | 248 case IceType_v4f32: |
239 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | 249 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); |
240 break; | 250 break; |
241 } | 251 } |
242 } | 252 } |
243 Operand *CallTarget = legalize(Instr->getCallTarget()); | 253 Operand *CallTarget = |
| 254 legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm | Legal_AddrAbs); |
244 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 255 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
245 if (NeedSandboxing) { | 256 if (NeedSandboxing) { |
246 if (llvm::isa<Constant>(CallTarget)) { | 257 if (llvm::isa<Constant>(CallTarget)) { |
247 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 258 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
248 } else { | 259 } else { |
249 Variable *CallTargetVar = nullptr; | 260 Variable *CallTargetVar = nullptr; |
250 _mov(CallTargetVar, CallTarget); | 261 _mov(CallTargetVar, CallTarget); |
251 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 262 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
252 const SizeT BundleSize = | 263 const SizeT BundleSize = |
253 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | 264 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 | 559 |
549 // Fill in stack offsets for stack args, and copy args into registers for | 560 // Fill in stack offsets for stack args, and copy args into registers for |
550 // those that were register-allocated. Args are pushed right to left, so | 561 // those that were register-allocated. Args are pushed right to left, so |
551 // Arg[0] is closest to the stack/frame pointer. | 562 // Arg[0] is closest to the stack/frame pointer. |
552 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 563 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
553 size_t BasicFrameOffset = | 564 size_t BasicFrameOffset = |
554 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; | 565 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; |
555 if (!IsEbpBasedFrame) | 566 if (!IsEbpBasedFrame) |
556 BasicFrameOffset += SpillAreaSizeBytes; | 567 BasicFrameOffset += SpillAreaSizeBytes; |
557 | 568 |
| 569 // If there is a non-deleted InstX86GetIP instruction, we need to move it to |
| 570 // the point after the stack frame has stabilized but before |
| 571 // register-allocated in-args are copied into their home registers. It would |
| 572 // be slightly faster to search for the GetIP instruction before other prolog |
| 573 // instructions are inserted, but it's more clear to do the whole |
| 574 // transformation in a single place. |
| 575 Traits::Insts::GetIP *GetIPInst = nullptr; |
| 576 if (Ctx->getFlags().getUseNonsfi()) { |
| 577 for (Inst &Instr : Node->getInsts()) { |
| 578 if (auto *GetIP = llvm::dyn_cast<Traits::Insts::GetIP>(&Instr)) { |
| 579 if (!Instr.isDeleted()) |
| 580 GetIPInst = GetIP; |
| 581 break; |
| 582 } |
| 583 } |
| 584 } |
| 585 // Delete any existing InstX86GetIP instruction and reinsert it here. Also, |
| 586 // insert the call to the helper function and the spill to the stack, to |
| 587 // simplify emission. |
| 588 if (GetIPInst) { |
| 589 GetIPInst->setDeleted(); |
| 590 Variable *Dest = GetIPInst->getDest(); |
| 591 Variable *CallDest = |
| 592 Dest->hasReg() ? Dest |
| 593 : getPhysicalRegister(Traits::RegisterSet::Reg_eax); |
| 594 // Call the getIP_<reg> helper. |
| 595 IceString RegName = Traits::getRegName(CallDest->getRegNum()); |
| 596 Constant *CallTarget = Ctx->getConstantExternSym(H_getIP_prefix + RegName); |
| 597 Context.insert<Traits::Insts::Call>(CallDest, CallTarget); |
| 598 // Insert a new version of InstX86GetIP. |
| 599 Context.insert<Traits::Insts::GetIP>(CallDest); |
| 600 // Spill the register to its home stack location if necessary. |
| 601 if (!Dest->hasReg()) { |
| 602 _mov(Dest, CallDest); |
| 603 } |
| 604 } |
| 605 |
558 const VarList &Args = Func->getArgs(); | 606 const VarList &Args = Func->getArgs(); |
559 size_t InArgsSizeBytes = 0; | 607 size_t InArgsSizeBytes = 0; |
560 unsigned NumXmmArgs = 0; | 608 unsigned NumXmmArgs = 0; |
561 for (Variable *Arg : Args) { | 609 for (Variable *Arg : Args) { |
562 // Skip arguments passed in registers. | 610 // Skip arguments passed in registers. |
563 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | 611 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
564 ++NumXmmArgs; | 612 ++NumXmmArgs; |
565 continue; | 613 continue; |
566 } | 614 } |
567 // For esp-based frames where the allocas are done outside the prolog, the | 615 // For esp-based frames where the allocas are done outside the prolog, the |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 Context.insert<InstFakeUse>(RetValue); | 736 Context.insert<InstFakeUse>(RetValue); |
689 } | 737 } |
690 RI->setDeleted(); | 738 RI->setDeleted(); |
691 } | 739 } |
692 | 740 |
693 void TargetX8632::emitJumpTable(const Cfg *Func, | 741 void TargetX8632::emitJumpTable(const Cfg *Func, |
694 const InstJumpTable *JumpTable) const { | 742 const InstJumpTable *JumpTable) const { |
695 if (!BuildDefs::dump()) | 743 if (!BuildDefs::dump()) |
696 return; | 744 return; |
697 Ostream &Str = Ctx->getStrEmit(); | 745 Ostream &Str = Ctx->getStrEmit(); |
698 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 746 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
699 Str << "\t.section\t.rodata." << MangledName | 747 const IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 748 const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; |
| 749 Str << "\t.section\t" << Prefix << MangledName |
700 << "$jumptable,\"a\",@progbits\n"; | 750 << "$jumptable,\"a\",@progbits\n"; |
701 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 751 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
702 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | 752 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; |
703 | 753 |
704 // On X8632 pointers are 32-bit hence the use of .long | 754 // On X8632 pointers are 32-bit hence the use of .long |
705 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | 755 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) |
706 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | 756 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); |
707 Str << "\n"; | 757 Str << "\n"; |
708 } | 758 } |
709 | 759 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | 898 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); |
849 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | 899 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); |
850 | 900 |
851 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 901 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
852 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 902 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
853 } break; | 903 } break; |
854 } | 904 } |
855 } | 905 } |
856 | 906 |
857 void TargetDataX8632::lowerJumpTables() { | 907 void TargetDataX8632::lowerJumpTables() { |
| 908 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); |
858 switch (Ctx->getFlags().getOutFileType()) { | 909 switch (Ctx->getFlags().getOutFileType()) { |
859 case FT_Elf: { | 910 case FT_Elf: { |
860 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 911 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
861 for (const JumpTableData &JT : Ctx->getJumpTables()) | 912 for (const JumpTableData &JT : Ctx->getJumpTables()) |
862 Writer->writeJumpTable(JT, TargetX8632::Traits::RelFixup); | 913 Writer->writeJumpTable(JT, TargetX8632::Traits::FK_Abs, IsPIC); |
863 } break; | 914 } break; |
864 case FT_Asm: | 915 case FT_Asm: |
865 // Already emitted from Cfg | 916 // Already emitted from Cfg |
866 break; | 917 break; |
867 case FT_Iasm: { | 918 case FT_Iasm: { |
868 if (!BuildDefs::dump()) | 919 if (!BuildDefs::dump()) |
869 return; | 920 return; |
870 Ostream &Str = Ctx->getStrEmit(); | 921 Ostream &Str = Ctx->getStrEmit(); |
| 922 const IceString Prefix = IsPIC ? ".data.rel.ro." : ".rodata."; |
871 for (const JumpTableData &JT : Ctx->getJumpTables()) { | 923 for (const JumpTableData &JT : Ctx->getJumpTables()) { |
872 Str << "\t.section\t.rodata." << JT.getFunctionName() | 924 Str << "\t.section\t" << Prefix << JT.getFunctionName() |
873 << "$jumptable,\"a\",@progbits\n"; | 925 << "$jumptable,\"a\",@progbits\n"; |
874 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 926 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
875 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | 927 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; |
876 | 928 |
877 // On X8632 pointers are 32-bit hence the use of .long | 929 // On X8632 pointers are 32-bit hence the use of .long |
878 for (intptr_t TargetOffset : JT.getTargetOffsets()) | 930 for (intptr_t TargetOffset : JT.getTargetOffsets()) |
879 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | 931 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; |
880 Str << "\n"; | 932 Str << "\n"; |
881 } | 933 } |
882 } break; | 934 } break; |
883 } | 935 } |
884 } | 936 } |
885 | 937 |
886 void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars, | 938 void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars, |
887 const IceString &SectionSuffix) { | 939 const IceString &SectionSuffix) { |
| 940 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); |
888 switch (Ctx->getFlags().getOutFileType()) { | 941 switch (Ctx->getFlags().getOutFileType()) { |
889 case FT_Elf: { | 942 case FT_Elf: { |
890 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 943 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
891 Writer->writeDataSection(Vars, TargetX8632::Traits::RelFixup, | 944 Writer->writeDataSection(Vars, TargetX8632::Traits::FK_Abs, SectionSuffix, |
892 SectionSuffix); | 945 IsPIC); |
893 } break; | 946 } break; |
894 case FT_Asm: | 947 case FT_Asm: |
895 case FT_Iasm: { | 948 case FT_Iasm: { |
896 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 949 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); |
897 OstreamLocker L(Ctx); | 950 OstreamLocker L(Ctx); |
898 for (const VariableDeclaration *Var : Vars) { | 951 for (const VariableDeclaration *Var : Vars) { |
899 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 952 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
900 emitGlobal(*Var, SectionSuffix); | 953 emitGlobal(*Var, SectionSuffix); |
901 } | 954 } |
902 } | 955 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 #define X(tag, sizeLog2, align, elts, elty, str) \ | 1059 #define X(tag, sizeLog2, align, elts, elty, str) \ |
1007 static_assert(_table1_##tag == _table2_##tag, \ | 1060 static_assert(_table1_##tag == _table2_##tag, \ |
1008 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 1061 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
1009 ICETYPE_TABLE | 1062 ICETYPE_TABLE |
1010 #undef X | 1063 #undef X |
1011 } // end of namespace dummy3 | 1064 } // end of namespace dummy3 |
1012 } // end of anonymous namespace | 1065 } // end of anonymous namespace |
1013 | 1066 |
1014 } // end of namespace X8632 | 1067 } // end of namespace X8632 |
1015 } // end of namespace Ice | 1068 } // end of namespace Ice |
OLD | NEW |