| 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 |