Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: src/IceTargetLoweringARM32.cpp

Issue 1665263003: Subzero. ARM32. Nonsfi. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: git pull Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 return ::Ice::ARM32::TargetDataARM32::create(Ctx); 45 return ::Ice::ARM32::TargetDataARM32::create(Ctx);
46 } 46 }
47 47
48 std::unique_ptr<::Ice::TargetHeaderLowering> 48 std::unique_ptr<::Ice::TargetHeaderLowering>
49 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) { 49 createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
50 return ::Ice::ARM32::TargetHeaderARM32::create(Ctx); 50 return ::Ice::ARM32::TargetHeaderARM32::create(Ctx);
51 } 51 }
52 52
53 void staticInit(::Ice::GlobalContext *Ctx) { 53 void staticInit(::Ice::GlobalContext *Ctx) {
54 ::Ice::ARM32::TargetARM32::staticInit(Ctx); 54 ::Ice::ARM32::TargetARM32::staticInit(Ctx);
55 if (Ctx->getFlags().getUseNonsfi()) {
56 // In nonsfi, we need to reference the _GLOBAL_OFFSET_TABLE_ for accessing
57 // globals. The GOT is an external symbol (i.e., it is not defined in the
58 // pexe) so we need to register it as such so that ELF emission won't barf
59 // on an "unknown" symbol. The GOT is added to the External symbols list
60 // here because staticInit() is invoked in a single-thread context.
61 Ctx->getConstantExternSym(::Ice::GlobalOffsetTable);
62 }
55 } 63 }
56 64
57 } // end of namespace ARM32 65 } // end of namespace ARM32
58 66
59 namespace Ice { 67 namespace Ice {
60 namespace ARM32 { 68 namespace ARM32 {
61 69
62 namespace { 70 namespace {
63 71
64 /// SizeOf is used to obtain the size of an initializer list as a constexpr 72 /// SizeOf is used to obtain the size of an initializer list as a constexpr
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset); 688 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_memset);
681 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper, 689 auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
682 NoTailCall, IsTargetHelperCall); 690 NoTailCall, IsTargetHelperCall);
683 Call->addArg(IntrinsicCall->getArg(0)); 691 Call->addArg(IntrinsicCall->getArg(0));
684 Call->addArg(ValExt); 692 Call->addArg(ValExt);
685 Call->addArg(IntrinsicCall->getArg(2)); 693 Call->addArg(IntrinsicCall->getArg(2));
686 Instr->setDeleted(); 694 Instr->setDeleted();
687 return; 695 return;
688 } 696 }
689 case Intrinsics::NaClReadTP: { 697 case Intrinsics::NaClReadTP: {
690 if (NeedSandboxing) { 698 if (SandboxingType == ST_NaCl) {
691 return; 699 return;
692 } 700 }
693 static constexpr SizeT MaxArgs = 0; 701 static constexpr SizeT MaxArgs = 0;
694 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp); 702 Operand *TargetHelper = Ctx->getConstantExternSym(H_call_read_tp);
695 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, 703 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall,
696 IsTargetHelperCall); 704 IsTargetHelperCall);
697 Instr->setDeleted(); 705 Instr->setDeleted();
698 return; 706 return;
699 } 707 }
700 case Intrinsics::Setjmp: { 708 case Intrinsics::Setjmp: {
(...skipping 22 matching lines...) Expand all
723 PostIncrLoweringContext PostIncrement(Context); 731 PostIncrLoweringContext PostIncrement(Context);
724 Inst *CurInstr = Context.getCur(); 732 Inst *CurInstr = Context.getCur();
725 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { 733 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) {
726 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); 734 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call);
727 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); 735 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes);
728 } 736 }
729 } 737 }
730 } 738 }
731 } 739 }
732 740
741 void TargetARM32::createGotPtr() {
742 if (SandboxingType != ST_Nonsfi) {
743 return;
744 }
745 GotPtr = Func->makeVariable(IceType_i32);
746 }
747
748 void TargetARM32::initGotPtr() {
749 if (SandboxingType != ST_Nonsfi) {
750 return;
751 }
752 assert(GotPtr != nullptr);
753 // TODO(jpp): explain fake def.
Jim Stichnoth 2016/02/10 06:36:00 yes, I'm curious... edit: I see, reading ahead in
John 2016/02/10 15:41:13 And I missed this comment. :-/ I wanted to leave
754 Variable *T = makeReg(IceType_i32);
755 Context.insert<InstFakeDef>(T);
756 Context.insert<InstFakeDef>(GotPtr, T);
757 }
758
759 IceString TargetARM32::createGotoffRelocation(const ConstantRelocatable *CR) {
760 const IceString CRName = CR->getName();
Jim Stichnoth 2016/02/10 06:36:00 maybe const IceString &CRName
John 2016/02/10 15:41:14 In general I don't like saving a return value by r
761 const IceString CRGotoffName =
762 "GOTOFF$" + Func->getFunctionName() + "$" + CRName;
763 if (KnownGotoffs.count(CRGotoffName) == 0) {
764 auto *Global = VariableDeclaration::create(Ctx);
765 Global->setIsConstant(true);
766 Global->setName(CRName);
767 Global->setSuppressMangling();
768
769 auto *Gotoff = VariableDeclaration::create(Ctx);
770 constexpr auto GotFixup = R_ARM_GOTOFF32;
771 Gotoff->setIsConstant(true);
772 Gotoff->setName(CRGotoffName);
773 Gotoff->setSuppressMangling();
774 Gotoff->addInitializer(VariableDeclaration::RelocInitializer::create(
775 Global, {RelocOffset::create(Ctx, 0)}, GotFixup));
776 Func->addGlobal(Gotoff);
777 KnownGotoffs.emplace(CRGotoffName);
778 }
779 return CRGotoffName;
780 }
781
782 void TargetARM32::materializeGotAddr(CfgNode *Node) {
783 if (SandboxingType != ST_Nonsfi) {
784 return;
785 }
786
787 // At first, we try to find the
788 // GotPtr = def T
789 // pseudo-instruction that we placed for defining the got ptr. That
790 // instruction is not just a place-holder for defining the GotPtr (thus
791 // keeping liveness consistent), but it is also located at a point where it is
792 // safe to materialize the got addr -- i.e., before loading parameters to
793 // registers, but after moving register parameters from their home location.
794 InstFakeDef *DefGotPtr = nullptr;
795 for (auto &Inst : Node->getInsts()) {
796 auto *FakeDef = llvm::dyn_cast<InstFakeDef>(&Inst);
797 if (FakeDef != nullptr && FakeDef->getDest() == GotPtr) {
798 DefGotPtr = FakeDef;
799 break;
800 }
801 }
802
803 if (DefGotPtr == nullptr || DefGotPtr->isDeleted()) {
804 return;
805 }
806
807 // The got addr needs to be materialized at the same point where DefGotPtr
808 // lives.
809 Context.setInsertPoint(DefGotPtr);
810 assert(DefGotPtr->getSrcSize() == 1);
811 auto *T = llvm::cast<Variable>(DefGotPtr->getSrc(0));
812 loadNamedConstantRelocatablePIC(GlobalOffsetTable, T,
813 [this, T](Variable *PC) { _add(T, PC, T); });
814 _mov(GotPtr, T);
815 DefGotPtr->setDeleted();
816 }
817
818 void TargetARM32::loadNamedConstantRelocatablePIC(
819 const IceString &Name, Variable *Register,
820 std::function<void(Variable *PC)> Finish, bool SuppressMangling) {
821 assert(SandboxingType == ST_Nonsfi);
822 // We makeReg() here instead of getPhysicalRegister() because the latter ends
823 // up creating multi-blocks temporaries that liveness fails to validate.
824 auto *PC = makeReg(IceType_i32, RegARM32::Reg_pc);
825
826 auto *AddPcReloc = RelocOffset::create(Ctx);
827 AddPcReloc->setSubtract(true);
828 auto *AddPcLabel = InstARM32Label::create(Func, this);
829 AddPcLabel->setRelocOffset(AddPcReloc);
830
831 const IceString EmitText = Name;
832 // We need a -8 in the relocation expression to account for the pc's value
833 // read by the first instruction emitted in Finish(PC).
834 auto *Imm8 = RelocOffset::create(Ctx, -8);
835
836 auto *MovwReloc = RelocOffset::create(Ctx);
837 auto *MovwLabel = InstARM32Label::create(Func, this);
838 MovwLabel->setRelocOffset(MovwReloc);
839
840 auto *MovtReloc = RelocOffset::create(Ctx);
841 auto *MovtLabel = InstARM32Label::create(Func, this);
842 MovtLabel->setRelocOffset(MovtReloc);
843
844 // The EmitString for these constant relocatables have hardcoded offsets
845 // attached to them. This could be dangerous if, e.g., we ever implemented
846 // instruction scheduling but llvm-mc currently does not support
847 //
848 // movw reg, #:lower16:(Symbol - Label - Number)
849 // movt reg, #:upper16:(Symbol - Label - Number)
850 //
851 // relocations.
852 auto *CRLower = Ctx->getConstantSym({MovwReloc, AddPcReloc, Imm8}, Name,
853 EmitText + " -16", SuppressMangling);
854 auto *CRUpper = Ctx->getConstantSym({MovtReloc, AddPcReloc, Imm8}, Name,
855 EmitText + " -12", SuppressMangling);
856
857 Context.insert(MovwLabel);
858 _movw(Register, CRLower);
859 Context.insert(MovtLabel);
860 _movt(Register, CRUpper);
861 // PC = fake-def to keep liveness consistent.
862 Context.insert<InstFakeDef>(PC);
863 Context.insert(AddPcLabel);
864 Finish(PC);
865 }
866
733 void TargetARM32::translateO2() { 867 void TargetARM32::translateO2() {
734 TimerMarker T(TimerStack::TT_O2, Func); 868 TimerMarker T(TimerStack::TT_O2, Func);
735 869
736 // TODO(stichnot): share passes with X86? 870 // TODO(stichnot): share passes with other targets?
737 // https://code.google.com/p/nativeclient/issues/detail?id=4094 871 // https://code.google.com/p/nativeclient/issues/detail?id=4094
872 if (SandboxingType == ST_Nonsfi) {
873 createGotPtr();
874 }
738 genTargetHelperCalls(); 875 genTargetHelperCalls();
739 findMaxStackOutArgsSize(); 876 findMaxStackOutArgsSize();
740 877
741 // Do not merge Alloca instructions, and lay out the stack. 878 // Do not merge Alloca instructions, and lay out the stack.
742 static constexpr bool SortAndCombineAllocas = true; 879 static constexpr bool SortAndCombineAllocas = true;
743 Func->processAllocas(SortAndCombineAllocas); 880 Func->processAllocas(SortAndCombineAllocas);
744 Func->dump("After Alloca processing"); 881 Func->dump("After Alloca processing");
745 882
746 if (!Ctx->getFlags().getPhiEdgeSplit()) { 883 if (!Ctx->getFlags().getPhiEdgeSplit()) {
747 // Lower Phi instructions. 884 // Lower Phi instructions.
(...skipping 26 matching lines...) Expand all
774 return; 911 return;
775 912
776 // TODO: It should be sufficient to use the fastest liveness calculation, 913 // TODO: It should be sufficient to use the fastest liveness calculation,
777 // i.e. livenessLightweight(). However, for some reason that slows down the 914 // i.e. livenessLightweight(). However, for some reason that slows down the
778 // rest of the translation. Investigate. 915 // rest of the translation. Investigate.
779 Func->liveness(Liveness_Basic); 916 Func->liveness(Liveness_Basic);
780 if (Func->hasError()) 917 if (Func->hasError())
781 return; 918 return;
782 Func->dump("After ARM32 address mode opt"); 919 Func->dump("After ARM32 address mode opt");
783 920
921 if (SandboxingType == ST_Nonsfi) {
922 initGotPtr();
923 }
784 Func->genCode(); 924 Func->genCode();
785 if (Func->hasError()) 925 if (Func->hasError())
786 return; 926 return;
787 Func->dump("After ARM32 codegen"); 927 Func->dump("After ARM32 codegen");
788 928
789 // Register allocation. This requires instruction renumbering and full 929 // Register allocation. This requires instruction renumbering and full
790 // liveness analysis. 930 // liveness analysis.
791 Func->renumberInstructions(); 931 Func->renumberInstructions();
792 if (Func->hasError()) 932 if (Func->hasError())
793 return; 933 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 978
839 // Nop insertion 979 // Nop insertion
840 if (Ctx->getFlags().shouldDoNopInsertion()) { 980 if (Ctx->getFlags().shouldDoNopInsertion()) {
841 Func->doNopInsertion(); 981 Func->doNopInsertion();
842 } 982 }
843 } 983 }
844 984
845 void TargetARM32::translateOm1() { 985 void TargetARM32::translateOm1() {
846 TimerMarker T(TimerStack::TT_Om1, Func); 986 TimerMarker T(TimerStack::TT_Om1, Func);
847 987
848 // TODO: share passes with X86? 988 // TODO(stichnot): share passes with other targets?
989 if (SandboxingType == ST_Nonsfi) {
990 createGotPtr();
991 }
992
849 genTargetHelperCalls(); 993 genTargetHelperCalls();
850 findMaxStackOutArgsSize(); 994 findMaxStackOutArgsSize();
851 995
852 // Do not merge Alloca instructions, and lay out the stack. 996 // Do not merge Alloca instructions, and lay out the stack.
853 static constexpr bool DontSortAndCombineAllocas = false; 997 static constexpr bool DontSortAndCombineAllocas = false;
854 Func->processAllocas(DontSortAndCombineAllocas); 998 Func->processAllocas(DontSortAndCombineAllocas);
855 Func->dump("After Alloca processing"); 999 Func->dump("After Alloca processing");
856 1000
857 Func->placePhiLoads(); 1001 Func->placePhiLoads();
858 if (Func->hasError()) 1002 if (Func->hasError())
859 return; 1003 return;
860 Func->placePhiStores(); 1004 Func->placePhiStores();
861 if (Func->hasError()) 1005 if (Func->hasError())
862 return; 1006 return;
863 Func->deletePhis(); 1007 Func->deletePhis();
864 if (Func->hasError()) 1008 if (Func->hasError())
865 return; 1009 return;
866 Func->dump("After Phi lowering"); 1010 Func->dump("After Phi lowering");
867 1011
868 Func->doArgLowering(); 1012 Func->doArgLowering();
869 1013
1014 if (SandboxingType == ST_Nonsfi) {
1015 initGotPtr();
1016 }
870 Func->genCode(); 1017 Func->genCode();
871 if (Func->hasError()) 1018 if (Func->hasError())
872 return; 1019 return;
873 Func->dump("After initial ARM32 codegen"); 1020 Func->dump("After initial ARM32 codegen");
874 1021
875 regAlloc(RAK_InfOnly); 1022 regAlloc(RAK_InfOnly);
876 if (Func->hasError()) 1023 if (Func->hasError())
877 return; 1024 return;
878 1025
879 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); 1026 copyRegAllocFromInfWeightVariable64On32(Func->getVariables());
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); 1504 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes);
1358 1505
1359 // Fill in stack offsets for stack args, and copy args into registers for 1506 // Fill in stack offsets for stack args, and copy args into registers for
1360 // those that were register-allocated. Args are pushed right to left, so 1507 // those that were register-allocated. Args are pushed right to left, so
1361 // Arg[0] is closest to the stack/frame pointer. 1508 // Arg[0] is closest to the stack/frame pointer.
1362 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); 1509 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg());
1363 size_t BasicFrameOffset = PreservedRegsSizeBytes; 1510 size_t BasicFrameOffset = PreservedRegsSizeBytes;
1364 if (!UsesFramePointer) 1511 if (!UsesFramePointer)
1365 BasicFrameOffset += SpillAreaSizeBytes; 1512 BasicFrameOffset += SpillAreaSizeBytes;
1366 1513
1514 materializeGotAddr(Node);
1515
1367 const VarList &Args = Func->getArgs(); 1516 const VarList &Args = Func->getArgs();
1368 size_t InArgsSizeBytes = 0; 1517 size_t InArgsSizeBytes = 0;
1369 TargetARM32::CallingConv CC; 1518 TargetARM32::CallingConv CC;
1370 for (Variable *Arg : Args) { 1519 for (Variable *Arg : Args) {
1371 int32_t DummyReg; 1520 int32_t DummyReg;
1372 const Type Ty = Arg->getType(); 1521 const Type Ty = Arg->getType();
1373 1522
1374 // Skip arguments passed in registers. 1523 // Skip arguments passed in registers.
1375 if (isScalarIntegerType(Ty)) { 1524 if (isScalarIntegerType(Ty)) {
1376 if (CC.argInGPR(Ty, &DummyReg)) { 1525 if (CC.argInGPR(Ty, &DummyReg)) {
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 } 3629 }
3481 3630
3482 // Allow ConstantRelocatable to be left alone as a direct call, but force 3631 // Allow ConstantRelocatable to be left alone as a direct call, but force
3483 // other constants like ConstantInteger32 to be in a register and make it an 3632 // other constants like ConstantInteger32 to be in a register and make it an
3484 // indirect call. 3633 // indirect call.
3485 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { 3634 if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
3486 CallTarget = legalize(CallTarget, Legal_Reg); 3635 CallTarget = legalize(CallTarget, Legal_Reg);
3487 } 3636 }
3488 3637
3489 // Copy arguments to be passed in registers to the appropriate registers. 3638 // Copy arguments to be passed in registers to the appropriate registers.
3639 CfgVector<Variable *> RegArgs;
3490 for (auto &FPArg : FPArgs) { 3640 for (auto &FPArg : FPArgs) {
3491 Variable *Reg = legalizeToReg(FPArg.first, FPArg.second); 3641 RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second));
3492 Context.insert<InstFakeUse>(Reg);
3493 } 3642 }
3494 for (auto &GPRArg : GPRArgs) { 3643 for (auto &GPRArg : GPRArgs) {
3495 Variable *Reg = legalizeToReg(GPRArg.first, GPRArg.second); 3644 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second));
3496 // Generate a FakeUse of register arguments so that they do not get dead 3645 }
3497 // code eliminated as a result of the FakeKill of scratch registers after 3646
3498 // the call. 3647 // Generate a FakeUse of register arguments so that they do not get dead code
3499 Context.insert<InstFakeUse>(Reg); 3648 // eliminated as a result of the FakeKill of scratch registers after the call.
3649 // These fake-uses need to be placed here to avoid argument registers from
3650 // being used during the legalizeToReg() calls above.
3651 for (auto *RegArg : RegArgs) {
3652 Context.insert<InstFakeUse>(RegArg);
3500 } 3653 }
3501 3654
3502 InstARM32Call *NewCall = 3655 InstARM32Call *NewCall =
3503 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget); 3656 Sandboxer(this, InstBundleLock::Opt_AlignToEnd).bl(ReturnReg, CallTarget);
3504 3657
3505 if (ReturnRegHi) 3658 if (ReturnRegHi)
3506 Context.insert<InstFakeDef>(ReturnRegHi); 3659 Context.insert<InstFakeDef>(ReturnRegHi);
3507 3660
3508 // Insert a register-kill pseudo instruction. 3661 // Insert a register-kill pseudo instruction.
3509 Context.insert<InstFakeKill>(NewCall); 3662 Context.insert<InstFakeKill>(NewCall);
(...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after
4834 case Intrinsics::Memcpy: { 4987 case Intrinsics::Memcpy: {
4835 llvm::report_fatal_error("memcpy should have been prelowered."); 4988 llvm::report_fatal_error("memcpy should have been prelowered.");
4836 } 4989 }
4837 case Intrinsics::Memmove: { 4990 case Intrinsics::Memmove: {
4838 llvm::report_fatal_error("memmove should have been prelowered."); 4991 llvm::report_fatal_error("memmove should have been prelowered.");
4839 } 4992 }
4840 case Intrinsics::Memset: { 4993 case Intrinsics::Memset: {
4841 llvm::report_fatal_error("memmove should have been prelowered."); 4994 llvm::report_fatal_error("memmove should have been prelowered.");
4842 } 4995 }
4843 case Intrinsics::NaClReadTP: { 4996 case Intrinsics::NaClReadTP: {
4844 if (!NeedSandboxing) { 4997 if (SandboxingType != ST_NaCl) {
4845 llvm::report_fatal_error("nacl-read-tp should have been prelowered."); 4998 llvm::report_fatal_error("nacl-read-tp should have been prelowered.");
4846 } 4999 }
4847 Variable *TP = legalizeToReg(OperandARM32Mem::create( 5000 Variable *TP = legalizeToReg(OperandARM32Mem::create(
4848 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9), 5001 Func, getPointerType(), getPhysicalRegister(RegARM32::Reg_r9),
4849 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)))); 5002 llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32))));
4850 _mov(Dest, TP); 5003 _mov(Dest, TP);
4851 return; 5004 return;
4852 } 5005 }
4853 case Intrinsics::Setjmp: { 5006 case Intrinsics::Setjmp: {
4854 llvm::report_fatal_error("setjmp should have been prelowered."); 5007 llvm::report_fatal_error("setjmp should have been prelowered.");
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
5494 _cmp(Src0Var, Value); 5647 _cmp(Src0Var, Value);
5495 _br(Instr->getLabel(I), CondARM32::EQ); 5648 _br(Instr->getLabel(I), CondARM32::EQ);
5496 } 5649 }
5497 _br(Instr->getLabelDefault()); 5650 _br(Instr->getLabelDefault());
5498 } 5651 }
5499 5652
5500 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) { 5653 void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) {
5501 _trap(); 5654 _trap();
5502 } 5655 }
5503 5656
5657 namespace {
5658 // Returns whether Opnd needs the GOT address. Currently, ConstantRelocatables,
5659 // and fp constants will need access to the GOT address.
5660 bool operandNeedsGot(const Operand *Opnd) {
5661 return llvm::isa<ConstantRelocatable>(Opnd) ||
5662 llvm::isa<ConstantFloat>(Opnd) || llvm::isa<ConstantDouble>(Opnd);
Jim Stichnoth 2016/02/10 06:36:00 Can/should this be more precise? I thought that +
John 2016/02/10 15:41:14 You spotted my laziness. Done.
5663 }
5664
5665 // Returns whether Phi needs the GOT address (which it does if any of its
5666 // operands needs the GOT address.)
5667 bool phiNeedsGot(const InstPhi *Phi) {
5668 if (Phi->isDeleted()) {
5669 return false;
5670 }
5671
5672 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) {
5673 if (operandNeedsGot(Phi->getSrc(I))) {
5674 return true;
5675 }
5676 }
5677
5678 return false;
5679 }
5680
5681 // Returns whether **any** phi in Node needs the GOT address.
5682 bool anyPhiInNodeNeedsGot(CfgNode *Node) {
5683 for (auto &Inst : Node->getPhis()) {
5684 if (phiNeedsGot(llvm::cast<InstPhi>(&Inst))) {
5685 return true;
5686 }
5687 }
5688 return false;
5689 }
5690
5691 } // end of anonymous namespace
5692
5504 void TargetARM32::prelowerPhis() { 5693 void TargetARM32::prelowerPhis() {
5505 PhiLowering::prelowerPhis32Bit<TargetARM32>(this, Context.getNode(), Func); 5694 CfgNode *Node = Context.getNode();
5695
5696 if (SandboxingType == ST_Nonsfi) {
5697 assert(GotPtr != nullptr);
5698 if (anyPhiInNodeNeedsGot(Node)) {
5699 // If any phi instruction needs the GOT address, we place a
5700 // fake-use GotPtr
5701 // in Node to prevent the GotPtr's initialization from being dead code
5702 // eliminated.
5703 Node->getInsts().push_front(InstFakeUse::create(Func, GotPtr));
5704 }
5705 }
5706
5707 PhiLowering::prelowerPhis32Bit(this, Node, Func);
5506 } 5708 }
5507 5709
5508 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) { 5710 Variable *TargetARM32::makeVectorOfZeros(Type Ty, int32_t RegNum) {
5509 Variable *Reg = makeReg(Ty, RegNum); 5711 Variable *Reg = makeReg(Ty, RegNum);
5510 Context.insert<InstFakeDef>(Reg); 5712 Context.insert<InstFakeDef>(Reg);
5511 UnimplementedError(Func->getContext()->getFlags()); 5713 UnimplementedError(Func->getContext()->getFlags());
5512 return Reg; 5714 return Reg;
5513 } 5715 }
5514 5716
5515 // Helper for legalize() to emit the right code to lower an operand to a 5717 // Helper for legalize() to emit the right code to lower an operand to a
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
5657 uint32_t UpperBits = (Value >> 16) & 0xFFFF; 5859 uint32_t UpperBits = (Value >> 16) & 0xFFFF;
5658 _movw(Reg, 5860 _movw(Reg,
5659 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32); 5861 UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32);
5660 if (UpperBits != 0) { 5862 if (UpperBits != 0) {
5661 _movt(Reg, Ctx->getConstantInt32(UpperBits)); 5863 _movt(Reg, Ctx->getConstantInt32(UpperBits));
5662 } 5864 }
5663 return Reg; 5865 return Reg;
5664 } 5866 }
5665 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { 5867 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) {
5666 Variable *Reg = makeReg(Ty, RegNum); 5868 Variable *Reg = makeReg(Ty, RegNum);
5667 _movw(Reg, C); 5869 if (SandboxingType != ST_Nonsfi) {
5668 _movt(Reg, C); 5870 _movw(Reg, C);
5871 _movt(Reg, C);
5872 } else {
5873 auto *GotAddr = legalizeToReg(GotPtr);
5874 const IceString CGotoffName = createGotoffRelocation(C);
5875 loadNamedConstantRelocatablePIC(
5876 CGotoffName, Reg, [this, Reg](Variable *PC) {
5877 _ldr(Reg, OperandARM32Mem::create(Func, IceType_i32, PC, Reg));
5878 });
5879 _add(Reg, GotAddr, Reg);
5880 }
5669 return Reg; 5881 return Reg;
5670 } else { 5882 } else {
5671 assert(isScalarFloatingType(Ty)); 5883 assert(isScalarFloatingType(Ty));
5672 uint32_t ModifiedImm; 5884 uint32_t ModifiedImm;
5673 if (OperandARM32FlexFpImm::canHoldImm(From, &ModifiedImm)) { 5885 if (OperandARM32FlexFpImm::canHoldImm(From, &ModifiedImm)) {
5674 Variable *T = makeReg(Ty, RegNum); 5886 Variable *T = makeReg(Ty, RegNum);
5675 _mov(T, 5887 _mov(T,
5676 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); 5888 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm));
5677 return T; 5889 return T;
5678 } 5890 }
5679 5891
5680 if (Ty == IceType_f64 && isFloatingPointZero(From)) { 5892 if (Ty == IceType_f64 && isFloatingPointZero(From)) {
5681 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 5893 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32
5682 // because ARM does not have a veor instruction with S registers. 5894 // because ARM does not have a veor instruction with S registers.
5683 Variable *T = makeReg(IceType_f64, RegNum); 5895 Variable *T = makeReg(IceType_f64, RegNum);
5684 Context.insert<InstFakeDef>(T); 5896 Context.insert<InstFakeDef>(T);
5685 _veor(T, T, T); 5897 _veor(T, T, T);
5686 return T; 5898 return T;
5687 } 5899 }
5688 5900
5689 // Load floats/doubles from literal pool. 5901 // Load floats/doubles from literal pool.
5690 std::string Buffer; 5902 std::string Buffer;
5691 llvm::raw_string_ostream StrBuf(Buffer); 5903 llvm::raw_string_ostream StrBuf(Buffer);
5692 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); 5904 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx);
5693 llvm::cast<Constant>(From)->setShouldBePooled(true); 5905 llvm::cast<Constant>(From)->setShouldBePooled(true);
5694 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); 5906 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
5695 Variable *BaseReg = makeReg(getPointerType()); 5907 Variable *BaseReg = nullptr;
5696 _movw(BaseReg, Offset); 5908 if (SandboxingType == ST_Nonsfi) {
5697 _movt(BaseReg, Offset); 5909 // vldr does not support the [base, index] addressing mode, so we need
5910 // to legalize Offset to a register. Otherwise, we could simply
5911 // vldr dest, [got, reg(Offset)]
5912 BaseReg = legalizeToReg(Offset);
5913 } else {
5914 BaseReg = makeReg(getPointerType());
5915 _movw(BaseReg, Offset);
5916 _movt(BaseReg, Offset);
5917 }
5698 From = formMemoryOperand(BaseReg, Ty); 5918 From = formMemoryOperand(BaseReg, Ty);
5699 return copyToReg(From, RegNum); 5919 return copyToReg(From, RegNum);
5700 } 5920 }
5701 } 5921 }
5702 5922
5703 if (auto *Var = llvm::dyn_cast<Variable>(From)) { 5923 if (auto *Var = llvm::dyn_cast<Variable>(From)) {
5704 if (Var->isRematerializable()) { 5924 if (Var->isRematerializable()) {
5705 if (Allowed & Legal_Rematerializable) { 5925 if (Allowed & Legal_Rematerializable) {
5706 return From; 5926 return From;
5707 } 5927 }
(...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after
6571 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; 6791 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n";
6572 } 6792 }
6573 6793
6574 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; 6794 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM];
6575 llvm::SmallBitVector 6795 llvm::SmallBitVector
6576 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; 6796 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM];
6577 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; 6797 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
6578 6798
6579 } // end of namespace ARM32 6799 } // end of namespace ARM32
6580 } // end of namespace Ice 6800 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698