| 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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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()) { | 55 if (Ice::getFlags().getUseNonsfi()) { |
| 56 // In nonsfi, we need to reference the _GLOBAL_OFFSET_TABLE_ for accessing | 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 | 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 | 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 | 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. | 60 // here because staticInit() is invoked in a single-thread context. |
| 61 Ctx->getConstantExternSym(Ctx->getGlobalString(::Ice::GlobalOffsetTable)); | 61 Ctx->getConstantExternSym(Ctx->getGlobalString(::Ice::GlobalOffsetTable)); |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 | 64 |
| 65 bool shouldBePooled(const ::Ice::Constant *C) { | 65 bool shouldBePooled(const ::Ice::Constant *C) { |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 // Add handling of new register classes below. | 293 // Add handling of new register classes below. |
| 294 case RegARM32::RCARM32_QtoS: | 294 case RegARM32::RCARM32_QtoS: |
| 295 return "QtoS"; | 295 return "QtoS"; |
| 296 } | 296 } |
| 297 } | 297 } |
| 298 | 298 |
| 299 } // end of anonymous namespace | 299 } // end of anonymous namespace |
| 300 | 300 |
| 301 TargetARM32::TargetARM32(Cfg *Func) | 301 TargetARM32::TargetARM32(Cfg *Func) |
| 302 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl), | 302 : TargetLowering(Func), NeedSandboxing(SandboxingType == ST_NaCl), |
| 303 CPUFeatures(Func->getContext()->getFlags()) {} | 303 CPUFeatures(getFlags()) {} |
| 304 | 304 |
| 305 void TargetARM32::staticInit(GlobalContext *Ctx) { | 305 void TargetARM32::staticInit(GlobalContext *Ctx) { |
| 306 RegNumT::setLimit(RegARM32::Reg_NUM); | 306 RegNumT::setLimit(RegARM32::Reg_NUM); |
| 307 // Limit this size (or do all bitsets need to be the same width)??? | 307 // Limit this size (or do all bitsets need to be the same width)??? |
| 308 SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); | 308 SmallBitVector IntegerRegisters(RegARM32::Reg_NUM); |
| 309 SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); | 309 SmallBitVector I64PairRegisters(RegARM32::Reg_NUM); |
| 310 SmallBitVector Float32Registers(RegARM32::Reg_NUM); | 310 SmallBitVector Float32Registers(RegARM32::Reg_NUM); |
| 311 SmallBitVector Float64Registers(RegARM32::Reg_NUM); | 311 SmallBitVector Float64Registers(RegARM32::Reg_NUM); |
| 312 SmallBitVector VectorRegisters(RegARM32::Reg_NUM); | 312 SmallBitVector VectorRegisters(RegARM32::Reg_NUM); |
| 313 SmallBitVector QtoSRegisters(RegARM32::Reg_NUM); | 313 SmallBitVector QtoSRegisters(RegARM32::Reg_NUM); |
| (...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 createGotPtr(); | 1034 createGotPtr(); |
| 1035 } | 1035 } |
| 1036 genTargetHelperCalls(); | 1036 genTargetHelperCalls(); |
| 1037 findMaxStackOutArgsSize(); | 1037 findMaxStackOutArgsSize(); |
| 1038 | 1038 |
| 1039 // Do not merge Alloca instructions, and lay out the stack. | 1039 // Do not merge Alloca instructions, and lay out the stack. |
| 1040 static constexpr bool SortAndCombineAllocas = true; | 1040 static constexpr bool SortAndCombineAllocas = true; |
| 1041 Func->processAllocas(SortAndCombineAllocas); | 1041 Func->processAllocas(SortAndCombineAllocas); |
| 1042 Func->dump("After Alloca processing"); | 1042 Func->dump("After Alloca processing"); |
| 1043 | 1043 |
| 1044 if (!Ctx->getFlags().getEnablePhiEdgeSplit()) { | 1044 if (!getFlags().getEnablePhiEdgeSplit()) { |
| 1045 // Lower Phi instructions. | 1045 // Lower Phi instructions. |
| 1046 Func->placePhiLoads(); | 1046 Func->placePhiLoads(); |
| 1047 if (Func->hasError()) | 1047 if (Func->hasError()) |
| 1048 return; | 1048 return; |
| 1049 Func->placePhiStores(); | 1049 Func->placePhiStores(); |
| 1050 if (Func->hasError()) | 1050 if (Func->hasError()) |
| 1051 return; | 1051 return; |
| 1052 Func->deletePhis(); | 1052 Func->deletePhis(); |
| 1053 if (Func->hasError()) | 1053 if (Func->hasError()) |
| 1054 return; | 1054 return; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1102 // cleanup, to make the dump cleaner and more useful. | 1102 // cleanup, to make the dump cleaner and more useful. |
| 1103 Func->dump("After initial ARM32 codegen"); | 1103 Func->dump("After initial ARM32 codegen"); |
| 1104 Func->getVMetadata()->init(VMK_All); | 1104 Func->getVMetadata()->init(VMK_All); |
| 1105 regAlloc(RAK_Global); | 1105 regAlloc(RAK_Global); |
| 1106 if (Func->hasError()) | 1106 if (Func->hasError()) |
| 1107 return; | 1107 return; |
| 1108 | 1108 |
| 1109 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); | 1109 copyRegAllocFromInfWeightVariable64On32(Func->getVariables()); |
| 1110 Func->dump("After linear scan regalloc"); | 1110 Func->dump("After linear scan regalloc"); |
| 1111 | 1111 |
| 1112 if (Ctx->getFlags().getEnablePhiEdgeSplit()) { | 1112 if (getFlags().getEnablePhiEdgeSplit()) { |
| 1113 Func->advancedPhiLowering(); | 1113 Func->advancedPhiLowering(); |
| 1114 Func->dump("After advanced Phi lowering"); | 1114 Func->dump("After advanced Phi lowering"); |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 ForbidTemporaryWithoutReg _(this); | 1117 ForbidTemporaryWithoutReg _(this); |
| 1118 | 1118 |
| 1119 // Stack frame mapping. | 1119 // Stack frame mapping. |
| 1120 Func->genFrame(); | 1120 Func->genFrame(); |
| 1121 if (Func->hasError()) | 1121 if (Func->hasError()) |
| 1122 return; | 1122 return; |
| 1123 Func->dump("After stack frame mapping"); | 1123 Func->dump("After stack frame mapping"); |
| 1124 | 1124 |
| 1125 postLowerLegalization(); | 1125 postLowerLegalization(); |
| 1126 if (Func->hasError()) | 1126 if (Func->hasError()) |
| 1127 return; | 1127 return; |
| 1128 Func->dump("After postLowerLegalization"); | 1128 Func->dump("After postLowerLegalization"); |
| 1129 | 1129 |
| 1130 Func->contractEmptyNodes(); | 1130 Func->contractEmptyNodes(); |
| 1131 Func->reorderNodes(); | 1131 Func->reorderNodes(); |
| 1132 | 1132 |
| 1133 // Branch optimization. This needs to be done just before code emission. In | 1133 // Branch optimization. This needs to be done just before code emission. In |
| 1134 // particular, no transformations that insert or reorder CfgNodes should be | 1134 // particular, no transformations that insert or reorder CfgNodes should be |
| 1135 // done after branch optimization. We go ahead and do it before nop insertion | 1135 // done after branch optimization. We go ahead and do it before nop insertion |
| 1136 // to reduce the amount of work needed for searching for opportunities. | 1136 // to reduce the amount of work needed for searching for opportunities. |
| 1137 Func->doBranchOpt(); | 1137 Func->doBranchOpt(); |
| 1138 Func->dump("After branch optimization"); | 1138 Func->dump("After branch optimization"); |
| 1139 | 1139 |
| 1140 // Nop insertion | 1140 // Nop insertion |
| 1141 if (Ctx->getFlags().getShouldDoNopInsertion()) { | 1141 if (getFlags().getShouldDoNopInsertion()) { |
| 1142 Func->doNopInsertion(); | 1142 Func->doNopInsertion(); |
| 1143 } | 1143 } |
| 1144 } | 1144 } |
| 1145 | 1145 |
| 1146 void TargetARM32::translateOm1() { | 1146 void TargetARM32::translateOm1() { |
| 1147 TimerMarker T(TimerStack::TT_Om1, Func); | 1147 TimerMarker T(TimerStack::TT_Om1, Func); |
| 1148 | 1148 |
| 1149 // TODO(stichnot): share passes with other targets? | 1149 // TODO(stichnot): share passes with other targets? |
| 1150 if (SandboxingType == ST_Nonsfi) { | 1150 if (SandboxingType == ST_Nonsfi) { |
| 1151 createGotPtr(); | 1151 createGotPtr(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 if (Func->hasError()) | 1193 if (Func->hasError()) |
| 1194 return; | 1194 return; |
| 1195 Func->dump("After stack frame mapping"); | 1195 Func->dump("After stack frame mapping"); |
| 1196 | 1196 |
| 1197 postLowerLegalization(); | 1197 postLowerLegalization(); |
| 1198 if (Func->hasError()) | 1198 if (Func->hasError()) |
| 1199 return; | 1199 return; |
| 1200 Func->dump("After postLowerLegalization"); | 1200 Func->dump("After postLowerLegalization"); |
| 1201 | 1201 |
| 1202 // Nop insertion | 1202 // Nop insertion |
| 1203 if (Ctx->getFlags().getShouldDoNopInsertion()) { | 1203 if (getFlags().getShouldDoNopInsertion()) { |
| 1204 Func->doNopInsertion(); | 1204 Func->doNopInsertion(); |
| 1205 } | 1205 } |
| 1206 } | 1206 } |
| 1207 | 1207 |
| 1208 uint32_t TargetARM32::getStackAlignment() const { | 1208 uint32_t TargetARM32::getStackAlignment() const { |
| 1209 return ARM32_STACK_ALIGNMENT_BYTES; | 1209 return ARM32_STACK_ALIGNMENT_BYTES; |
| 1210 } | 1210 } |
| 1211 | 1211 |
| 1212 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 1212 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
| 1213 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { | 1213 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 // liveness validation errors for saving callee-save registers. | 1249 // liveness validation errors for saving callee-save registers. |
| 1250 Func->addImplicitArg(Reg); | 1250 Func->addImplicitArg(Reg); |
| 1251 // Don't bother tracking the live range of a named physical register. | 1251 // Don't bother tracking the live range of a named physical register. |
| 1252 Reg->setIgnoreLiveness(); | 1252 Reg->setIgnoreLiveness(); |
| 1253 } | 1253 } |
| 1254 return Reg; | 1254 return Reg; |
| 1255 } | 1255 } |
| 1256 | 1256 |
| 1257 void TargetARM32::emitJumpTable(const Cfg *Func, | 1257 void TargetARM32::emitJumpTable(const Cfg *Func, |
| 1258 const InstJumpTable *JumpTable) const { | 1258 const InstJumpTable *JumpTable) const { |
| 1259 (void)Func; |
| 1259 (void)JumpTable; | 1260 (void)JumpTable; |
| 1260 UnimplementedError(Func->getContext()->getFlags()); | 1261 UnimplementedError(getFlags()); |
| 1261 } | 1262 } |
| 1262 | 1263 |
| 1263 void TargetARM32::emitVariable(const Variable *Var) const { | 1264 void TargetARM32::emitVariable(const Variable *Var) const { |
| 1264 if (!BuildDefs::dump()) | 1265 if (!BuildDefs::dump()) |
| 1265 return; | 1266 return; |
| 1266 Ostream &Str = Ctx->getStrEmit(); | 1267 Ostream &Str = Ctx->getStrEmit(); |
| 1267 if (Var->hasReg()) { | 1268 if (Var->hasReg()) { |
| 1268 Str << getRegName(Var->getRegNum(), Var->getType()); | 1269 Str << getRegName(Var->getRegNum(), Var->getType()); |
| 1269 return; | 1270 return; |
| 1270 } | 1271 } |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 Legal_Reg | Legal_Flex, getReservedTmpReg()); | 1761 Legal_Reg | Legal_Flex, getReservedTmpReg()); |
| 1761 Sandboxer(this).add_sp(AddAmount); | 1762 Sandboxer(this).add_sp(AddAmount); |
| 1762 } | 1763 } |
| 1763 } | 1764 } |
| 1764 | 1765 |
| 1765 if (!PreservedGPRs.empty()) | 1766 if (!PreservedGPRs.empty()) |
| 1766 _pop(PreservedGPRs); | 1767 _pop(PreservedGPRs); |
| 1767 if (!PreservedSRegs.empty()) | 1768 if (!PreservedSRegs.empty()) |
| 1768 _pop(PreservedSRegs); | 1769 _pop(PreservedSRegs); |
| 1769 | 1770 |
| 1770 if (!Ctx->getFlags().getUseSandboxing()) | 1771 if (!getFlags().getUseSandboxing()) |
| 1771 return; | 1772 return; |
| 1772 | 1773 |
| 1773 // Change the original ret instruction into a sandboxed return sequence. | 1774 // Change the original ret instruction into a sandboxed return sequence. |
| 1774 // | 1775 // |
| 1775 // bundle_lock | 1776 // bundle_lock |
| 1776 // bic lr, #0xc000000f | 1777 // bic lr, #0xc000000f |
| 1777 // bx lr | 1778 // bx lr |
| 1778 // bundle_unlock | 1779 // bundle_unlock |
| 1779 // | 1780 // |
| 1780 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to | 1781 // This isn't just aligning to the getBundleAlignLog2Bytes(). It needs to |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2248 // bit-manipulation problems below. | 2249 // bit-manipulation problems below. |
| 2249 const uint32_t AlignmentParam = std::max(1u, Instr->getAlignInBytes()); | 2250 const uint32_t AlignmentParam = std::max(1u, Instr->getAlignInBytes()); |
| 2250 | 2251 |
| 2251 // LLVM enforces power of 2 alignment. | 2252 // LLVM enforces power of 2 alignment. |
| 2252 assert(llvm::isPowerOf2_32(AlignmentParam)); | 2253 assert(llvm::isPowerOf2_32(AlignmentParam)); |
| 2253 assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES)); | 2254 assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES)); |
| 2254 | 2255 |
| 2255 const uint32_t Alignment = | 2256 const uint32_t Alignment = |
| 2256 std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES); | 2257 std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES); |
| 2257 const bool OverAligned = Alignment > ARM32_STACK_ALIGNMENT_BYTES; | 2258 const bool OverAligned = Alignment > ARM32_STACK_ALIGNMENT_BYTES; |
| 2258 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 2259 const bool OptM1 = getFlags().getOptLevel() == Opt_m1; |
| 2259 const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset(); | 2260 const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset(); |
| 2260 const bool UseFramePointer = | 2261 const bool UseFramePointer = |
| 2261 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; | 2262 hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1; |
| 2262 | 2263 |
| 2263 if (UseFramePointer) | 2264 if (UseFramePointer) |
| 2264 setHasFramePointer(); | 2265 setHasFramePointer(); |
| 2265 | 2266 |
| 2266 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); | 2267 Variable *SP = getPhysicalRegister(RegARM32::Reg_sp); |
| 2267 if (OverAligned) { | 2268 if (OverAligned) { |
| 2268 Sandboxer(this).align_sp(Alignment); | 2269 Sandboxer(this).align_sp(Alignment); |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3349 Variable *Src1R = Srcs.unswappedSrc1R(this); | 3350 Variable *Src1R = Srcs.unswappedSrc1R(this); |
| 3350 if (isVectorType(DestTy)) { | 3351 if (isVectorType(DestTy)) { |
| 3351 _vsub(T, Src0R, Src1R); | 3352 _vsub(T, Src0R, Src1R); |
| 3352 } else { | 3353 } else { |
| 3353 _sub(T, Src0R, Src1R); | 3354 _sub(T, Src0R, Src1R); |
| 3354 } | 3355 } |
| 3355 _mov(Dest, T); | 3356 _mov(Dest, T); |
| 3356 return; | 3357 return; |
| 3357 } | 3358 } |
| 3358 case InstArithmetic::Mul: { | 3359 case InstArithmetic::Mul: { |
| 3359 const bool OptM1 = Ctx->getFlags().getOptLevel() == Opt_m1; | 3360 const bool OptM1 = getFlags().getOptLevel() == Opt_m1; |
| 3360 if (!OptM1 && Srcs.hasConstOperand()) { | 3361 if (!OptM1 && Srcs.hasConstOperand()) { |
| 3361 constexpr std::size_t MaxShifts = 4; | 3362 constexpr std::size_t MaxShifts = 4; |
| 3362 std::array<StrengthReduction::AggregationElement, MaxShifts> Shifts; | 3363 std::array<StrengthReduction::AggregationElement, MaxShifts> Shifts; |
| 3363 SizeT NumOperations; | 3364 SizeT NumOperations; |
| 3364 int32_t Const = Srcs.getConstantValue(); | 3365 int32_t Const = Srcs.getConstantValue(); |
| 3365 const bool Invert = Const < 0; | 3366 const bool Invert = Const < 0; |
| 3366 const bool MultiplyByZero = Const == 0; | 3367 const bool MultiplyByZero = Const == 0; |
| 3367 Operand *_0 = | 3368 Operand *_0 = |
| 3368 legalize(Ctx->getConstantZero(DestTy), Legal_Reg | Legal_Flex); | 3369 legalize(Ctx->getConstantZero(DestTy), Legal_Reg | Legal_Flex); |
| 3369 | 3370 |
| (...skipping 2758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6128 TmpRegNum); | 6129 TmpRegNum); |
| 6129 _bic(Reg, Reg, Mask); | 6130 _bic(Reg, Reg, Mask); |
| 6130 } else { | 6131 } else { |
| 6131 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, | 6132 Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex, |
| 6132 TmpRegNum); | 6133 TmpRegNum); |
| 6133 _and(Reg, Reg, Mask); | 6134 _and(Reg, Reg, Mask); |
| 6134 } | 6135 } |
| 6135 } | 6136 } |
| 6136 | 6137 |
| 6137 void TargetARM32::postLower() { | 6138 void TargetARM32::postLower() { |
| 6138 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 6139 if (getFlags().getOptLevel() == Opt_m1) |
| 6139 return; | 6140 return; |
| 6140 markRedefinitions(); | 6141 markRedefinitions(); |
| 6141 Context.availabilityUpdate(); | 6142 Context.availabilityUpdate(); |
| 6142 } | 6143 } |
| 6143 | 6144 |
| 6144 void TargetARM32::makeRandomRegisterPermutation( | 6145 void TargetARM32::makeRandomRegisterPermutation( |
| 6145 llvm::SmallVectorImpl<RegNumT> &Permutation, | 6146 llvm::SmallVectorImpl<RegNumT> &Permutation, |
| 6146 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 6147 const SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
| 6147 (void)Permutation; | 6148 (void)Permutation; |
| 6148 (void)ExcludeRegisters; | 6149 (void)ExcludeRegisters; |
| 6149 (void)Salt; | 6150 (void)Salt; |
| 6150 UnimplementedError(Func->getContext()->getFlags()); | 6151 UnimplementedError(getFlags()); |
| 6151 } | 6152 } |
| 6152 | 6153 |
| 6153 void TargetARM32::emit(const ConstantInteger32 *C) const { | 6154 void TargetARM32::emit(const ConstantInteger32 *C) const { |
| 6154 if (!BuildDefs::dump()) | 6155 if (!BuildDefs::dump()) |
| 6155 return; | 6156 return; |
| 6156 Ostream &Str = Ctx->getStrEmit(); | 6157 Ostream &Str = Ctx->getStrEmit(); |
| 6157 Str << "#" << C->getValue(); | 6158 Str << "#" << C->getValue(); |
| 6158 } | 6159 } |
| 6159 | 6160 |
| 6160 void TargetARM32::emit(const ConstantInteger64 *) const { | 6161 void TargetARM32::emit(const ConstantInteger64 *) const { |
| 6161 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 6162 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
| 6162 } | 6163 } |
| 6163 | 6164 |
| 6164 void TargetARM32::emit(const ConstantFloat *C) const { | 6165 void TargetARM32::emit(const ConstantFloat *C) const { |
| 6165 (void)C; | 6166 (void)C; |
| 6166 UnimplementedError(Ctx->getFlags()); | 6167 UnimplementedError(getFlags()); |
| 6167 } | 6168 } |
| 6168 | 6169 |
| 6169 void TargetARM32::emit(const ConstantDouble *C) const { | 6170 void TargetARM32::emit(const ConstantDouble *C) const { |
| 6170 (void)C; | 6171 (void)C; |
| 6171 UnimplementedError(Ctx->getFlags()); | 6172 UnimplementedError(getFlags()); |
| 6172 } | 6173 } |
| 6173 | 6174 |
| 6174 void TargetARM32::emit(const ConstantUndef *) const { | 6175 void TargetARM32::emit(const ConstantUndef *) const { |
| 6175 llvm::report_fatal_error("undef value encountered by emitter."); | 6176 llvm::report_fatal_error("undef value encountered by emitter."); |
| 6176 } | 6177 } |
| 6177 | 6178 |
| 6178 void TargetARM32::emit(const ConstantRelocatable *C) const { | 6179 void TargetARM32::emit(const ConstantRelocatable *C) const { |
| 6179 if (!BuildDefs::dump()) | 6180 if (!BuildDefs::dump()) |
| 6180 return; | 6181 return; |
| 6181 Ostream &Str = Ctx->getStrEmit(); | 6182 Ostream &Str = Ctx->getStrEmit(); |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6714 createAutoBundle(); | 6715 createAutoBundle(); |
| 6715 Target->_sub(SP, SP, SubAmount); | 6716 Target->_sub(SP, SP, SubAmount); |
| 6716 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | 6717 Target->_bic(SP, SP, memOpBicMask(Target->Func)); |
| 6717 } | 6718 } |
| 6718 | 6719 |
| 6719 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 6720 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
| 6720 : TargetDataLowering(Ctx) {} | 6721 : TargetDataLowering(Ctx) {} |
| 6721 | 6722 |
| 6722 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, | 6723 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, |
| 6723 const std::string &SectionSuffix) { | 6724 const std::string &SectionSuffix) { |
| 6724 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | 6725 const bool IsPIC = getFlags().getUseNonsfi(); |
| 6725 switch (Ctx->getFlags().getOutFileType()) { | 6726 switch (getFlags().getOutFileType()) { |
| 6726 case FT_Elf: { | 6727 case FT_Elf: { |
| 6727 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 6728 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 6728 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix, | 6729 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix, |
| 6729 IsPIC); | 6730 IsPIC); |
| 6730 } break; | 6731 } break; |
| 6731 case FT_Asm: | 6732 case FT_Asm: |
| 6732 case FT_Iasm: { | 6733 case FT_Iasm: { |
| 6733 const std::string TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 6734 const std::string TranslateOnly = getFlags().getTranslateOnly(); |
| 6734 OstreamLocker _(Ctx); | 6735 OstreamLocker _(Ctx); |
| 6735 for (const VariableDeclaration *Var : Vars) { | 6736 for (const VariableDeclaration *Var : Vars) { |
| 6736 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 6737 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
| 6737 emitGlobal(*Var, SectionSuffix); | 6738 emitGlobal(*Var, SectionSuffix); |
| 6738 } | 6739 } |
| 6739 } | 6740 } |
| 6740 } break; | 6741 } break; |
| 6741 } | 6742 } |
| 6742 } | 6743 } |
| 6743 | 6744 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6803 static constexpr size_t MinimumAlignment = 4; | 6804 static constexpr size_t MinimumAlignment = 4; |
| 6804 SizeT Align = std::max(MinimumAlignment, typeAlignInBytes(Traits::IceType)); | 6805 SizeT Align = std::max(MinimumAlignment, typeAlignInBytes(Traits::IceType)); |
| 6805 assert((Align % 4) == 0 && "Constants should be aligned"); | 6806 assert((Align % 4) == 0 && "Constants should be aligned"); |
| 6806 Ostream &Str = Ctx->getStrEmit(); | 6807 Ostream &Str = Ctx->getStrEmit(); |
| 6807 ConstantList Pool = Ctx->getConstantPool(Traits::IceType); | 6808 ConstantList Pool = Ctx->getConstantPool(Traits::IceType); |
| 6808 | 6809 |
| 6809 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",%progbits," << Align | 6810 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",%progbits," << Align |
| 6810 << "\n" | 6811 << "\n" |
| 6811 << "\t.align\t" << Align << "\n"; | 6812 << "\t.align\t" << Align << "\n"; |
| 6812 | 6813 |
| 6813 if (Ctx->getFlags().getReorderPooledConstants()) { | 6814 if (getFlags().getReorderPooledConstants()) { |
| 6814 // TODO(jpp): add constant pooling. | 6815 // TODO(jpp): add constant pooling. |
| 6815 UnimplementedError(Ctx->getFlags()); | 6816 UnimplementedError(getFlags()); |
| 6816 } | 6817 } |
| 6817 | 6818 |
| 6818 for (Constant *C : Pool) { | 6819 for (Constant *C : Pool) { |
| 6819 if (!C->getShouldBePooled()) { | 6820 if (!C->getShouldBePooled()) { |
| 6820 continue; | 6821 continue; |
| 6821 } | 6822 } |
| 6822 | 6823 |
| 6823 emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C)); | 6824 emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C)); |
| 6824 } | 6825 } |
| 6825 } | 6826 } |
| 6826 } // end of anonymous namespace | 6827 } // end of anonymous namespace |
| 6827 | 6828 |
| 6828 void TargetDataARM32::lowerConstants() { | 6829 void TargetDataARM32::lowerConstants() { |
| 6829 if (Ctx->getFlags().getDisableTranslation()) | 6830 if (getFlags().getDisableTranslation()) |
| 6830 return; | 6831 return; |
| 6831 switch (Ctx->getFlags().getOutFileType()) { | 6832 switch (getFlags().getOutFileType()) { |
| 6832 case FT_Elf: { | 6833 case FT_Elf: { |
| 6833 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 6834 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| 6834 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 6835 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 6835 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 6836 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 6836 } break; | 6837 } break; |
| 6837 case FT_Asm: | 6838 case FT_Asm: |
| 6838 case FT_Iasm: { | 6839 case FT_Iasm: { |
| 6839 OstreamLocker _(Ctx); | 6840 OstreamLocker _(Ctx); |
| 6840 emitConstantPool<float>(Ctx); | 6841 emitConstantPool<float>(Ctx); |
| 6841 emitConstantPool<double>(Ctx); | 6842 emitConstantPool<double>(Ctx); |
| 6842 break; | 6843 break; |
| 6843 } | 6844 } |
| 6844 } | 6845 } |
| 6845 } | 6846 } |
| 6846 | 6847 |
| 6847 void TargetDataARM32::lowerJumpTables() { | 6848 void TargetDataARM32::lowerJumpTables() { |
| 6848 if (Ctx->getFlags().getDisableTranslation()) | 6849 if (getFlags().getDisableTranslation()) |
| 6849 return; | 6850 return; |
| 6850 switch (Ctx->getFlags().getOutFileType()) { | 6851 switch (getFlags().getOutFileType()) { |
| 6851 case FT_Elf: | 6852 case FT_Elf: |
| 6852 if (!Ctx->getJumpTables().empty()) { | 6853 if (!Ctx->getJumpTables().empty()) { |
| 6853 llvm::report_fatal_error("ARM32 does not support jump tables yet."); | 6854 llvm::report_fatal_error("ARM32 does not support jump tables yet."); |
| 6854 } | 6855 } |
| 6855 break; | 6856 break; |
| 6856 case FT_Asm: | 6857 case FT_Asm: |
| 6857 // Already emitted from Cfg | 6858 // Already emitted from Cfg |
| 6858 break; | 6859 break; |
| 6859 case FT_Iasm: { | 6860 case FT_Iasm: { |
| 6860 // TODO(kschimpf): Fill this in when we get more information. | 6861 // TODO(kschimpf): Fill this in when we get more information. |
| 6861 break; | 6862 break; |
| 6862 } | 6863 } |
| 6863 } | 6864 } |
| 6864 } | 6865 } |
| 6865 | 6866 |
| 6866 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx) | 6867 TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx) |
| 6867 : TargetHeaderLowering(Ctx), CPUFeatures(Ctx->getFlags()) {} | 6868 : TargetHeaderLowering(Ctx), CPUFeatures(getFlags()) {} |
| 6868 | 6869 |
| 6869 void TargetHeaderARM32::lower() { | 6870 void TargetHeaderARM32::lower() { |
| 6870 OstreamLocker _(Ctx); | 6871 OstreamLocker _(Ctx); |
| 6871 Ostream &Str = Ctx->getStrEmit(); | 6872 Ostream &Str = Ctx->getStrEmit(); |
| 6872 Str << ".syntax unified\n"; | 6873 Str << ".syntax unified\n"; |
| 6873 // Emit build attributes in format: .eabi_attribute TAG, VALUE. See Sec. 2 of | 6874 // Emit build attributes in format: .eabi_attribute TAG, VALUE. See Sec. 2 of |
| 6874 // "Addenda to, and Errata in the ABI for the ARM architecture" | 6875 // "Addenda to, and Errata in the ABI for the ARM architecture" |
| 6875 // http://infocenter.arm.com | 6876 // http://infocenter.arm.com |
| 6876 // /help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf | 6877 // /help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf |
| 6877 // | 6878 // |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6911 // However, for compatibility with current NaCl LLVM, don't claim that. | 6912 // However, for compatibility with current NaCl LLVM, don't claim that. |
| 6912 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6913 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
| 6913 } | 6914 } |
| 6914 | 6915 |
| 6915 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6916 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
| 6916 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6917 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
| 6917 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6918 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
| 6918 | 6919 |
| 6919 } // end of namespace ARM32 | 6920 } // end of namespace ARM32 |
| 6920 } // end of namespace Ice | 6921 } // end of namespace Ice |
| OLD | NEW |