Chromium Code Reviews| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 | 92 |
| 93 template <> | 93 template <> |
| 94 std::array<llvm::SmallBitVector, | 94 std::array<llvm::SmallBitVector, |
| 95 TargetX86Base<TargetX8632>::Traits::RegisterSet::Reg_NUM> | 95 TargetX86Base<TargetX8632>::Traits::RegisterSet::Reg_NUM> |
| 96 TargetX86Base<TargetX8632>::RegisterAliases = {{}}; | 96 TargetX86Base<TargetX8632>::RegisterAliases = {{}}; |
| 97 | 97 |
| 98 template <> | 98 template <> |
| 99 llvm::SmallBitVector | 99 llvm::SmallBitVector |
| 100 TargetX86Base<TargetX8632>::ScratchRegs = llvm::SmallBitVector(); | 100 TargetX86Base<TargetX8632>::ScratchRegs = llvm::SmallBitVector(); |
| 101 | 101 |
| 102 template <> | |
| 103 FixupKind TargetX86Base<TargetX8632>::PcRelFixup = | |
| 104 TargetX86Base<TargetX8632>::Traits::FK_PcRel; | |
| 105 | |
| 106 template <> | |
| 107 FixupKind TargetX86Base<TargetX8632>::AbsFixup = | |
| 108 TargetX86Base<TargetX8632>::Traits::FK_Abs; | |
| 109 | |
| 102 } // end of namespace X86Internal | 110 } // end of namespace X86Internal |
| 103 | 111 |
| 104 //------------------------------------------------------------------------------ | 112 //------------------------------------------------------------------------------ |
| 105 // __ ______ __ __ ______ ______ __ __ __ ______ | 113 // __ ______ __ __ ______ ______ __ __ __ ______ |
| 106 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ | 114 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ |
| 107 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ | 115 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ |
| 108 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ | 116 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ |
| 109 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ | 117 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ |
| 110 // | 118 // |
| 111 //------------------------------------------------------------------------------ | 119 //------------------------------------------------------------------------------ |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 case IceType_v8i1: | 230 case IceType_v8i1: |
| 223 case IceType_v16i1: | 231 case IceType_v16i1: |
| 224 case IceType_v16i8: | 232 case IceType_v16i8: |
| 225 case IceType_v8i16: | 233 case IceType_v8i16: |
| 226 case IceType_v4i32: | 234 case IceType_v4i32: |
| 227 case IceType_v4f32: | 235 case IceType_v4f32: |
| 228 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | 236 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); |
| 229 break; | 237 break; |
| 230 } | 238 } |
| 231 } | 239 } |
| 232 Operand *CallTarget = legalize(Instr->getCallTarget()); | 240 Operand *CallTarget = |
| 241 legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm | Legal_AddrAbs); | |
| 233 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 242 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| 234 if (NeedSandboxing) { | 243 if (NeedSandboxing) { |
| 235 if (llvm::isa<Constant>(CallTarget)) { | 244 if (llvm::isa<Constant>(CallTarget)) { |
| 236 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 245 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
| 237 } else { | 246 } else { |
| 238 Variable *CallTargetVar = nullptr; | 247 Variable *CallTargetVar = nullptr; |
| 239 _mov(CallTargetVar, CallTarget); | 248 _mov(CallTargetVar, CallTarget); |
| 240 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 249 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
| 241 const SizeT BundleSize = | 250 const SizeT BundleSize = |
| 242 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | 251 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 // registers (as a side effect, this gives variables a second chance at | 405 // registers (as a side effect, this gives variables a second chance at |
| 397 // physical register assignment). | 406 // physical register assignment). |
| 398 // | 407 // |
| 399 // A middle ground approach is to leverage sparsity and allocate one block of | 408 // A middle ground approach is to leverage sparsity and allocate one block of |
| 400 // space on the frame for globals (variables with multi-block lifetime), and | 409 // space on the frame for globals (variables with multi-block lifetime), and |
| 401 // one block to share for locals (single-block lifetime). | 410 // one block to share for locals (single-block lifetime). |
| 402 | 411 |
| 403 Context.init(Node); | 412 Context.init(Node); |
| 404 Context.setInsertPoint(Context.getCur()); | 413 Context.setInsertPoint(Context.getCur()); |
| 405 | 414 |
| 415 // If there is a non-deleted InstX86GetIP instruction, we need to move it to | |
|
John
2016/01/04 21:33:51
Can you move this block closer to where GetIpInst
Jim Stichnoth
2016/01/04 23:32:12
Moved the def and use closer together - with a com
| |
| 416 // the point after the stack frame has stabilized but before | |
| 417 // register-allocated in-args are copied into their home registers. | |
| 418 X86Internal::InstX86GetIP<TargetX8632> *GetIPInst = nullptr; | |
|
John
2016/01/04 21:33:51
whenever you add an X86 instruction, add it to the
Jim Stichnoth
2016/01/04 23:32:12
Done.
| |
| 419 if (Ctx->getFlags().getUseNonsfi()) { | |
| 420 for (Inst &Instr : Node->getInsts()) { | |
| 421 if (auto *GetIP = | |
| 422 llvm::dyn_cast<X86Internal::InstX86GetIP<TargetX8632>>(&Instr)) { | |
| 423 if (!Instr.isDeleted()) | |
| 424 GetIPInst = GetIP; | |
| 425 break; | |
| 426 } | |
| 427 } | |
| 428 } | |
| 429 | |
| 406 llvm::SmallBitVector CalleeSaves = | 430 llvm::SmallBitVector CalleeSaves = |
| 407 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 431 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 408 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); | 432 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); |
| 409 VarList SortedSpilledVariables, VariablesLinkedToSpillSlots; | 433 VarList SortedSpilledVariables, VariablesLinkedToSpillSlots; |
| 410 size_t GlobalsSize = 0; | 434 size_t GlobalsSize = 0; |
| 411 // If there is a separate locals area, this represents that area. Otherwise | 435 // If there is a separate locals area, this represents that area. Otherwise |
| 412 // it counts any variable not counted by GlobalsSize. | 436 // it counts any variable not counted by GlobalsSize. |
| 413 SpillAreaSizeBytes = 0; | 437 SpillAreaSizeBytes = 0; |
| 414 // If there is a separate locals area, this specifies the alignment for it. | 438 // If there is a separate locals area, this specifies the alignment for it. |
| 415 uint32_t LocalsSlotsAlignmentBytes = 0; | 439 uint32_t LocalsSlotsAlignmentBytes = 0; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 | 561 |
| 538 // Fill in stack offsets for stack args, and copy args into registers for | 562 // Fill in stack offsets for stack args, and copy args into registers for |
| 539 // those that were register-allocated. Args are pushed right to left, so | 563 // those that were register-allocated. Args are pushed right to left, so |
| 540 // Arg[0] is closest to the stack/frame pointer. | 564 // Arg[0] is closest to the stack/frame pointer. |
| 541 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 565 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
| 542 size_t BasicFrameOffset = | 566 size_t BasicFrameOffset = |
| 543 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; | 567 PreservedRegsSizeBytes + Traits::X86_RET_IP_SIZE_BYTES; |
| 544 if (!IsEbpBasedFrame) | 568 if (!IsEbpBasedFrame) |
| 545 BasicFrameOffset += SpillAreaSizeBytes; | 569 BasicFrameOffset += SpillAreaSizeBytes; |
| 546 | 570 |
| 571 // Delete any existing InstX86GetIP instruction and reinsert it here. Also, | |
| 572 // insert the call to the helper function and the spill to the stack, to | |
| 573 // simplify emission. | |
| 574 if (GetIPInst) { | |
| 575 GetIPInst->setDeleted(); | |
| 576 Variable *Dest = GetIPInst->getDest(); | |
| 577 Variable *CallDest = | |
| 578 Dest->hasReg() ? Dest | |
| 579 : getPhysicalRegister(Traits::RegisterSet::Reg_eax); | |
| 580 // Call the getIP_<reg> helper. | |
| 581 IceString RegName = Traits::getRegName(CallDest->getRegNum()); | |
| 582 Constant *CallTarget = Ctx->getConstantExternSym(H_getIP_prefix + RegName); | |
| 583 Context.insert<Traits::Insts::Call>(CallDest, CallTarget); | |
| 584 // Insert a new version of InstX86GetIP. | |
| 585 Context.insert<X86Internal::InstX86GetIP<TargetX8632>>(CallDest); | |
| 586 // Spill the register to its home stack location if necessary. | |
| 587 if (!Dest->hasReg()) { | |
| 588 _mov(Dest, CallDest); | |
| 589 } | |
| 590 } | |
| 591 | |
| 547 const VarList &Args = Func->getArgs(); | 592 const VarList &Args = Func->getArgs(); |
| 548 size_t InArgsSizeBytes = 0; | 593 size_t InArgsSizeBytes = 0; |
| 549 unsigned NumXmmArgs = 0; | 594 unsigned NumXmmArgs = 0; |
| 550 for (Variable *Arg : Args) { | 595 for (Variable *Arg : Args) { |
| 551 // Skip arguments passed in registers. | 596 // Skip arguments passed in registers. |
| 552 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { | 597 if (isVectorType(Arg->getType()) && NumXmmArgs < Traits::X86_MAX_XMM_ARGS) { |
| 553 ++NumXmmArgs; | 598 ++NumXmmArgs; |
| 554 continue; | 599 continue; |
| 555 } | 600 } |
| 556 // For esp-based frames where the allocas are done outside the prolog, the | 601 // 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... | |
| 677 Context.insert<InstFakeUse>(RetValue); | 722 Context.insert<InstFakeUse>(RetValue); |
| 678 } | 723 } |
| 679 RI->setDeleted(); | 724 RI->setDeleted(); |
| 680 } | 725 } |
| 681 | 726 |
| 682 void TargetX8632::emitJumpTable(const Cfg *Func, | 727 void TargetX8632::emitJumpTable(const Cfg *Func, |
| 683 const InstJumpTable *JumpTable) const { | 728 const InstJumpTable *JumpTable) const { |
| 684 if (!BuildDefs::dump()) | 729 if (!BuildDefs::dump()) |
| 685 return; | 730 return; |
| 686 Ostream &Str = Ctx->getStrEmit(); | 731 Ostream &Str = Ctx->getStrEmit(); |
| 687 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 732 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); |
| 688 Str << "\t.section\t.rodata." << MangledName | 733 const IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
| 734 const IceString Prefix = UseNonsfi ? ".data.rel.ro." : ".rodata."; | |
| 735 Str << "\t.section\t" << Prefix << MangledName | |
| 689 << "$jumptable,\"a\",@progbits\n"; | 736 << "$jumptable,\"a\",@progbits\n"; |
| 690 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 737 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 691 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; | 738 Str << InstJumpTable::makeName(MangledName, JumpTable->getId()) << ":"; |
| 692 | 739 |
| 693 // On X8632 pointers are 32-bit hence the use of .long | 740 // On X8632 pointers are 32-bit hence the use of .long |
| 694 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) | 741 for (SizeT I = 0; I < JumpTable->getNumTargets(); ++I) |
| 695 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); | 742 Str << "\n\t.long\t" << JumpTable->getTarget(I)->getAsmName(); |
| 696 Str << "\n"; | 743 Str << "\n"; |
| 697 } | 744 } |
| 698 | 745 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); | 884 emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx); |
| 838 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); | 885 emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx); |
| 839 | 886 |
| 840 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 887 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 841 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 888 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 842 } break; | 889 } break; |
| 843 } | 890 } |
| 844 } | 891 } |
| 845 | 892 |
| 846 void TargetDataX8632::lowerJumpTables() { | 893 void TargetDataX8632::lowerJumpTables() { |
| 894 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
| 847 switch (Ctx->getFlags().getOutFileType()) { | 895 switch (Ctx->getFlags().getOutFileType()) { |
| 848 case FT_Elf: { | 896 case FT_Elf: { |
| 849 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 897 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 850 for (const JumpTableData &JT : Ctx->getJumpTables()) | 898 for (const JumpTableData &JT : Ctx->getJumpTables()) |
| 851 Writer->writeJumpTable(JT, TargetX8632::Traits::RelFixup); | 899 Writer->writeJumpTable(JT, TargetX8632::Traits::FK_Abs, IsPIC); |
| 852 } break; | 900 } break; |
| 853 case FT_Asm: | 901 case FT_Asm: |
| 854 // Already emitted from Cfg | 902 // Already emitted from Cfg |
| 855 break; | 903 break; |
| 856 case FT_Iasm: { | 904 case FT_Iasm: { |
| 857 if (!BuildDefs::dump()) | 905 if (!BuildDefs::dump()) |
| 858 return; | 906 return; |
| 859 Ostream &Str = Ctx->getStrEmit(); | 907 Ostream &Str = Ctx->getStrEmit(); |
| 908 const IceString Prefix = IsPIC ? ".data.rel.ro." : ".rodata."; | |
| 860 for (const JumpTableData &JT : Ctx->getJumpTables()) { | 909 for (const JumpTableData &JT : Ctx->getJumpTables()) { |
| 861 Str << "\t.section\t.rodata." << JT.getFunctionName() | 910 Str << "\t.section\t" << Prefix << JT.getFunctionName() |
| 862 << "$jumptable,\"a\",@progbits\n"; | 911 << "$jumptable,\"a\",@progbits\n"; |
| 863 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; | 912 Str << "\t.align\t" << typeWidthInBytes(getPointerType()) << "\n"; |
| 864 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; | 913 Str << InstJumpTable::makeName(JT.getFunctionName(), JT.getId()) << ":"; |
| 865 | 914 |
| 866 // On X8632 pointers are 32-bit hence the use of .long | 915 // On X8632 pointers are 32-bit hence the use of .long |
| 867 for (intptr_t TargetOffset : JT.getTargetOffsets()) | 916 for (intptr_t TargetOffset : JT.getTargetOffsets()) |
| 868 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; | 917 Str << "\n\t.long\t" << JT.getFunctionName() << "+" << TargetOffset; |
| 869 Str << "\n"; | 918 Str << "\n"; |
| 870 } | 919 } |
| 871 } break; | 920 } break; |
| 872 } | 921 } |
| 873 } | 922 } |
| 874 | 923 |
| 875 void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars, | 924 void TargetDataX8632::lowerGlobals(const VariableDeclarationList &Vars, |
| 876 const IceString &SectionSuffix) { | 925 const IceString &SectionSuffix) { |
| 926 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
| 877 switch (Ctx->getFlags().getOutFileType()) { | 927 switch (Ctx->getFlags().getOutFileType()) { |
| 878 case FT_Elf: { | 928 case FT_Elf: { |
| 879 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 929 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 880 Writer->writeDataSection(Vars, TargetX8632::Traits::RelFixup, | 930 Writer->writeDataSection(Vars, TargetX8632::Traits::FK_Abs, SectionSuffix, |
| 881 SectionSuffix); | 931 IsPIC); |
| 882 } break; | 932 } break; |
| 883 case FT_Asm: | 933 case FT_Asm: |
| 884 case FT_Iasm: { | 934 case FT_Iasm: { |
| 885 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 935 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); |
| 886 OstreamLocker L(Ctx); | 936 OstreamLocker L(Ctx); |
| 887 for (const VariableDeclaration *Var : Vars) { | 937 for (const VariableDeclaration *Var : Vars) { |
| 888 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 938 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
| 889 emitGlobal(*Var, SectionSuffix); | 939 emitGlobal(*Var, SectionSuffix); |
| 890 } | 940 } |
| 891 } | 941 } |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 994 // case the high-level table has extra entries. | 1044 // case the high-level table has extra entries. |
| 995 #define X(tag, sizeLog2, align, elts, elty, str) \ | 1045 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 996 static_assert(_table1_##tag == _table2_##tag, \ | 1046 static_assert(_table1_##tag == _table2_##tag, \ |
| 997 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 1047 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
| 998 ICETYPE_TABLE | 1048 ICETYPE_TABLE |
| 999 #undef X | 1049 #undef X |
| 1000 } // end of namespace dummy3 | 1050 } // end of namespace dummy3 |
| 1001 } // end of anonymous namespace | 1051 } // end of anonymous namespace |
| 1002 | 1052 |
| 1003 } // end of namespace Ice | 1053 } // end of namespace Ice |
| OLD | NEW |