OLD | NEW |
---|---|
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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 continue; | 226 continue; |
227 } | 227 } |
228 Lo->setRegNum(FirstReg); | 228 Lo->setRegNum(FirstReg); |
229 Lo->setMustHaveReg(); | 229 Lo->setMustHaveReg(); |
230 Hi->setRegNum(FirstReg + 1); | 230 Hi->setRegNum(FirstReg + 1); |
231 Hi->setMustHaveReg(); | 231 Hi->setMustHaveReg(); |
232 } | 232 } |
233 } | 233 } |
234 } // end of anonymous namespace | 234 } // end of anonymous namespace |
235 | 235 |
236 uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) { | |
237 TargetARM32::CallingConv CC; | |
238 size_t OutArgsSizeBytes = 0; | |
239 for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) { | |
240 Operand *Arg = legalizeUndef(Call->getArg(i)); | |
241 Type Ty = Arg->getType(); | |
242 if (Ty == IceType_i64) { | |
243 std::pair<int32_t, int32_t> Regs; | |
244 if (CC.I64InRegs(&Regs)) { | |
245 continue; | |
246 } | |
247 } else if (isVectorType(Ty) || isFloatingType(Ty)) { | |
248 int32_t Reg; | |
249 if (CC.FPInReg(Ty, &Reg)) { | |
250 continue; | |
251 } | |
252 } else { | |
253 assert(Ty == IceType_i32); | |
254 int32_t Reg; | |
255 if (CC.I32InReg(&Reg)) { | |
256 continue; | |
257 } | |
258 } | |
259 | |
260 OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty); | |
261 OutArgsSizeBytes += typeWidthInBytesOnStack(Ty); | |
262 } | |
263 | |
264 return applyStackAlignment(OutArgsSizeBytes); | |
265 } | |
266 | |
267 void TargetARM32::findMaxStackOutArgsSize() { | |
268 // MinNeededOutArgsBytes should be updated if the Target ever creates an | |
Jim Stichnoth
2015/11/22 04:09:43
s/an/a/
at least for the way I pronounce "high"
John
2015/11/23 18:54:10
Done.
| |
269 // high-level InstCall that requires more stack bytes. | |
270 constexpr size_t MinNeededOutArgsBytes = 0; | |
271 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; | |
272 for (CfgNode *Node : Func->getNodes()) { | |
273 Context.init(Node); | |
274 while (!Context.atEnd()) { | |
275 PostIncrLoweringContext PostIncrement(Context); | |
276 Inst *CurInstr = Context.getCur(); | |
277 if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) { | |
278 SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call); | |
279 MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes); | |
280 } | |
281 } | |
282 } | |
283 } | |
284 | |
236 void TargetARM32::translateO2() { | 285 void TargetARM32::translateO2() { |
237 TimerMarker T(TimerStack::TT_O2, Func); | 286 TimerMarker T(TimerStack::TT_O2, Func); |
238 | 287 |
239 // TODO(stichnot): share passes with X86? | 288 // TODO(stichnot): share passes with X86? |
240 // https://code.google.com/p/nativeclient/issues/detail?id=4094 | 289 // https://code.google.com/p/nativeclient/issues/detail?id=4094 |
241 genTargetHelperCalls(); | 290 genTargetHelperCalls(); |
291 findMaxStackOutArgsSize(); | |
242 | 292 |
243 // Do not merge Alloca instructions, and lay out the stack. | 293 // Do not merge Alloca instructions, and lay out the stack. |
244 static constexpr bool SortAndCombineAllocas = false; | 294 static constexpr bool SortAndCombineAllocas = false; |
245 Func->processAllocas(SortAndCombineAllocas); | 295 Func->processAllocas(SortAndCombineAllocas); |
246 Func->dump("After Alloca processing"); | 296 Func->dump("After Alloca processing"); |
247 | 297 |
248 if (!Ctx->getFlags().getPhiEdgeSplit()) { | 298 if (!Ctx->getFlags().getPhiEdgeSplit()) { |
249 // Lower Phi instructions. | 299 // Lower Phi instructions. |
250 Func->placePhiLoads(); | 300 Func->placePhiLoads(); |
251 if (Func->hasError()) | 301 if (Func->hasError()) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 if (Ctx->getFlags().shouldDoNopInsertion()) { | 389 if (Ctx->getFlags().shouldDoNopInsertion()) { |
340 Func->doNopInsertion(); | 390 Func->doNopInsertion(); |
341 } | 391 } |
342 } | 392 } |
343 | 393 |
344 void TargetARM32::translateOm1() { | 394 void TargetARM32::translateOm1() { |
345 TimerMarker T(TimerStack::TT_Om1, Func); | 395 TimerMarker T(TimerStack::TT_Om1, Func); |
346 | 396 |
347 // TODO: share passes with X86? | 397 // TODO: share passes with X86? |
348 genTargetHelperCalls(); | 398 genTargetHelperCalls(); |
399 findMaxStackOutArgsSize(); | |
349 | 400 |
350 // Do not merge Alloca instructions, and lay out the stack. | 401 // Do not merge Alloca instructions, and lay out the stack. |
351 static constexpr bool SortAndCombineAllocas = false; | 402 static constexpr bool SortAndCombineAllocas = false; |
352 Func->processAllocas(SortAndCombineAllocas); | 403 Func->processAllocas(SortAndCombineAllocas); |
353 Func->dump("After Alloca processing"); | 404 Func->dump("After Alloca processing"); |
354 | 405 |
355 Func->placePhiLoads(); | 406 Func->placePhiLoads(); |
356 if (Func->hasError()) | 407 if (Func->hasError()) |
357 return; | 408 return; |
358 Func->placePhiStores(); | 409 Func->placePhiStores(); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 return; | 517 return; |
467 } | 518 } |
468 if (Var->mustHaveReg()) { | 519 if (Var->mustHaveReg()) { |
469 llvm::report_fatal_error( | 520 llvm::report_fatal_error( |
470 "Infinite-weight Variable has no register assigned"); | 521 "Infinite-weight Variable has no register assigned"); |
471 } | 522 } |
472 int32_t Offset = Var->getStackOffset(); | 523 int32_t Offset = Var->getStackOffset(); |
473 int32_t BaseRegNum = Var->getBaseRegNum(); | 524 int32_t BaseRegNum = Var->getBaseRegNum(); |
474 if (BaseRegNum == Variable::NoRegister) { | 525 if (BaseRegNum == Variable::NoRegister) { |
475 BaseRegNum = getFrameOrStackReg(); | 526 BaseRegNum = getFrameOrStackReg(); |
476 if (!hasFramePointer()) | |
477 Offset += getStackAdjustment(); | |
478 } | 527 } |
479 const Type VarTy = Var->getType(); | 528 const Type VarTy = Var->getType(); |
480 Str << "[" << getRegName(BaseRegNum, VarTy); | 529 Str << "[" << getRegName(BaseRegNum, VarTy); |
481 if (Offset != 0) { | 530 if (Offset != 0) { |
482 Str << ", " << getConstantPrefix() << Offset; | 531 Str << ", " << getConstantPrefix() << Offset; |
483 } | 532 } |
484 Str << "]"; | 533 Str << "]"; |
485 } | 534 } |
486 | 535 |
487 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { | 536 bool TargetARM32::CallingConv::I64InRegs(std::pair<int32_t, int32_t> *Regs) { |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 // | 2. padding | | 712 // | 2. padding | |
664 // +------------------------+ <--- FramePointer (if used) | 713 // +------------------------+ <--- FramePointer (if used) |
665 // | 3. global spill area | | 714 // | 3. global spill area | |
666 // +------------------------+ | 715 // +------------------------+ |
667 // | 4. padding | | 716 // | 4. padding | |
668 // +------------------------+ | 717 // +------------------------+ |
669 // | 5. local spill area | | 718 // | 5. local spill area | |
670 // +------------------------+ | 719 // +------------------------+ |
671 // | 6. padding | | 720 // | 6. padding | |
672 // +------------------------+ | 721 // +------------------------+ |
673 // | 7. allocas | | 722 // | 7. allocas (variable) | |
723 // +------------------------+ | |
724 // | 8. padding | | |
725 // +------------------------+ | |
726 // | 9. out args | | |
674 // +------------------------+ <--- StackPointer | 727 // +------------------------+ <--- StackPointer |
675 // | 728 // |
676 // The following variables record the size in bytes of the given areas: | 729 // The following variables record the size in bytes of the given areas: |
677 // * PreservedRegsSizeBytes: area 1 | 730 // * PreservedRegsSizeBytes: area 1 |
678 // * SpillAreaPaddingBytes: area 2 | 731 // * SpillAreaPaddingBytes: area 2 |
679 // * GlobalsSize: area 3 | 732 // * GlobalsSize: area 3 |
680 // * GlobalsAndSubsequentPaddingSize: areas 3 - 4 | 733 // * GlobalsAndSubsequentPaddingSize: areas 3 - 4 |
681 // * LocalsSpillAreaSize: area 5 | 734 // * LocalsSpillAreaSize: area 5 |
682 // * SpillAreaSizeBytes: areas 2 - 6 | 735 // * SpillAreaSizeBytes: areas 2 - 6, and 9 |
736 // * MaxOutArgsSizeBytes: area 9 | |
737 // | |
683 // Determine stack frame offsets for each Variable without a register | 738 // Determine stack frame offsets for each Variable without a register |
684 // assignment. This can be done as one variable per stack slot. Or, do | 739 // assignment. This can be done as one variable per stack slot. Or, do |
685 // coalescing by running the register allocator again with an infinite set of | 740 // coalescing by running the register allocator again with an infinite set of |
686 // registers (as a side effect, this gives variables a second chance at | 741 // registers (as a side effect, this gives variables a second chance at |
687 // physical register assignment). | 742 // physical register assignment). |
688 // | 743 // |
689 // A middle ground approach is to leverage sparsity and allocate one block of | 744 // A middle ground approach is to leverage sparsity and allocate one block of |
690 // space on the frame for globals (variables with multi-block lifetime), and | 745 // space on the frame for globals (variables with multi-block lifetime), and |
691 // one block to share for locals (single-block lifetime). | 746 // one block to share for locals (single-block lifetime). |
692 | 747 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | 833 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
779 uint32_t SpillAreaPaddingBytes = 0; | 834 uint32_t SpillAreaPaddingBytes = 0; |
780 uint32_t LocalsSlotsPaddingBytes = 0; | 835 uint32_t LocalsSlotsPaddingBytes = 0; |
781 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes, | 836 alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes, |
782 GlobalsSize, LocalsSlotsAlignmentBytes, | 837 GlobalsSize, LocalsSlotsAlignmentBytes, |
783 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes); | 838 &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes); |
784 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; | 839 SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes; |
785 uint32_t GlobalsAndSubsequentPaddingSize = | 840 uint32_t GlobalsAndSubsequentPaddingSize = |
786 GlobalsSize + LocalsSlotsPaddingBytes; | 841 GlobalsSize + LocalsSlotsPaddingBytes; |
787 | 842 |
788 // Align SP if necessary. | 843 // Adds the out args space to the stack, and align SP if necessary. |
789 if (NeedsStackAlignment) { | 844 if (!NeedsStackAlignment) { |
845 SpillAreaSizeBytes += MaxOutArgsSizeBytes; | |
846 } else { | |
790 uint32_t StackOffset = PreservedRegsSizeBytes; | 847 uint32_t StackOffset = PreservedRegsSizeBytes; |
791 uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes); | 848 uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes); |
849 StackSize = applyStackAlignment(StackSize + MaxOutArgsSizeBytes); | |
792 SpillAreaSizeBytes = StackSize - StackOffset; | 850 SpillAreaSizeBytes = StackSize - StackOffset; |
793 } | 851 } |
794 | 852 |
795 // Generate "sub sp, SpillAreaSizeBytes" | 853 // Generate "sub sp, SpillAreaSizeBytes" |
796 if (SpillAreaSizeBytes) { | 854 if (SpillAreaSizeBytes) { |
797 // Use the scratch register if needed to legalize the immediate. | 855 // Use the scratch register if needed to legalize the immediate. |
798 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), | 856 Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes), |
799 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 857 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
800 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 858 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
801 _sub(SP, SP, SubAmount); | 859 _sub(SP, SP, SubAmount); |
802 } | 860 } |
803 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); | 861 Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes); |
804 | 862 |
805 resetStackAdjustment(); | |
806 | |
807 // Fill in stack offsets for stack args, and copy args into registers for | 863 // Fill in stack offsets for stack args, and copy args into registers for |
808 // those that were register-allocated. Args are pushed right to left, so | 864 // those that were register-allocated. Args are pushed right to left, so |
809 // Arg[0] is closest to the stack/frame pointer. | 865 // Arg[0] is closest to the stack/frame pointer. |
810 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); | 866 Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg()); |
811 size_t BasicFrameOffset = PreservedRegsSizeBytes; | 867 size_t BasicFrameOffset = PreservedRegsSizeBytes; |
812 if (!UsesFramePointer) | 868 if (!UsesFramePointer) |
813 BasicFrameOffset += SpillAreaSizeBytes; | 869 BasicFrameOffset += SpillAreaSizeBytes; |
814 | 870 |
815 const VarList &Args = Func->getArgs(); | 871 const VarList &Args = Func->getArgs(); |
816 size_t InArgsSizeBytes = 0; | 872 size_t InArgsSizeBytes = 0; |
(...skipping 23 matching lines...) Expand all Loading... | |
840 UsesFramePointer); | 896 UsesFramePointer); |
841 this->HasComputedFrame = true; | 897 this->HasComputedFrame = true; |
842 | 898 |
843 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 899 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
844 OstreamLocker _(Func->getContext()); | 900 OstreamLocker _(Func->getContext()); |
845 Ostream &Str = Func->getContext()->getStrDump(); | 901 Ostream &Str = Func->getContext()->getStrDump(); |
846 | 902 |
847 Str << "Stack layout:\n"; | 903 Str << "Stack layout:\n"; |
848 uint32_t SPAdjustmentPaddingSize = | 904 uint32_t SPAdjustmentPaddingSize = |
849 SpillAreaSizeBytes - LocalsSpillAreaSize - | 905 SpillAreaSizeBytes - LocalsSpillAreaSize - |
850 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; | 906 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes - |
907 MaxOutArgsSizeBytes; | |
851 Str << " in-args = " << InArgsSizeBytes << " bytes\n" | 908 Str << " in-args = " << InArgsSizeBytes << " bytes\n" |
852 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" | 909 << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n" |
853 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" | 910 << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n" |
854 << " globals spill area = " << GlobalsSize << " bytes\n" | 911 << " globals spill area = " << GlobalsSize << " bytes\n" |
855 << " globals-locals spill areas intermediate padding = " | 912 << " globals-locals spill areas intermediate padding = " |
856 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" | 913 << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n" |
857 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" | 914 << " locals spill area = " << LocalsSpillAreaSize << " bytes\n" |
858 << " SP alignment padding = " << SPAdjustmentPaddingSize << " bytes\n"; | 915 << " SP alignment padding = " << SPAdjustmentPaddingSize << " bytes\n"; |
859 | 916 |
860 Str << "Stack details:\n" | 917 Str << "Stack details:\n" |
861 << " SP adjustment = " << SpillAreaSizeBytes << " bytes\n" | 918 << " SP adjustment = " << SpillAreaSizeBytes << " bytes\n" |
862 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" | 919 << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n" |
920 << " outgoing args size = " << MaxOutArgsSizeBytes << " bytes\n" | |
863 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes | 921 << " locals spill area alignment = " << LocalsSlotsAlignmentBytes |
864 << " bytes\n" | 922 << " bytes\n" |
865 << " is FP based = " << UsesFramePointer << "\n"; | 923 << " is FP based = " << UsesFramePointer << "\n"; |
866 } | 924 } |
867 } | 925 } |
868 | 926 |
869 void TargetARM32::addEpilog(CfgNode *Node) { | 927 void TargetARM32::addEpilog(CfgNode *Node) { |
870 InstList &Insts = Node->getInsts(); | 928 InstList &Insts = Node->getInsts(); |
871 InstList::reverse_iterator RI, E; | 929 InstList::reverse_iterator RI, E; |
872 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { | 930 for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
949 _ret(LR, RetValue); | 1007 _ret(LR, RetValue); |
950 _bundle_unlock(); | 1008 _bundle_unlock(); |
951 RI->setDeleted(); | 1009 RI->setDeleted(); |
952 } | 1010 } |
953 | 1011 |
954 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { | 1012 bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const { |
955 constexpr bool ZeroExt = false; | 1013 constexpr bool ZeroExt = false; |
956 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); | 1014 return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset); |
957 } | 1015 } |
958 | 1016 |
959 Variable *TargetARM32::newBaseRegister(int32_t OriginalOffset, | 1017 Variable *TargetARM32::newBaseRegister(int32_t Offset, Variable *OrigBaseReg) { |
960 int32_t StackAdjust, | |
961 Variable *OrigBaseReg) { | |
962 int32_t Offset = OriginalOffset + StackAdjust; | |
963 // Legalize will likely need a movw/movt combination, but if the top bits are | 1018 // Legalize will likely need a movw/movt combination, but if the top bits are |
964 // all 0 from negating the offset and subtracting, we could use that instead. | 1019 // all 0 from negating the offset and subtracting, we could use that instead. |
965 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; | 1020 bool ShouldSub = (-Offset & 0xFFFF0000) == 0; |
966 if (ShouldSub) | 1021 if (ShouldSub) |
967 Offset = -Offset; | 1022 Offset = -Offset; |
968 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), | 1023 Operand *OffsetVal = legalize(Ctx->getConstantInt32(Offset), |
969 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1024 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
970 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); | 1025 Variable *ScratchReg = makeReg(IceType_i32, getReservedTmpReg()); |
971 if (ShouldSub) | 1026 if (ShouldSub) |
972 _sub(ScratchReg, OrigBaseReg, OffsetVal); | 1027 _sub(ScratchReg, OrigBaseReg, OffsetVal); |
973 else | 1028 else |
974 _add(ScratchReg, OrigBaseReg, OffsetVal); | 1029 _add(ScratchReg, OrigBaseReg, OffsetVal); |
975 return ScratchReg; | 1030 return ScratchReg; |
976 } | 1031 } |
977 | 1032 |
978 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, | 1033 OperandARM32Mem *TargetARM32::createMemOperand(Type Ty, int32_t Offset, |
979 int32_t StackAdjust, | |
980 Variable *OrigBaseReg, | 1034 Variable *OrigBaseReg, |
981 Variable **NewBaseReg, | 1035 Variable **NewBaseReg, |
982 int32_t *NewBaseOffset) { | 1036 int32_t *NewBaseOffset) { |
983 if (isLegalMemOffset(Ty, Offset + StackAdjust)) { | 1037 if (isLegalMemOffset(Ty, Offset)) { |
984 return OperandARM32Mem::create( | 1038 return OperandARM32Mem::create( |
985 Func, Ty, OrigBaseReg, llvm::cast<ConstantInteger32>( | 1039 Func, Ty, OrigBaseReg, |
986 Ctx->getConstantInt32(Offset + StackAdjust)), | 1040 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset)), |
987 OperandARM32Mem::Offset); | 1041 OperandARM32Mem::Offset); |
988 } | 1042 } |
989 | 1043 |
990 if (*NewBaseReg == nullptr) { | 1044 if (*NewBaseReg == nullptr) { |
991 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 1045 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); |
992 *NewBaseOffset = Offset + StackAdjust; | 1046 *NewBaseOffset = Offset; |
993 } | 1047 } |
994 | 1048 |
995 int32_t OffsetDiff = Offset + StackAdjust - *NewBaseOffset; | 1049 int32_t OffsetDiff = Offset - *NewBaseOffset; |
996 if (!isLegalMemOffset(Ty, OffsetDiff)) { | 1050 if (!isLegalMemOffset(Ty, OffsetDiff)) { |
997 *NewBaseReg = newBaseRegister(Offset, StackAdjust, OrigBaseReg); | 1051 *NewBaseReg = newBaseRegister(Offset, OrigBaseReg); |
998 *NewBaseOffset = Offset + StackAdjust; | 1052 *NewBaseOffset = Offset; |
999 OffsetDiff = 0; | 1053 OffsetDiff = 0; |
1000 } | 1054 } |
1001 | 1055 |
1002 return OperandARM32Mem::create( | 1056 return OperandARM32Mem::create( |
1003 Func, Ty, *NewBaseReg, | 1057 Func, Ty, *NewBaseReg, |
1004 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), | 1058 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetDiff)), |
1005 OperandARM32Mem::Offset); | 1059 OperandARM32Mem::Offset); |
1006 } | 1060 } |
1007 | 1061 |
1008 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, int32_t StackAdjust, | 1062 void TargetARM32::legalizeMov(InstARM32Mov *MovInstr, Variable *OrigBaseReg, |
1009 Variable *OrigBaseReg, Variable **NewBaseReg, | 1063 Variable **NewBaseReg, int32_t *NewBaseOffset) { |
1010 int32_t *NewBaseOffset) { | |
1011 Variable *Dest = MovInstr->getDest(); | 1064 Variable *Dest = MovInstr->getDest(); |
1012 assert(Dest != nullptr); | 1065 assert(Dest != nullptr); |
1013 Type DestTy = Dest->getType(); | 1066 Type DestTy = Dest->getType(); |
1014 assert(DestTy != IceType_i64); | 1067 assert(DestTy != IceType_i64); |
1015 | 1068 |
1016 Operand *Src = MovInstr->getSrc(0); | 1069 Operand *Src = MovInstr->getSrc(0); |
1017 Type SrcTy = Src->getType(); | 1070 Type SrcTy = Src->getType(); |
1018 (void)SrcTy; | 1071 (void)SrcTy; |
1019 assert(SrcTy != IceType_i64); | 1072 assert(SrcTy != IceType_i64); |
1020 | 1073 |
1021 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1074 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
1022 return; | 1075 return; |
1023 | 1076 |
1024 bool Legalized = false; | 1077 bool Legalized = false; |
1025 if (!Dest->hasReg()) { | 1078 if (!Dest->hasReg()) { |
1026 auto *const SrcR = llvm::cast<Variable>(Src); | 1079 auto *const SrcR = llvm::cast<Variable>(Src); |
1027 assert(SrcR->hasReg()); | 1080 assert(SrcR->hasReg()); |
1028 const int32_t Offset = Dest->getStackOffset(); | 1081 const int32_t Offset = Dest->getStackOffset(); |
1029 // This is a _mov(Mem(), Variable), i.e., a store. | 1082 // This is a _mov(Mem(), Variable), i.e., a store. |
1030 _str(SrcR, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, | 1083 _str(SrcR, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, |
1031 NewBaseReg, NewBaseOffset), | 1084 NewBaseOffset), |
1032 MovInstr->getPredicate()); | 1085 MovInstr->getPredicate()); |
1033 // _str() does not have a Dest, so we add a fake-def(Dest). | 1086 // _str() does not have a Dest, so we add a fake-def(Dest). |
1034 Context.insert(InstFakeDef::create(Func, Dest)); | 1087 Context.insert(InstFakeDef::create(Func, Dest)); |
1035 Legalized = true; | 1088 Legalized = true; |
1036 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1089 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
1037 if (!Var->hasReg()) { | 1090 if (!Var->hasReg()) { |
1038 const int32_t Offset = Var->getStackOffset(); | 1091 const int32_t Offset = Var->getStackOffset(); |
1039 _ldr(Dest, createMemOperand(DestTy, Offset, StackAdjust, OrigBaseReg, | 1092 _ldr(Dest, createMemOperand(DestTy, Offset, OrigBaseReg, NewBaseReg, |
1040 NewBaseReg, NewBaseOffset), | 1093 NewBaseOffset), |
1041 MovInstr->getPredicate()); | 1094 MovInstr->getPredicate()); |
1042 Legalized = true; | 1095 Legalized = true; |
1043 } | 1096 } |
1044 } | 1097 } |
1045 | 1098 |
1046 if (Legalized) { | 1099 if (Legalized) { |
1047 if (MovInstr->isDestRedefined()) { | 1100 if (MovInstr->isDestRedefined()) { |
1048 _set_dest_redefined(); | 1101 _set_dest_redefined(); |
1049 } | 1102 } |
1050 MovInstr->setDeleted(); | 1103 MovInstr->setDeleted(); |
1051 } | 1104 } |
1052 } | 1105 } |
1053 | 1106 |
1054 void TargetARM32::legalizeStackSlots() { | 1107 void TargetARM32::legalizeStackSlots() { |
1055 // If a stack variable's frame offset doesn't fit, convert from: | 1108 // If a stack variable's frame offset doesn't fit, convert from: |
1056 // ldr X, OFF[SP] | 1109 // ldr X, OFF[SP] |
1057 // to: | 1110 // to: |
1058 // movw/movt TMP, OFF_PART | 1111 // movw/movt TMP, OFF_PART |
1059 // add TMP, TMP, SP | 1112 // add TMP, TMP, SP |
1060 // ldr X, OFF_MORE[TMP] | 1113 // ldr X, OFF_MORE[TMP] |
1061 // | 1114 // |
1062 // This is safe because we have reserved TMP, and add for ARM does not | 1115 // This is safe because we have reserved TMP, and add for ARM does not |
1063 // clobber the flags register. | 1116 // clobber the flags register. |
1064 Func->dump("Before legalizeStackSlots"); | 1117 Func->dump("Before legalizeStackSlots"); |
1065 assert(hasComputedFrame()); | 1118 assert(hasComputedFrame()); |
1066 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); | 1119 Variable *OrigBaseReg = getPhysicalRegister(getFrameOrStackReg()); |
1067 int32_t StackAdjust = 0; | |
1068 // Do a fairly naive greedy clustering for now. Pick the first stack slot | 1120 // Do a fairly naive greedy clustering for now. Pick the first stack slot |
1069 // that's out of bounds and make a new base reg using the architecture's temp | 1121 // that's out of bounds and make a new base reg using the architecture's temp |
1070 // register. If that works for the next slot, then great. Otherwise, create a | 1122 // register. If that works for the next slot, then great. Otherwise, create a |
1071 // new base register, clobbering the previous base register. Never share a | 1123 // new base register, clobbering the previous base register. Never share a |
1072 // base reg across different basic blocks. This isn't ideal if local and | 1124 // base reg across different basic blocks. This isn't ideal if local and |
1073 // multi-block variables are far apart and their references are interspersed. | 1125 // multi-block variables are far apart and their references are interspersed. |
1074 // It may help to be more coordinated about assign stack slot numbers and may | 1126 // It may help to be more coordinated about assign stack slot numbers and may |
1075 // help to assign smaller offsets to higher-weight variables so that they | 1127 // help to assign smaller offsets to higher-weight variables so that they |
1076 // don't depend on this legalization. | 1128 // don't depend on this legalization. |
1077 for (CfgNode *Node : Func->getNodes()) { | 1129 for (CfgNode *Node : Func->getNodes()) { |
1078 Context.init(Node); | 1130 Context.init(Node); |
1079 Variable *NewBaseReg = nullptr; | 1131 Variable *NewBaseReg = nullptr; |
1080 int32_t NewBaseOffset = 0; | 1132 int32_t NewBaseOffset = 0; |
1081 while (!Context.atEnd()) { | 1133 while (!Context.atEnd()) { |
1082 PostIncrLoweringContext PostIncrement(Context); | 1134 PostIncrLoweringContext PostIncrement(Context); |
1083 Inst *CurInstr = Context.getCur(); | 1135 Inst *CurInstr = Context.getCur(); |
1084 Variable *Dest = CurInstr->getDest(); | 1136 Variable *Dest = CurInstr->getDest(); |
1085 | 1137 |
1086 // Check if the previous NewBaseReg is clobbered, and reset if needed. | 1138 // Check if the previous NewBaseReg is clobbered, and reset if needed. |
1087 if ((Dest && NewBaseReg && Dest->hasReg() && | 1139 if ((Dest && NewBaseReg && Dest->hasReg() && |
1088 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) || | 1140 Dest->getRegNum() == NewBaseReg->getBaseRegNum()) || |
1089 llvm::isa<InstFakeKill>(CurInstr)) { | 1141 llvm::isa<InstFakeKill>(CurInstr)) { |
1090 NewBaseReg = nullptr; | 1142 NewBaseReg = nullptr; |
1091 NewBaseOffset = 0; | 1143 NewBaseOffset = 0; |
1092 } | 1144 } |
1093 | 1145 |
1094 // The stack adjustment only matters if we are using SP instead of FP. | |
1095 if (!hasFramePointer()) { | |
1096 if (auto *AdjInst = llvm::dyn_cast<InstARM32AdjustStack>(CurInstr)) { | |
1097 StackAdjust += AdjInst->getAmount(); | |
1098 NewBaseOffset += AdjInst->getAmount(); | |
1099 continue; | |
1100 } | |
1101 if (llvm::isa<InstARM32Call>(CurInstr)) { | |
1102 NewBaseOffset -= StackAdjust; | |
1103 StackAdjust = 0; | |
1104 continue; | |
1105 } | |
1106 } | |
1107 | |
1108 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { | 1146 if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) { |
1109 legalizeMov(MovInstr, StackAdjust, OrigBaseReg, &NewBaseReg, | 1147 legalizeMov(MovInstr, OrigBaseReg, &NewBaseReg, &NewBaseOffset); |
1110 &NewBaseOffset); | |
1111 } | 1148 } |
1112 } | 1149 } |
1113 } | 1150 } |
1114 } | 1151 } |
1115 | 1152 |
1116 Operand *TargetARM32::loOperand(Operand *Operand) { | 1153 Operand *TargetARM32::loOperand(Operand *Operand) { |
1117 assert(Operand->getType() == IceType_i64); | 1154 assert(Operand->getType() == IceType_i64); |
1118 if (Operand->getType() != IceType_i64) | 1155 if (Operand->getType() != IceType_i64) |
1119 return Operand; | 1156 return Operand; |
1120 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 1157 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1262 // Non-constant sizes need to be adjusted to the next highest multiple of | 1299 // Non-constant sizes need to be adjusted to the next highest multiple of |
1263 // the required alignment at runtime. | 1300 // the required alignment at runtime. |
1264 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); | 1301 TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex); |
1265 Variable *T = makeReg(IceType_i32); | 1302 Variable *T = makeReg(IceType_i32); |
1266 _mov(T, TotalSize); | 1303 _mov(T, TotalSize); |
1267 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); | 1304 Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1)); |
1268 _add(T, T, AddAmount); | 1305 _add(T, T, AddAmount); |
1269 alignRegisterPow2(T, Alignment); | 1306 alignRegisterPow2(T, Alignment); |
1270 _sub(SP, SP, T); | 1307 _sub(SP, SP, T); |
1271 } | 1308 } |
1272 _mov(Dest, SP); | 1309 Variable *T = SP; |
1310 if (MaxOutArgsSizeBytes != 0) { | |
1311 T = makeReg(getPointerType()); | |
1312 Operand *OutArgsSizeRF = legalize( | |
1313 Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex); | |
1314 _add(T, SP, OutArgsSizeRF); | |
1315 } | |
1316 _mov(Dest, T); | |
1273 } | 1317 } |
1274 | 1318 |
1275 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { | 1319 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { |
1276 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) | 1320 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) |
1277 return; | 1321 return; |
1278 Variable *SrcLoReg = legalizeToReg(SrcLo); | 1322 Variable *SrcLoReg = legalizeToReg(SrcLo); |
1279 switch (Ty) { | 1323 switch (Ty) { |
1280 default: | 1324 default: |
1281 llvm::report_fatal_error("Unexpected type"); | 1325 llvm::report_fatal_error("Unexpected type"); |
1282 case IceType_i8: | 1326 case IceType_i8: |
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2086 } | 2130 } |
2087 case InstArithmetic::Xor: { | 2131 case InstArithmetic::Xor: { |
2088 Variable *Src0R = Srcs.src0R(this); | 2132 Variable *Src0R = Srcs.src0R(this); |
2089 Operand *Src1RF = Srcs.src1RF(this); | 2133 Operand *Src1RF = Srcs.src1RF(this); |
2090 _eor(T, Src0R, Src1RF); | 2134 _eor(T, Src0R, Src1RF); |
2091 _mov(Dest, T); | 2135 _mov(Dest, T); |
2092 return; | 2136 return; |
2093 } | 2137 } |
2094 case InstArithmetic::Sub: { | 2138 case InstArithmetic::Sub: { |
2095 if (Srcs.hasConstOperand()) { | 2139 if (Srcs.hasConstOperand()) { |
2140 // TODO(jpp): lowering Src0R here is wrong -- Src0R it is not guaranteed | |
2141 // to be used. | |
2096 Variable *Src0R = Srcs.src0R(this); | 2142 Variable *Src0R = Srcs.src0R(this); |
2097 if (Srcs.immediateIsFlexEncodable()) { | 2143 if (Srcs.immediateIsFlexEncodable()) { |
2098 Operand *Src1RF = Srcs.src1RF(this); | 2144 Operand *Src1RF = Srcs.src1RF(this); |
2099 if (Srcs.swappedOperands()) { | 2145 if (Srcs.swappedOperands()) { |
2100 _rsb(T, Src0R, Src1RF); | 2146 _rsb(T, Src0R, Src1RF); |
2101 } else { | 2147 } else { |
2102 _sub(T, Src0R, Src1RF); | 2148 _sub(T, Src0R, Src1RF); |
2103 } | 2149 } |
2104 _mov(Dest, T); | 2150 _mov(Dest, T); |
2105 return; | 2151 return; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2339 | 2385 |
2340 // Assign arguments to registers and stack. Also reserve stack. | 2386 // Assign arguments to registers and stack. Also reserve stack. |
2341 TargetARM32::CallingConv CC; | 2387 TargetARM32::CallingConv CC; |
2342 // Pair of Arg Operand -> GPR number assignments. | 2388 // Pair of Arg Operand -> GPR number assignments. |
2343 llvm::SmallVector<std::pair<Operand *, int32_t>, | 2389 llvm::SmallVector<std::pair<Operand *, int32_t>, |
2344 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; | 2390 TargetARM32::CallingConv::ARM32_MAX_GPR_ARG> GPRArgs; |
2345 llvm::SmallVector<std::pair<Operand *, int32_t>, | 2391 llvm::SmallVector<std::pair<Operand *, int32_t>, |
2346 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; | 2392 TargetARM32::CallingConv::ARM32_MAX_FP_REG_UNITS> FPArgs; |
2347 // Pair of Arg Operand -> stack offset. | 2393 // Pair of Arg Operand -> stack offset. |
2348 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 2394 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
2349 int32_t ParameterAreaSizeBytes = 0; | 2395 size_t ParameterAreaSizeBytes = 0; |
2350 | 2396 |
2351 // Classify each argument operand according to the location where the | 2397 // Classify each argument operand according to the location where the |
2352 // argument is passed. | 2398 // argument is passed. |
2353 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 2399 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { |
2354 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 2400 Operand *Arg = legalizeUndef(Instr->getArg(i)); |
2355 Type Ty = Arg->getType(); | 2401 Type Ty = Arg->getType(); |
2356 bool InRegs = false; | 2402 bool InRegs = false; |
2357 if (Ty == IceType_i64) { | 2403 if (Ty == IceType_i64) { |
2358 std::pair<int32_t, int32_t> Regs; | 2404 std::pair<int32_t, int32_t> Regs; |
2359 if (CC.I64InRegs(&Regs)) { | 2405 if (CC.I64InRegs(&Regs)) { |
(...skipping 23 matching lines...) Expand all Loading... | |
2383 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 2429 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); |
2384 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 2430 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); |
2385 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | 2431 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); |
2386 } | 2432 } |
2387 } | 2433 } |
2388 | 2434 |
2389 // Adjust the parameter area so that the stack is aligned. It is assumed that | 2435 // Adjust the parameter area so that the stack is aligned. It is assumed that |
2390 // the stack is already aligned at the start of the calling sequence. | 2436 // the stack is already aligned at the start of the calling sequence. |
2391 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 2437 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
2392 | 2438 |
2393 // Subtract the appropriate amount for the argument area. This also takes | 2439 if (ParameterAreaSizeBytes > MaxOutArgsSizeBytes) { |
2394 // care of setting the stack adjustment during emission. | 2440 llvm::report_fatal_error("MaxOutArgsSizeBytes is not really a max."); |
2395 // | |
2396 // TODO: If for some reason the call instruction gets dead-code eliminated | |
2397 // after lowering, we would need to ensure that the pre-call and the | |
2398 // post-call esp adjustment get eliminated as well. | |
2399 if (ParameterAreaSizeBytes) { | |
2400 Operand *SubAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), | |
2401 Legal_Reg | Legal_Flex); | |
2402 _adjust_stack(ParameterAreaSizeBytes, SubAmount); | |
2403 } | 2441 } |
2404 | 2442 |
2405 // Copy arguments that are passed on the stack to the appropriate stack | 2443 // Copy arguments that are passed on the stack to the appropriate stack |
2406 // locations. | 2444 // locations. |
2407 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2445 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
2408 for (auto &StackArg : StackArgs) { | 2446 for (auto &StackArg : StackArgs) { |
2409 ConstantInteger32 *Loc = | 2447 ConstantInteger32 *Loc = |
2410 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); | 2448 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); |
2411 Type Ty = StackArg.first->getType(); | 2449 Type Ty = StackArg.first->getType(); |
2412 OperandARM32Mem *Addr; | 2450 OperandARM32Mem *Addr; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2485 // Generate a FakeUse of register arguments so that they do not get dead | 2523 // Generate a FakeUse of register arguments so that they do not get dead |
2486 // code eliminated as a result of the FakeKill of scratch registers after | 2524 // code eliminated as a result of the FakeKill of scratch registers after |
2487 // the call. | 2525 // the call. |
2488 Context.insert(InstFakeUse::create(Func, Reg)); | 2526 Context.insert(InstFakeUse::create(Func, Reg)); |
2489 } | 2527 } |
2490 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); | 2528 Inst *NewCall = InstARM32Call::create(Func, ReturnReg, CallTarget); |
2491 Context.insert(NewCall); | 2529 Context.insert(NewCall); |
2492 if (ReturnRegHi) | 2530 if (ReturnRegHi) |
2493 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 2531 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
2494 | 2532 |
2495 // Add the appropriate offset to SP. The call instruction takes care of | |
2496 // resetting the stack offset during emission. | |
2497 if (ParameterAreaSizeBytes) { | |
2498 Operand *AddAmount = legalize(Ctx->getConstantInt32(ParameterAreaSizeBytes), | |
2499 Legal_Reg | Legal_Flex); | |
2500 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | |
2501 _add(SP, SP, AddAmount); | |
2502 } | |
2503 | |
2504 // Insert a register-kill pseudo instruction. | 2533 // Insert a register-kill pseudo instruction. |
2505 Context.insert(InstFakeKill::create(Func, NewCall)); | 2534 Context.insert(InstFakeKill::create(Func, NewCall)); |
2506 | 2535 |
2507 // Generate a FakeUse to keep the call live if necessary. | 2536 // Generate a FakeUse to keep the call live if necessary. |
2508 if (Instr->hasSideEffects() && ReturnReg) { | 2537 if (Instr->hasSideEffects() && ReturnReg) { |
2509 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 2538 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); |
2510 Context.insert(FakeUse); | 2539 Context.insert(FakeUse); |
2511 } | 2540 } |
2512 | 2541 |
2513 if (!Dest) | 2542 if (!Dest) |
(...skipping 2869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5383 // Technically R9 is used for TLS with Sandboxing, and we reserve it. | 5412 // Technically R9 is used for TLS with Sandboxing, and we reserve it. |
5384 // However, for compatibility with current NaCl LLVM, don't claim that. | 5413 // However, for compatibility with current NaCl LLVM, don't claim that. |
5385 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 5414 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
5386 } | 5415 } |
5387 | 5416 |
5388 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; | 5417 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[IceType_NUM]; |
5389 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 5418 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
5390 llvm::SmallBitVector TargetARM32::ScratchRegs; | 5419 llvm::SmallBitVector TargetARM32::ScratchRegs; |
5391 | 5420 |
5392 } // end of namespace Ice | 5421 } // end of namespace Ice |
OLD | NEW |