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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 (Ctx->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(::Ice::GlobalOffsetTable); | 61 Ctx->getConstantExternSym(Ctx->getGlobalString(::Ice::GlobalOffsetTable)); |
62 } | 62 } |
63 } | 63 } |
64 | 64 |
| 65 bool shouldBePooled(const ::Ice::Constant *C) { |
| 66 return ::Ice::ARM32::TargetARM32::shouldBePooled(C); |
| 67 } |
| 68 |
65 } // end of namespace ARM32 | 69 } // end of namespace ARM32 |
66 | 70 |
67 namespace Ice { | 71 namespace Ice { |
68 namespace ARM32 { | 72 namespace ARM32 { |
69 | 73 |
70 namespace { | 74 namespace { |
71 | 75 |
72 /// SizeOf is used to obtain the size of an initializer list as a constexpr | 76 /// SizeOf is used to obtain the size of an initializer list as a constexpr |
73 /// expression. This is only needed until our C++ library is updated to | 77 /// expression. This is only needed until our C++ library is updated to |
74 /// C++ 14 -- which defines constexpr members to std::initializer_list. | 78 /// C++ 14 -- which defines constexpr members to std::initializer_list. |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 276 |
273 constexpr SizeT NumVec128Args = | 277 constexpr SizeT NumVec128Args = |
274 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 278 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
275 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 279 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
276 +(((cc_arg > 0)) ? 1 : 0) | 280 +(((cc_arg > 0)) ? 1 : 0) |
277 REGARM32_VEC128_TABLE | 281 REGARM32_VEC128_TABLE |
278 #undef X | 282 #undef X |
279 ; | 283 ; |
280 std::array<RegNumT, NumVec128Args> Vec128ArgInitializer; | 284 std::array<RegNumT, NumVec128Args> Vec128ArgInitializer; |
281 | 285 |
282 IceString getRegClassName(RegClass C) { | 286 const char *getRegClassName(RegClass C) { |
283 auto ClassNum = static_cast<RegARM32::RegClassARM32>(C); | 287 auto ClassNum = static_cast<RegARM32::RegClassARM32>(C); |
284 assert(ClassNum < RegARM32::RCARM32_NUM); | 288 assert(ClassNum < RegARM32::RCARM32_NUM); |
285 switch (ClassNum) { | 289 switch (ClassNum) { |
286 default: | 290 default: |
287 assert(C < RC_Target); | 291 assert(C < RC_Target); |
288 return regClassString(C); | 292 return regClassString(C); |
289 // Add handling of new register classes below. | 293 // Add handling of new register classes below. |
290 case RegARM32::RCARM32_QtoS: | 294 case RegARM32::RCARM32_QtoS: |
291 return "QtoS"; | 295 return "QtoS"; |
292 } | 296 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; | 358 TypeToRegisterSet[IceType_v16i1] = VectorRegisters; |
355 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; | 359 TypeToRegisterSet[IceType_v16i8] = VectorRegisters; |
356 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; | 360 TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
357 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; | 361 TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
358 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; | 362 TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
359 TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters; | 363 TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters; |
360 | 364 |
361 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) | 365 for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i) |
362 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; | 366 TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i]; |
363 | 367 |
364 filterTypeToRegisterSet( | 368 filterTypeToRegisterSet(Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, |
365 Ctx, RegARM32::Reg_NUM, TypeToRegisterSet, | 369 llvm::array_lengthof(TypeToRegisterSet), |
366 llvm::array_lengthof(TypeToRegisterSet), [](RegNumT RegNum) -> IceString { | 370 [](RegNumT RegNum) -> std::string { |
367 // This function simply removes ", " from the register name. | 371 // This function simply removes ", " from the |
368 IceString Name = RegARM32::getRegName(RegNum); | 372 // register name. |
369 constexpr const char RegSeparator[] = ", "; | 373 std::string Name = RegARM32::getRegName(RegNum); |
370 constexpr size_t RegSeparatorWidth = | 374 constexpr const char RegSeparator[] = ", "; |
371 llvm::array_lengthof(RegSeparator) - 1; | 375 constexpr size_t RegSeparatorWidth = |
372 for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos; | 376 llvm::array_lengthof(RegSeparator) - 1; |
373 Pos = Name.find(RegSeparator)) { | 377 for (size_t Pos = Name.find(RegSeparator); |
374 Name.replace(Pos, RegSeparatorWidth, ""); | 378 Pos != std::string::npos; |
375 } | 379 Pos = Name.find(RegSeparator)) { |
376 return Name; | 380 Name.replace(Pos, RegSeparatorWidth, ""); |
377 }, getRegClassName); | 381 } |
| 382 return Name; |
| 383 }, |
| 384 getRegClassName); |
378 } | 385 } |
379 | 386 |
380 namespace { | 387 namespace { |
381 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { | 388 void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) { |
382 for (Variable *Var : Vars) { | 389 for (Variable *Var : Vars) { |
383 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); | 390 auto *Var64 = llvm::dyn_cast<Variable64On32>(Var); |
384 if (!Var64) { | 391 if (!Var64) { |
385 // This is not the variable we are looking for. | 392 // This is not the variable we are looking for. |
386 continue; | 393 continue; |
387 } | 394 } |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 Instr->setDeleted(); | 790 Instr->setDeleted(); |
784 return; | 791 return; |
785 } | 792 } |
786 case Intrinsics::NaClReadTP: { | 793 case Intrinsics::NaClReadTP: { |
787 if (SandboxingType == ST_NaCl) { | 794 if (SandboxingType == ST_NaCl) { |
788 return; | 795 return; |
789 } | 796 } |
790 static constexpr SizeT MaxArgs = 0; | 797 static constexpr SizeT MaxArgs = 0; |
791 Operand *TargetHelper = | 798 Operand *TargetHelper = |
792 SandboxingType == ST_Nonsfi | 799 SandboxingType == ST_Nonsfi |
793 ? Ctx->getConstantExternSym("__aeabi_read_tp") | 800 ? Ctx->getConstantExternSym( |
| 801 Ctx->getGlobalString("__aeabi_read_tp")) |
794 : Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_read_tp); | 802 : Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_read_tp); |
795 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, | 803 Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, NoTailCall, |
796 IsTargetHelperCall); | 804 IsTargetHelperCall); |
797 Instr->setDeleted(); | 805 Instr->setDeleted(); |
798 return; | 806 return; |
799 } | 807 } |
800 case Intrinsics::Setjmp: { | 808 case Intrinsics::Setjmp: { |
801 static constexpr SizeT MaxArgs = 1; | 809 static constexpr SizeT MaxArgs = 1; |
802 Operand *TargetHelper = | 810 Operand *TargetHelper = |
803 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp); | 811 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
902 // movt reg, _GLOBAL_OFFSET_TABLE_ - 12 - . | 910 // movt reg, _GLOBAL_OFFSET_TABLE_ - 12 - . |
903 // add reg, pc, reg | 911 // add reg, pc, reg |
904 // mov GotPtr, reg | 912 // mov GotPtr, reg |
905 // | 913 // |
906 // If GotPtr is not used, then both these pseudo-instructions are dce'd. | 914 // If GotPtr is not used, then both these pseudo-instructions are dce'd. |
907 Variable *T = makeReg(IceType_i32); | 915 Variable *T = makeReg(IceType_i32); |
908 Context.insert<InstFakeDef>(T); | 916 Context.insert<InstFakeDef>(T); |
909 Context.insert<InstFakeDef>(GotPtr, T); | 917 Context.insert<InstFakeDef>(GotPtr, T); |
910 } | 918 } |
911 | 919 |
912 IceString TargetARM32::createGotoffRelocation(const ConstantRelocatable *CR) { | 920 GlobalString |
913 const IceString &CRName = CR->getName(); | 921 TargetARM32::createGotoffRelocation(const ConstantRelocatable *CR) { |
914 const IceString CRGotoffName = | 922 GlobalString CRName = CR->getName(); |
915 "GOTOFF$" + Func->getFunctionName() + "$" + CRName; | 923 GlobalString CRGotoffName = |
| 924 Ctx->getGlobalString("GOTOFF$" + Func->getFunctionName() + "$" + CRName); |
916 if (KnownGotoffs.count(CRGotoffName) == 0) { | 925 if (KnownGotoffs.count(CRGotoffName) == 0) { |
917 constexpr bool SuppressMangling = true; | 926 constexpr bool SuppressMangling = true; |
918 auto *Global = | 927 auto *Global = |
919 VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling); | 928 VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling); |
920 Global->setIsConstant(true); | 929 Global->setIsConstant(true); |
921 Global->setName(CRName); | 930 Global->setName(CRName); |
922 Func->getGlobalPool()->willNotBeEmitted(Global); | 931 Func->getGlobalPool()->willNotBeEmitted(Global); |
923 | 932 |
924 auto *Gotoff = | 933 auto *Gotoff = |
925 VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling); | 934 VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 | 967 |
959 if (DefGotPtr == nullptr || DefGotPtr->isDeleted()) { | 968 if (DefGotPtr == nullptr || DefGotPtr->isDeleted()) { |
960 return; | 969 return; |
961 } | 970 } |
962 | 971 |
963 // The got addr needs to be materialized at the same point where DefGotPtr | 972 // The got addr needs to be materialized at the same point where DefGotPtr |
964 // lives. | 973 // lives. |
965 Context.setInsertPoint(DefGotPtr); | 974 Context.setInsertPoint(DefGotPtr); |
966 assert(DefGotPtr->getSrcSize() == 1); | 975 assert(DefGotPtr->getSrcSize() == 1); |
967 auto *T = llvm::cast<Variable>(DefGotPtr->getSrc(0)); | 976 auto *T = llvm::cast<Variable>(DefGotPtr->getSrc(0)); |
968 loadNamedConstantRelocatablePIC(GlobalOffsetTable, T, | 977 loadNamedConstantRelocatablePIC(Ctx->getGlobalString(GlobalOffsetTable), T, |
969 [this, T](Variable *PC) { _add(T, PC, T); }); | 978 [this, T](Variable *PC) { _add(T, PC, T); }); |
970 _mov(GotPtr, T); | 979 _mov(GotPtr, T); |
971 DefGotPtr->setDeleted(); | 980 DefGotPtr->setDeleted(); |
972 } | 981 } |
973 | 982 |
974 void TargetARM32::loadNamedConstantRelocatablePIC( | 983 void TargetARM32::loadNamedConstantRelocatablePIC( |
975 const IceString &Name, Variable *Register, | 984 GlobalString Name, Variable *Register, |
976 std::function<void(Variable *PC)> Finish) { | 985 std::function<void(Variable *PC)> Finish) { |
977 assert(SandboxingType == ST_Nonsfi); | 986 assert(SandboxingType == ST_Nonsfi); |
978 // We makeReg() here instead of getPhysicalRegister() because the latter ends | 987 // We makeReg() here instead of getPhysicalRegister() because the latter ends |
979 // up creating multi-blocks temporaries that liveness fails to validate. | 988 // up creating multi-blocks temporaries that liveness fails to validate. |
980 auto *PC = makeReg(IceType_i32, RegARM32::Reg_pc); | 989 auto *PC = makeReg(IceType_i32, RegARM32::Reg_pc); |
981 | 990 |
982 auto *AddPcReloc = RelocOffset::create(Ctx); | 991 auto *AddPcReloc = RelocOffset::create(Ctx); |
983 AddPcReloc->setSubtract(true); | 992 AddPcReloc->setSubtract(true); |
984 auto *AddPcLabel = InstARM32Label::create(Func, this); | 993 auto *AddPcLabel = InstARM32Label::create(Func, this); |
985 AddPcLabel->setRelocOffset(AddPcReloc); | 994 AddPcLabel->setRelocOffset(AddPcReloc); |
986 | 995 |
987 auto *MovwReloc = RelocOffset::create(Ctx); | 996 auto *MovwReloc = RelocOffset::create(Ctx); |
988 auto *MovwLabel = InstARM32Label::create(Func, this); | 997 auto *MovwLabel = InstARM32Label::create(Func, this); |
989 MovwLabel->setRelocOffset(MovwReloc); | 998 MovwLabel->setRelocOffset(MovwReloc); |
990 | 999 |
991 auto *MovtReloc = RelocOffset::create(Ctx); | 1000 auto *MovtReloc = RelocOffset::create(Ctx); |
992 auto *MovtLabel = InstARM32Label::create(Func, this); | 1001 auto *MovtLabel = InstARM32Label::create(Func, this); |
993 MovtLabel->setRelocOffset(MovtReloc); | 1002 MovtLabel->setRelocOffset(MovtReloc); |
994 | 1003 |
995 // The EmitString for these constant relocatables have hardcoded offsets | 1004 // The EmitString for these constant relocatables have hardcoded offsets |
996 // attached to them. This could be dangerous if, e.g., we ever implemented | 1005 // attached to them. This could be dangerous if, e.g., we ever implemented |
997 // instruction scheduling but llvm-mc currently does not support | 1006 // instruction scheduling but llvm-mc currently does not support |
998 // | 1007 // |
999 // movw reg, #:lower16:(Symbol - Label - Number) | 1008 // movw reg, #:lower16:(Symbol - Label - Number) |
1000 // movt reg, #:upper16:(Symbol - Label - Number) | 1009 // movt reg, #:upper16:(Symbol - Label - Number) |
1001 // | 1010 // |
1002 // relocations. | 1011 // relocations. |
1003 static constexpr RelocOffsetT PcOffset = -8; | 1012 static constexpr RelocOffsetT PcOffset = -8; |
1004 auto *CRLower = Ctx->getConstantSym(PcOffset, {MovwReloc, AddPcReloc}, Name, | 1013 auto *CRLower = Ctx->getConstantSymWithEmitString( |
1005 Name + " -16"); | 1014 PcOffset, {MovwReloc, AddPcReloc}, Name, Name + " -16"); |
1006 auto *CRUpper = Ctx->getConstantSym(PcOffset, {MovtReloc, AddPcReloc}, Name, | 1015 auto *CRUpper = Ctx->getConstantSymWithEmitString( |
1007 Name + " -12"); | 1016 PcOffset, {MovtReloc, AddPcReloc}, Name, Name + " -12"); |
1008 | 1017 |
1009 Context.insert(MovwLabel); | 1018 Context.insert(MovwLabel); |
1010 _movw(Register, CRLower); | 1019 _movw(Register, CRLower); |
1011 Context.insert(MovtLabel); | 1020 Context.insert(MovtLabel); |
1012 _movt(Register, CRUpper); | 1021 _movt(Register, CRUpper); |
1013 // PC = fake-def to keep liveness consistent. | 1022 // PC = fake-def to keep liveness consistent. |
1014 Context.insert<InstFakeDef>(PC); | 1023 Context.insert<InstFakeDef>(PC); |
1015 Context.insert(AddPcLabel); | 1024 Context.insert(AddPcLabel); |
1016 Finish(PC); | 1025 Finish(PC); |
1017 } | 1026 } |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 return ARM32_STACK_ALIGNMENT_BYTES; | 1209 return ARM32_STACK_ALIGNMENT_BYTES; |
1201 } | 1210 } |
1202 | 1211 |
1203 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { | 1212 bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
1204 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { | 1213 if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) { |
1205 return Br->optimizeBranch(NextNode); | 1214 return Br->optimizeBranch(NextNode); |
1206 } | 1215 } |
1207 return false; | 1216 return false; |
1208 } | 1217 } |
1209 | 1218 |
1210 IceString TargetARM32::getRegName(RegNumT RegNum, Type Ty) const { | 1219 const char *TargetARM32::getRegName(RegNumT RegNum, Type Ty) const { |
1211 (void)Ty; | 1220 (void)Ty; |
1212 return RegARM32::getRegName(RegNum); | 1221 return RegARM32::getRegName(RegNum); |
1213 } | 1222 } |
1214 | 1223 |
1215 Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) { | 1224 Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) { |
1216 static const Type DefaultType[] = { | 1225 static const Type DefaultType[] = { |
1217 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ | 1226 #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr, \ |
1218 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ | 1227 isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init) \ |
1219 (isFP32) \ | 1228 (isFP32) \ |
1220 ? IceType_f32 \ | 1229 ? IceType_f32 \ |
(...skipping 1085 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2306 _mov(Dest, T); | 2315 _mov(Dest, T); |
2307 } | 2316 } |
2308 | 2317 |
2309 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { | 2318 void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) { |
2310 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) | 2319 if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi)) |
2311 return; | 2320 return; |
2312 Variable *SrcLoReg = legalizeToReg(SrcLo); | 2321 Variable *SrcLoReg = legalizeToReg(SrcLo); |
2313 switch (Ty) { | 2322 switch (Ty) { |
2314 default: | 2323 default: |
2315 llvm_unreachable( | 2324 llvm_unreachable( |
2316 ("Unexpected type in div0Check: " + typeIceString(Ty)).c_str()); | 2325 ("Unexpected type in div0Check: " + typeStdString(Ty)).c_str()); |
2317 case IceType_i8: | 2326 case IceType_i8: |
2318 case IceType_i16: { | 2327 case IceType_i16: { |
2319 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); | 2328 Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty)); |
2320 Variable *T = makeReg(IceType_i32); | 2329 Variable *T = makeReg(IceType_i32); |
2321 _lsls(T, SrcLoReg, ShAmtImm); | 2330 _lsls(T, SrcLoReg, ShAmtImm); |
2322 Context.insert<InstFakeUse>(T); | 2331 Context.insert<InstFakeUse>(T); |
2323 } break; | 2332 } break; |
2324 case IceType_i32: { | 2333 case IceType_i32: { |
2325 _tst(SrcLoReg, SrcLoReg); | 2334 _tst(SrcLoReg, SrcLoReg); |
2326 break; | 2335 break; |
(...skipping 3629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5956 } | 5965 } |
5957 return Reg; | 5966 return Reg; |
5958 } | 5967 } |
5959 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 5968 } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
5960 Variable *Reg = makeReg(Ty, RegNum); | 5969 Variable *Reg = makeReg(Ty, RegNum); |
5961 if (SandboxingType != ST_Nonsfi) { | 5970 if (SandboxingType != ST_Nonsfi) { |
5962 _movw(Reg, C); | 5971 _movw(Reg, C); |
5963 _movt(Reg, C); | 5972 _movt(Reg, C); |
5964 } else { | 5973 } else { |
5965 auto *GotAddr = legalizeToReg(GotPtr); | 5974 auto *GotAddr = legalizeToReg(GotPtr); |
5966 const IceString CGotoffName = createGotoffRelocation(C); | 5975 GlobalString CGotoffName = createGotoffRelocation(C); |
5967 loadNamedConstantRelocatablePIC( | 5976 loadNamedConstantRelocatablePIC( |
5968 CGotoffName, Reg, [this, Reg](Variable *PC) { | 5977 CGotoffName, Reg, [this, Reg](Variable *PC) { |
5969 _ldr(Reg, OperandARM32Mem::create(Func, IceType_i32, PC, Reg)); | 5978 _ldr(Reg, OperandARM32Mem::create(Func, IceType_i32, PC, Reg)); |
5970 }); | 5979 }); |
5971 _add(Reg, GotAddr, Reg); | 5980 _add(Reg, GotAddr, Reg); |
5972 } | 5981 } |
5973 return Reg; | 5982 return Reg; |
5974 } else { | 5983 } else { |
5975 assert(isScalarFloatingType(Ty)); | 5984 assert(isScalarFloatingType(Ty)); |
5976 uint32_t ModifiedImm; | 5985 uint32_t ModifiedImm; |
5977 if (OperandARM32FlexFpImm::canHoldImm(From, &ModifiedImm)) { | 5986 if (OperandARM32FlexFpImm::canHoldImm(From, &ModifiedImm)) { |
5978 Variable *T = makeReg(Ty, RegNum); | 5987 Variable *T = makeReg(Ty, RegNum); |
5979 _mov(T, | 5988 _mov(T, |
5980 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); | 5989 OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm)); |
5981 return T; | 5990 return T; |
5982 } | 5991 } |
5983 | 5992 |
5984 if (Ty == IceType_f64 && isFloatingPointZero(From)) { | 5993 if (Ty == IceType_f64 && isFloatingPointZero(From)) { |
5985 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 | 5994 // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32 |
5986 // because ARM does not have a veor instruction with S registers. | 5995 // because ARM does not have a veor instruction with S registers. |
5987 Variable *T = makeReg(IceType_f64, RegNum); | 5996 Variable *T = makeReg(IceType_f64, RegNum); |
5988 Context.insert<InstFakeDef>(T); | 5997 Context.insert<InstFakeDef>(T); |
5989 _veor(T, T, T); | 5998 _veor(T, T, T); |
5990 return T; | 5999 return T; |
5991 } | 6000 } |
5992 | 6001 |
5993 // Load floats/doubles from literal pool. | 6002 // Load floats/doubles from literal pool. |
5994 std::string Buffer; | 6003 auto *CFrom = llvm::cast<Constant>(From); |
5995 llvm::raw_string_ostream StrBuf(Buffer); | 6004 assert(CFrom->getShouldBePooled()); |
5996 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf); | 6005 Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName()); |
5997 llvm::cast<Constant>(From)->setShouldBePooled(true); | |
5998 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str()); | |
5999 Variable *BaseReg = nullptr; | 6006 Variable *BaseReg = nullptr; |
6000 if (SandboxingType == ST_Nonsfi) { | 6007 if (SandboxingType == ST_Nonsfi) { |
6001 // vldr does not support the [base, index] addressing mode, so we need | 6008 // vldr does not support the [base, index] addressing mode, so we need |
6002 // to legalize Offset to a register. Otherwise, we could simply | 6009 // to legalize Offset to a register. Otherwise, we could simply |
6003 // vldr dest, [got, reg(Offset)] | 6010 // vldr dest, [got, reg(Offset)] |
6004 BaseReg = legalizeToReg(Offset); | 6011 BaseReg = legalizeToReg(Offset); |
6005 } else { | 6012 } else { |
6006 BaseReg = makeReg(getPointerType()); | 6013 BaseReg = makeReg(getPointerType()); |
6007 _movw(BaseReg, Offset); | 6014 _movw(BaseReg, Offset); |
6008 _movt(BaseReg, Offset); | 6015 _movt(BaseReg, Offset); |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6706 } | 6713 } |
6707 createAutoBundle(); | 6714 createAutoBundle(); |
6708 Target->_sub(SP, SP, SubAmount); | 6715 Target->_sub(SP, SP, SubAmount); |
6709 Target->_bic(SP, SP, memOpBicMask(Target->Func)); | 6716 Target->_bic(SP, SP, memOpBicMask(Target->Func)); |
6710 } | 6717 } |
6711 | 6718 |
6712 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) | 6719 TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
6713 : TargetDataLowering(Ctx) {} | 6720 : TargetDataLowering(Ctx) {} |
6714 | 6721 |
6715 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, | 6722 void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars, |
6716 const IceString &SectionSuffix) { | 6723 const std::string &SectionSuffix) { |
6717 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | 6724 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); |
6718 switch (Ctx->getFlags().getOutFileType()) { | 6725 switch (Ctx->getFlags().getOutFileType()) { |
6719 case FT_Elf: { | 6726 case FT_Elf: { |
6720 ELFObjectWriter *Writer = Ctx->getObjectWriter(); | 6727 ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
6721 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix, | 6728 Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix, |
6722 IsPIC); | 6729 IsPIC); |
6723 } break; | 6730 } break; |
6724 case FT_Asm: | 6731 case FT_Asm: |
6725 case FT_Iasm: { | 6732 case FT_Iasm: { |
6726 const IceString &TranslateOnly = Ctx->getFlags().getTranslateOnly(); | 6733 const std::string TranslateOnly = Ctx->getFlags().getTranslateOnly(); |
6727 OstreamLocker _(Ctx); | 6734 OstreamLocker _(Ctx); |
6728 for (const VariableDeclaration *Var : Vars) { | 6735 for (const VariableDeclaration *Var : Vars) { |
6729 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { | 6736 if (GlobalContext::matchSymbolName(Var->getName(), TranslateOnly)) { |
6730 emitGlobal(*Var, SectionSuffix); | 6737 emitGlobal(*Var, SectionSuffix); |
6731 } | 6738 } |
6732 } | 6739 } |
6733 } break; | 6740 } break; |
6734 } | 6741 } |
6735 } | 6742 } |
6736 | 6743 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6773 } | 6780 } |
6774 }; | 6781 }; |
6775 const char ConstantPoolEmitterTraits<double>::AsmTag[] = ".quad"; | 6782 const char ConstantPoolEmitterTraits<double>::AsmTag[] = ".quad"; |
6776 const char ConstantPoolEmitterTraits<double>::TypeName[] = "f64"; | 6783 const char ConstantPoolEmitterTraits<double>::TypeName[] = "f64"; |
6777 | 6784 |
6778 template <typename T> | 6785 template <typename T> |
6779 void emitConstant( | 6786 void emitConstant( |
6780 Ostream &Str, | 6787 Ostream &Str, |
6781 const typename ConstantPoolEmitterTraits<T>::ConstantType *Const) { | 6788 const typename ConstantPoolEmitterTraits<T>::ConstantType *Const) { |
6782 using Traits = ConstantPoolEmitterTraits<T>; | 6789 using Traits = ConstantPoolEmitterTraits<T>; |
6783 Const->emitPoolLabel(Str); | 6790 Str << Const->getLabelName(); |
6784 Str << ":\n\t" << Traits::AsmTag << "\t0x"; | 6791 Str << ":\n\t" << Traits::AsmTag << "\t0x"; |
6785 T Value = Const->getValue(); | 6792 T Value = Const->getValue(); |
6786 Str.write_hex(Traits::bitcastToUint64(Value)); | 6793 Str.write_hex(Traits::bitcastToUint64(Value)); |
6787 Str << "\t/* " << Traits::TypeName << " " << Value << " */\n"; | 6794 Str << "\t/* " << Traits::TypeName << " " << Value << " */\n"; |
6788 } | 6795 } |
6789 | 6796 |
6790 template <typename T> void emitConstantPool(GlobalContext *Ctx) { | 6797 template <typename T> void emitConstantPool(GlobalContext *Ctx) { |
6791 if (!BuildDefs::dump()) { | 6798 if (!BuildDefs::dump()) { |
6792 return; | 6799 return; |
6793 } | 6800 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6904 // However, for compatibility with current NaCl LLVM, don't claim that. | 6911 // However, for compatibility with current NaCl LLVM, don't claim that. |
6905 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6912 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
6906 } | 6913 } |
6907 | 6914 |
6908 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6915 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
6909 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6916 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
6910 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6917 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
6911 | 6918 |
6912 } // end of namespace ARM32 | 6919 } // end of namespace ARM32 |
6913 } // end of namespace Ice | 6920 } // end of namespace Ice |
OLD | NEW |