1b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===- subzero/src/IceTargetLoweringARM32.h - ARM32 lowering ----*- C++ -*-===// 2b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 3b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// The Subzero Code Generator 4b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 5b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// This file is distributed under the University of Illinois Open Source 6b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// License. See LICENSE.TXT for details. 7b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung// 8b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===// 99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file 1192a6e5b08ec68e7076d637ebc680da2fcc346a00Jim Stichnoth/// \brief Declares the TargetLoweringARM32 class, which implements the 129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// TargetLowering interface for the ARM 32-bit architecture. 139612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 14b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung//===----------------------------------------------------------------------===// 15b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 16b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#ifndef SUBZERO_SRC_ICETARGETLOWERINGARM32_H 17b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#define SUBZERO_SRC_ICETARGETLOWERINGARM32_H 18b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1953611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto#include "IceAssemblerARM32.h" 20b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#include "IceDefs.h" 21b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "IceInstARM32.h" 22b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#include "IceRegistersARM32.h" 23b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#include "IceTargetLowering.h" 24b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 25a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto#include <utility> 26a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto 27b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungnamespace Ice { 284a56686b5b56db6803f90ad53514bf2fa190d9f7John Portonamespace ARM32 { 29b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 306ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung// Class encapsulating ARM cpu features / instruction set. 316ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungclass TargetARM32Features { 326ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung TargetARM32Features() = delete; 336ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung TargetARM32Features(const TargetARM32Features &) = delete; 346ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung TargetARM32Features &operator=(const TargetARM32Features &) = delete; 356ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 366ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungpublic: 376ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung explicit TargetARM32Features(const ClFlags &Flags); 386ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 396ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung enum ARM32InstructionSet { 406ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Begin, 416ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung // Neon is the PNaCl baseline instruction set. 426ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung Neon = Begin, 436ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung HWDivArm, // HW divide in ARM mode (not just Thumb mode). 446ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung End 456ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung }; 466ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 476ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung bool hasFeature(ARM32InstructionSet I) const { return I <= InstructionSet; } 486ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 496ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voungprivate: 506ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung ARM32InstructionSet InstructionSet = ARM32InstructionSet::Begin; 516ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung}; 526ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 536ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung// The target lowering logic for ARM32. 54b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungclass TargetARM32 : public TargetLowering { 55b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetARM32() = delete; 56b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetARM32(const TargetARM32 &) = delete; 57b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetARM32 &operator=(const TargetARM32 &) = delete; 58b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 59b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungpublic: 605403f5dc6b43f077bbbee369bbe178b660654366Karl Schimpf static void staticInit(GlobalContext *Ctx); 61467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth 62467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth static bool shouldBePooled(const Constant *C) { 63467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(C)) { 64467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth return !Utils::isPositiveZero(ConstDouble->getValue()); 65467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth } 66467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth if (llvm::isa<ConstantFloat>(C)) 67467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth return true; 68467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth return false; 69467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth } 70467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth 7132f9ccef8dee33110cc9ebdca2853d6a078752edNicolas Capens static ::Ice::Type getPointerType() { return ::Ice::IceType_i32; } 7232f9ccef8dee33110cc9ebdca2853d6a078752edNicolas Capens 73b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung // TODO(jvoung): return a unique_ptr. 7453611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) { 7553611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto return makeUnique<TargetARM32>(Func); 7653611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto } 7753611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto 7853611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto std::unique_ptr<::Ice::Assembler> createAssembler() const override { 79dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto const bool IsNonsfi = SandboxingType == ST_Nonsfi; 80dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto return makeUnique<ARM32::AssemblerARM32>(IsNonsfi); 8153611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto } 82b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 834a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void initNodeForLowering(CfgNode *Node) override { 84eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Computations.forgetProducers(); 85eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Computations.recordProducers(Node); 86eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Computations.dump(Func); 874a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 884a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 89b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void translateOm1() override; 90b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void translateO2() override; 91b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; 92b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 93b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung SizeT getNumRegisters() const override { return RegARM32::Reg_NUM; } 948aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth Variable *getPhysicalRegister(RegNumT RegNum, 958aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth Type Ty = IceType_void) override; 96467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth const char *getRegName(RegNumT RegNum, Type Ty) const override; 97e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector getRegisterSet(RegSetMask Include, 98e82b560e649f8a68bcb252b9b002708e74d962d3John Porto RegSetMask Exclude) const override; 99e82b560e649f8a68bcb252b9b002708e74d962d3John Porto const SmallBitVector & 100c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth getRegistersForVariable(const Variable *Var) const override { 101c59288b334b91f4c0b2edf0de7415c68c760aa12Jim Stichnoth RegClass RC = Var->getRegClass(); 102658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk switch (RC) { 103658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk default: 104658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk assert(RC < RC_Target); 105658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk return TypeToRegisterSet[RC]; 106658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk case RegARM32::RCARM32_QtoS: 107658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk return TypeToRegisterSet[RC]; 108658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 109b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung } 110e82b560e649f8a68bcb252b9b002708e74d962d3John Porto const SmallBitVector & 111b40595a17b83cca5d11f8d056a4ac5a4d8102a84Jim Stichnoth getAllRegistersForVariable(const Variable *Var) const override { 112b40595a17b83cca5d11f8d056a4ac5a4d8102a84Jim Stichnoth RegClass RC = Var->getRegClass(); 113658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk assert((RegARM32::RegClassARM32)RC < RegARM32::RCARM32_NUM); 114b40595a17b83cca5d11f8d056a4ac5a4d8102a84Jim Stichnoth return TypeToRegisterSetUnfiltered[RC]; 115b40595a17b83cca5d11f8d056a4ac5a4d8102a84Jim Stichnoth } 116e82b560e649f8a68bcb252b9b002708e74d962d3John Porto const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override { 117bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto return RegisterAliases[Reg]; 118bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto } 119b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung bool hasFramePointer() const override { return UsesFramePointer; } 120e39d0ca2c6a0cbc6e68b6d4323f0f8cfb1914840David Sehr void setHasFramePointer() override { UsesFramePointer = true; } 1218aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT getStackReg() const override { return RegARM32::Reg_sp; } 1228aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT getFrameReg() const override { return RegARM32::Reg_fp; } 1238aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT getFrameOrStackReg() const override { 1242f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr return UsesFramePointer ? getFrameReg() : getStackReg(); 125b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung } 1268aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT getReservedTmpReg() const { return RegARM32::Reg_ip; } 12728068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung 128b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung size_t typeWidthInBytesOnStack(Type Ty) const override { 12957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // Round up to the next multiple of 4 bytes. In particular, i1, i8, and i16 13057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // are rounded up to 4 bytes. 131b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung return (typeWidthInBytes(Ty) + 3) & ~3; 132b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung } 133e39d0ca2c6a0cbc6e68b6d4323f0f8cfb1914840David Sehr uint32_t getStackAlignment() const override; 1342f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr void reserveFixedAllocaArea(size_t Size, size_t Align) override { 135614140e2be672234e28e3179eba9f973eb6a19c6John Porto FixedAllocaSizeBytes = Size; 136614140e2be672234e28e3179eba9f973eb6a19c6John Porto assert(llvm::isPowerOf2_32(Align)); 137614140e2be672234e28e3179eba9f973eb6a19c6John Porto FixedAllocaAlignBytes = Align; 138614140e2be672234e28e3179eba9f973eb6a19c6John Porto PrologEmitsFixedAllocas = true; 1392f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr } 1402f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr int32_t getFrameFixedAllocaOffset() const override { 141614140e2be672234e28e3179eba9f973eb6a19c6John Porto return FixedAllocaSizeBytes - (SpillAreaSizeBytes - MaxOutArgsSizeBytes); 1422f3b8ec812321b1549bc1714a239b9dd0c95ebd7David Sehr } 143614140e2be672234e28e3179eba9f973eb6a19c6John Porto uint32_t maxOutArgsSizeBytes() const override { return MaxOutArgsSizeBytes; } 1440fa6c5a062f465360448a672abed3b916b413ca8Jan Voung 1456d47bcdcf16ce8eddc737d4f26baad9653604048Andrew Scull bool shouldSplitToVariable64On32(Type Ty) const override { 1466d47bcdcf16ce8eddc737d4f26baad9653604048Andrew Scull return Ty == IceType_i64; 1476d47bcdcf16ce8eddc737d4f26baad9653604048Andrew Scull } 1486d47bcdcf16ce8eddc737d4f26baad9653604048Andrew Scull 14987f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull // TODO(ascull): what size is best for ARM? 15087f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull SizeT getMinJumpTableSize() const override { return 3; } 15186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull void emitJumpTable(const Cfg *Func, 15286df4e9e6d183f07638440afd2c225b485c03917Andrew Scull const InstJumpTable *JumpTable) const override; 15387f80c128a9e2bc95829cd1aac2bbc3c44b44ac1Andrew Scull 154b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void emitVariable(const Variable *Var) const override; 15576bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung 15676bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung void emit(const ConstantUndef *C) const final; 15776bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung void emit(const ConstantInteger32 *C) const final; 15876bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung void emit(const ConstantInteger64 *C) const final; 15976bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung void emit(const ConstantFloat *C) const final; 16076bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung void emit(const ConstantDouble *C) const final; 1618ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth void emit(const ConstantRelocatable *C) const final; 16276bb0bec94b99765be86525fa1ae2c607e66d9b6Jan Voung 163b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void lowerArguments() override; 164b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void addProlog(CfgNode *Node) override; 165b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void addEpilog(CfgNode *Node) override; 166b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 167b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand *loOperand(Operand *Operand); 168b3401d27a236b81393092b4d571df473b5bba64bJan Voung Operand *hiOperand(Operand *Operand); 1690fa6c5a062f465360448a672abed3b916b413ca8Jan Voung void finishArgumentLowering(Variable *Arg, Variable *FramePtr, 1703f6b47d53174f4f44d8b7c32d806fc5b5288a218John Porto size_t BasicFrameOffset, size_t *InArgsSizeBytes); 171b3401d27a236b81393092b4d571df473b5bba64bJan Voung 1726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung bool hasCPUFeature(TargetARM32Features::ARM32InstructionSet I) const { 1736ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung return CPUFeatures.hasFeature(I); 1746ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 175ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 176ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto enum OperandLegalization { 177ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Legal_Reg = 1 << 0, /// physical register, not stack location 178ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Legal_Flex = 1 << 1, /// A flexible operand2, which can hold rotated small 179ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto /// immediates, shifted registers, or modified fp imm. 180ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Legal_Mem = 1 << 2, /// includes [r0, r1 lsl #2] as well as [sp, #12] 181866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto Legal_Rematerializable = 1 << 3, 1828ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth Legal_Default = ~Legal_Rematerializable, 183ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto }; 184ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 185ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto using LegalMask = uint32_t; 1865fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT()); 1878ff4b2819944bc4f02fb29204a1fa5ba7dea5682Jim Stichnoth Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default, 1885fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler RegNumT RegNum = RegNumT()); 1895fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT()); 190ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto 1912758bb077495d7a88b3d66368b3d760de61cedc7John Porto OperandARM32ShAmtImm *shAmtImm(uint32_t ShAmtImm) const { 1922758bb077495d7a88b3d66368b3d760de61cedc7John Porto assert(ShAmtImm < 32); 1932758bb077495d7a88b3d66368b3d760de61cedc7John Porto return OperandARM32ShAmtImm::create( 1942758bb077495d7a88b3d66368b3d760de61cedc7John Porto Func, 1952758bb077495d7a88b3d66368b3d760de61cedc7John Porto llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmtImm & 0x1F))); 1962758bb077495d7a88b3d66368b3d760de61cedc7John Porto } 1972758bb077495d7a88b3d66368b3d760de61cedc7John Porto 198ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto GlobalContext *getCtx() const { return Ctx; } 199d062f73a671032d93860dfb2774a7fa4acd0a0aeJan Voung 200b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungprotected: 201b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung explicit TargetARM32(Cfg *Func); 202b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 203b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void postLower() override; 204b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 2057b3d9cbb1c1697e03c616162382d945f35c37347John Porto enum SafeBoolChain { 2067b3d9cbb1c1697e03c616162382d945f35c37347John Porto SBC_No, 2077b3d9cbb1c1697e03c616162382d945f35c37347John Porto SBC_Yes, 2087b3d9cbb1c1697e03c616162382d945f35c37347John Porto }; 2097b3d9cbb1c1697e03c616162382d945f35c37347John Porto 2108cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerAlloca(const InstAlloca *Instr) override; 2118cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth SafeBoolChain lowerInt1Arithmetic(const InstArithmetic *Instr); 212ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void lowerInt64Arithmetic(InstArithmetic::OpKind Op, Variable *Dest, 213ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Operand *Src0, Operand *Src1); 2148cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerArithmetic(const InstArithmetic *Instr) override; 2158cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerAssign(const InstAssign *Instr) override; 2168cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerBr(const InstBr *Instr) override; 2178cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerCall(const InstCall *Instr) override; 2188cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerCast(const InstCast *Instr) override; 2198cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerExtractElement(const InstExtractElement *Instr) override; 2207b3d9cbb1c1697e03c616162382d945f35c37347John Porto 2217b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// CondWhenTrue is a helper type returned by every method in the lowering 2227b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// that emits code to set the condition codes. 2237b3d9cbb1c1697e03c616162382d945f35c37347John Porto class CondWhenTrue { 2247b3d9cbb1c1697e03c616162382d945f35c37347John Porto public: 2257b3d9cbb1c1697e03c616162382d945f35c37347John Porto explicit CondWhenTrue(CondARM32::Cond T0, 2267b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondARM32::Cond T1 = CondARM32::kNone) 2277b3d9cbb1c1697e03c616162382d945f35c37347John Porto : WhenTrue0(T0), WhenTrue1(T1) { 2287b3d9cbb1c1697e03c616162382d945f35c37347John Porto assert(T1 == CondARM32::kNone || T0 != CondARM32::kNone); 2297b3d9cbb1c1697e03c616162382d945f35c37347John Porto assert(T1 != T0 || T0 == CondARM32::kNone); 2307b3d9cbb1c1697e03c616162382d945f35c37347John Porto } 2317b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondARM32::Cond WhenTrue0; 2327b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondARM32::Cond WhenTrue1; 2337b3d9cbb1c1697e03c616162382d945f35c37347John Porto 2347b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// invert returns a new object with WhenTrue0 and WhenTrue1 inverted. 2357b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondWhenTrue invert() const { 2367b3d9cbb1c1697e03c616162382d945f35c37347John Porto switch (WhenTrue0) { 2377b3d9cbb1c1697e03c616162382d945f35c37347John Porto default: 2387b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (WhenTrue1 == CondARM32::kNone) 2397b3d9cbb1c1697e03c616162382d945f35c37347John Porto return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0)); 2407b3d9cbb1c1697e03c616162382d945f35c37347John Porto return CondWhenTrue(InstARM32::getOppositeCondition(WhenTrue0), 2417b3d9cbb1c1697e03c616162382d945f35c37347John Porto InstARM32::getOppositeCondition(WhenTrue1)); 2427b3d9cbb1c1697e03c616162382d945f35c37347John Porto case CondARM32::AL: 2437b3d9cbb1c1697e03c616162382d945f35c37347John Porto return CondWhenTrue(CondARM32::kNone); 2447b3d9cbb1c1697e03c616162382d945f35c37347John Porto case CondARM32::kNone: 2457b3d9cbb1c1697e03c616162382d945f35c37347John Porto return CondWhenTrue(CondARM32::AL); 2467b3d9cbb1c1697e03c616162382d945f35c37347John Porto } 2477b3d9cbb1c1697e03c616162382d945f35c37347John Porto } 2487b3d9cbb1c1697e03c616162382d945f35c37347John Porto }; 2497b3d9cbb1c1697e03c616162382d945f35c37347John Porto 2507b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondWhenTrue lowerFcmpCond(const InstFcmp *Instr); 2514a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void lowerFcmp(const InstFcmp *Instr) override; 252ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondWhenTrue lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, 253ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Operand *Src0, Operand *Src1); 254ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondWhenTrue lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, 255ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Operand *Src1); 256ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondWhenTrue lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0, 257ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto Operand *Src1); 2584b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto CondWhenTrue lowerIcmpCond(InstIcmp::ICond Condition, Operand *Src0, 2594b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto Operand *Src1); 2607b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondWhenTrue lowerIcmpCond(const InstIcmp *Instr); 2614a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void lowerIcmp(const InstIcmp *Instr) override; 2624b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// Emits the basic sequence for lower-linked/store-exclusive loops: 2634b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// 2644b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// retry: 2654b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// ldrex tmp, [Addr] 2664b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// StoreValue = Operation(tmp) 2674b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// strexCond success, StoreValue, [Addr] 2684b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// cmpCond success, #0 2694b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// bne retry 2704b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// 2714b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// Operation needs to return which value to strex in Addr, it must not change 2724b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// the flags if Cond is not AL, and must not emit any instructions that could 2734b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// end up writing to memory. Operation also needs to handle fake-defing for 2744b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto /// i64 handling. 2754b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto void 2764b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto lowerLoadLinkedStoreExclusive(Type Ty, Operand *Addr, 2774b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto std::function<Variable *(Variable *)> Operation, 2784b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto CondARM32::Cond Cond = CondARM32::AL); 2794b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto void lowerInt64AtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, 2804b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto Operand *Val); 281578f1161ad7a3ef98c90d88e5734940523d1f8e0John Porto void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, 282578f1161ad7a3ef98c90d88e5734940523d1f8e0John Porto Operand *Val); 28367c7c4161ad5bcf234357348a421e313932a8ee3Eric Holk void lowerBreakpoint(const InstBreakpoint *Instr) override; 2848cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerIntrinsicCall(const InstIntrinsicCall *Instr) override; 2858cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerInsertElement(const InstInsertElement *Instr) override; 2868cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerLoad(const InstLoad *Instr) override; 2878cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerPhi(const InstPhi *Instr) override; 2888cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerRet(const InstRet *Instr) override; 2898cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerSelect(const InstSelect *Instr) override; 290a47c11c7f17022050043d69c0802241e0747a056John Porto void lowerShuffleVector(const InstShuffleVector *Instr) override; 2918cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerStore(const InstStore *Instr) override; 2928cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerSwitch(const InstSwitch *Instr) override; 2938cfeb69e17190d3bfe22a8a1cbd7679a114d68cfJim Stichnoth void lowerUnreachable(const InstUnreachable *Instr) override; 294b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void prelowerPhis() override; 295f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override; 296c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto void genTargetHelperCallFor(Inst *Instr) override; 297b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void doAddressOptLoad() override; 298b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung void doAddressOptStore() override; 299aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu void randomlyInsertNop(float Probability, 300aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu RandomNumberGenerator &RNG) override; 301b3401d27a236b81393092b4d571df473b5bba64bJan Voung 302befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty); 303b3401d27a236b81393092b4d571df473b5bba64bJan Voung 304578f1161ad7a3ef98c90d88e5734940523d1f8e0John Porto Variable64On32 *makeI64RegPair(); 3055fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT()); 306b3401d27a236b81393092b4d571df473b5bba64bJan Voung static Type stackSlotType(); 3075fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT()); 308614140e2be672234e28e3179eba9f973eb6a19c6John Porto void alignRegisterPow2(Variable *Reg, uint32_t Align, 3095fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler RegNumT TmpRegNum = RegNumT()); 310b3401d27a236b81393092b4d571df473b5bba64bJan Voung 3119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Returns a vector in a register with the given constant entries. 3125fa0a5f7f730f33e6987527a261de8d833d7585cReed Kotler Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT()); 313b3401d27a236b81393092b4d571df473b5bba64bJan Voung 314aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu void 3158aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth makeRandomRegisterPermutation(llvm::SmallVectorImpl<RegNumT> &Permutation, 316e82b560e649f8a68bcb252b9b002708e74d962d3John Porto const SmallBitVector &ExcludeRegisters, 317aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu uint64_t Salt) const override; 318b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 31957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // If a divide-by-zero check is needed, inserts a: test; branch .LSKIP; trap; 32057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // .LSKIP: <continuation>. If no check is needed nothing is inserted. 3216ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi); 3228072bae156fa62e51e02925997992c4908a2682fAndrew Scull using ExtInstr = void (TargetARM32::*)(Variable *, Variable *, 3238072bae156fa62e51e02925997992c4908a2682fAndrew Scull CondARM32::Cond); 3248072bae156fa62e51e02925997992c4908a2682fAndrew Scull using DivInstr = void (TargetARM32::*)(Variable *, Variable *, Variable *, 3258072bae156fa62e51e02925997992c4908a2682fAndrew Scull CondARM32::Cond); 3266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R, Operand *Src1, 327c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto ExtInstr ExtFunc, DivInstr DivFunc, bool IsRemainder); 3286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 329f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung void lowerCLZ(Variable *Dest, Variable *ValLo, Variable *ValHi); 330f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung 33157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // The following are helpers that insert lowered ARM32 instructions with 33257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // minimal syntactic overhead, so that the lowering code can look as close to 33357e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // assembly as practical. 3343bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _add(Variable *Dest, Variable *Src0, Operand *Src1, 3353bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3361d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred); 3372971997a96b7484165cfedead111c7cafb3073aeJan Voung } 3383bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _adds(Variable *Dest, Variable *Src0, Operand *Src1, 3393bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 34086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung constexpr bool SetFlags = true; 3411d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Add>(Dest, Src0, Src1, Pred, SetFlags); 3427e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 3437e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 3447e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 3452971997a96b7484165cfedead111c7cafb3073aeJan Voung } 3463bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _adc(Variable *Dest, Variable *Src0, Operand *Src1, 3473bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3481d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Adc>(Dest, Src0, Src1, Pred); 3492971997a96b7484165cfedead111c7cafb3073aeJan Voung } 3503bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _and(Variable *Dest, Variable *Src0, Operand *Src1, 3513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3521d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32And>(Dest, Src0, Src1, Pred); 3532971997a96b7484165cfedead111c7cafb3073aeJan Voung } 35466c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung void _asr(Variable *Dest, Variable *Src0, Operand *Src1, 35566c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3561d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Asr>(Dest, Src0, Src1, Pred); 35766c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung } 35855500dbceb14d4223533701158389e89c1f93a5eJan Voung void _bic(Variable *Dest, Variable *Src0, Operand *Src1, 35955500dbceb14d4223533701158389e89c1f93a5eJan Voung CondARM32::Cond Pred = CondARM32::AL) { 3601d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Bic>(Dest, Src0, Src1, Pred); 36155500dbceb14d4223533701158389e89c1f93a5eJan Voung } 3626ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _br(CfgNode *TargetTrue, CfgNode *TargetFalse, 3636ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Condition) { 3641d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Br>(TargetTrue, TargetFalse, Condition); 365b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 3661d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto void _br(CfgNode *Target) { Context.insert<InstARM32Br>(Target); } 367fdc54db71f2478ca17128f82e781aa605ab5a2e4Andrew Scull void _br(CfgNode *Target, CondARM32::Cond Condition) { 3681d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Br>(Target, Condition); 369fdc54db71f2478ca17128f82e781aa605ab5a2e4Andrew Scull } 3706ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _br(InstARM32Label *Label, CondARM32::Cond Condition) { 3711d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Br>(Label, Condition); 3726ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 373ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _cmn(Variable *Src0, Operand *Src1, 374ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 3751d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Cmn>(Src0, Src1, Pred); 376ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 3773bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _cmp(Variable *Src0, Operand *Src1, 3783bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3791d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Cmp>(Src0, Src1, Pred); 3803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 381f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung void _clz(Variable *Dest, Variable *Src0, 382f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3831d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Clz>(Dest, Src0, Pred); 384f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung } 3851d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto void _dmb() { Context.insert<InstARM32Dmb>(); } 3863bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _eor(Variable *Dest, Variable *Src0, Operand *Src1, 3873bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3881d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Eor>(Dest, Src0, Src1, Pred); 3893bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 390ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// _ldr, for all your memory to Variable data moves. It handles all types 391ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// (integer, floating point, and vectors.) Addr needs to be valid for Dest's 392ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// type (e.g., no immediates for vector loads, and no index registers for fp 393ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// loads.) 3943bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _ldr(Variable *Dest, OperandARM32Mem *Addr, 3953bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 3961d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Ldr>(Dest, Addr, Pred); 3973bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 3984b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto InstARM32Ldrex *_ldrex(Variable *Dest, OperandARM32Mem *Addr, 3994b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto CondARM32::Cond Pred = CondARM32::AL) { 4004b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto auto *Ldrex = Context.insert<InstARM32Ldrex>(Dest, Addr, Pred); 401b36757e1cf19a443ed40128b43b8e2f1f8579eb0Jim Stichnoth if (auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest)) { 4021d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeDef>(Dest64->getLo(), Dest); 4031d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeDef>(Dest64->getHi(), Dest); 404b36757e1cf19a443ed40128b43b8e2f1f8579eb0Jim Stichnoth } 4054b6e4b44a8abe5f4c5f209d45828cc1ef1bb6a1eJohn Porto return Ldrex; 406b36757e1cf19a443ed40128b43b8e2f1f8579eb0Jim Stichnoth } 4073bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _lsl(Variable *Dest, Variable *Src0, Operand *Src1, 4083bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 4091d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred); 4103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 411ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _lsls(Variable *Dest, Variable *Src0, Operand *Src1, 412ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 413ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto constexpr bool SetFlags = true; 4141d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Lsl>(Dest, Src0, Src1, Pred, SetFlags); 4157e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 4167e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 4177e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 418ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 41966c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung void _lsr(Variable *Dest, Variable *Src0, Operand *Src1, 42066c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 4211d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Lsr>(Dest, Src0, Src1, Pred); 42266c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung } 4233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _mla(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, 4243bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 4251d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Mla>(Dest, Src0, Src1, Acc, Pred); 4262971997a96b7484165cfedead111c7cafb3073aeJan Voung } 4276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _mls(Variable *Dest, Variable *Src0, Variable *Src1, Variable *Acc, 4286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 4291d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Mls>(Dest, Src0, Src1, Acc, Pred); 4306ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 431ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// _mov, for all your Variable to Variable data movement needs. It handles 432ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// all types (integer, floating point, and vectors), as well as moves between 433ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// Core and VFP registers. This is not a panacea: you must obey the (weird, 434ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// confusing, non-uniform) rules for data moves in ARM. 435ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto void _mov(Variable *Dest, Operand *Src0, 436ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto CondARM32::Cond Pred = CondARM32::AL) { 437ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto // _mov used to be unique in the sense that it would create a temporary 438ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto // automagically if Dest was nullptr. It won't do that anymore, so we keep 439ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto // an assert around just in case there is some untested code path where Dest 440ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto // is nullptr. 441ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto assert(Dest != nullptr); 4423f6b47d53174f4f44d8b7c32d806fc5b5288a218John Porto assert(!llvm::isa<OperandARM32Mem>(Src0)); 4431d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred); 444e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto 445e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto if (Instr->isMultiDest()) { 446e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto // If Instr is multi-dest, then Dest must be a Variable64On32. We add a 447e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto // fake-def for Instr.DestHi here. 448e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto assert(llvm::isa<Variable64On32>(Dest)); 4491d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeDef>(Instr->getDestHi()); 450e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto } 4513bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 452578f1161ad7a3ef98c90d88e5734940523d1f8e0John Porto 453230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth void _mov_redefined(Variable *Dest, Operand *Src0, 454230d4101fb3c591d044406eef27d0ce43ffab53eJim Stichnoth CondARM32::Cond Pred = CondARM32::AL) { 4551d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto auto *Instr = Context.insert<InstARM32Mov>(Dest, Src0, Pred); 456e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto Instr->setDestRedefined(); 457e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto if (Instr->isMultiDest()) { 458e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto // If Instr is multi-dest, then Dest must be a Variable64On32. We add a 459e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto // fake-def for Instr.DestHi here. 460e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto assert(llvm::isa<Variable64On32>(Dest)); 4611d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeDef>(Instr->getDestHi()); 462e0b829f8d2ff3185a885349c37b50144c2191c9aJohn Porto } 463b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 4644a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 465f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf void _nop() { Context.insert<InstARM32Nop>(); } 466f084a57174a1fe74522c8d41cffe578b3f11ae84Karl Schimpf 467658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk // Generates a vmov instruction to extract the given index from a vector 468658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk // register. 469658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk void _extractelement(Variable *Dest, Variable *Src0, uint32_t Index, 470658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk CondARM32::Cond Pred = CondARM32::AL) { 471658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Context.insert<InstARM32Extract>(Dest, Src0, Index, Pred); 472658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 473658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 474658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk // Generates a vmov instruction to insert a value into the given index of a 475658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk // vector register. 476658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk void _insertelement(Variable *Dest, Variable *Src0, uint32_t Index, 477658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk CondARM32::Cond Pred = CondARM32::AL) { 478658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk Context.insert<InstARM32Insert>(Dest, Src0, Index, Pred); 479658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk } 480658bae2023cace91f8489f597c1c82dfe95aaaa2Eric Holk 4817b3d9cbb1c1697e03c616162382d945f35c37347John Porto // -------------------------------------------------------------------------- 4827b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Begin bool folding machinery. 4837b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 4847b3d9cbb1c1697e03c616162382d945f35c37347John Porto // There are three types of boolean lowerings handled by this target: 4857b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 4867b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 1) Boolean expressions leading to a boolean Variable definition 4877b3d9cbb1c1697e03c616162382d945f35c37347John Porto // --------------------------------------------------------------- 4887b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 4897b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Whenever a i1 Variable is live out (i.e., its live range extends beyond 4907b3d9cbb1c1697e03c616162382d945f35c37347John Porto // the defining basic block) we do not fold the operation. We instead 4917b3d9cbb1c1697e03c616162382d945f35c37347John Porto // materialize (i.e., compute) the variable normally, so that it can be used 4927b3d9cbb1c1697e03c616162382d945f35c37347John Porto // when needed. We also materialize i1 values that are not single use to 4937b3d9cbb1c1697e03c616162382d945f35c37347John Porto // avoid code duplication. These expressions are not short circuited. 4947b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 4957b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 2) Boolean expressions leading to a select 4967b3d9cbb1c1697e03c616162382d945f35c37347John Porto // ------------------------------------------ 4977b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 4987b3d9cbb1c1697e03c616162382d945f35c37347John Porto // These include boolean chains leading to a select instruction, as well as 4997b3d9cbb1c1697e03c616162382d945f35c37347John Porto // i1 Sexts. These boolean expressions are lowered to: 5007b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5017b3d9cbb1c1697e03c616162382d945f35c37347John Porto // mov T, <false value> 5027b3d9cbb1c1697e03c616162382d945f35c37347John Porto // CC <- eval(Boolean Expression) 5037b3d9cbb1c1697e03c616162382d945f35c37347John Porto // movCC T, <true value> 5047b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5057b3d9cbb1c1697e03c616162382d945f35c37347John Porto // For Sexts, <false value> is 0, and <true value> is -1. 5067b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5077b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 3) Boolean expressions leading to a br i1 5087b3d9cbb1c1697e03c616162382d945f35c37347John Porto // ----------------------------------------- 5097b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5107b3d9cbb1c1697e03c616162382d945f35c37347John Porto // These are the boolean chains leading to a branch. These chains are 5117b3d9cbb1c1697e03c616162382d945f35c37347John Porto // short-circuited, i.e.: 5127b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5137b3d9cbb1c1697e03c616162382d945f35c37347John Porto // A = or i1 B, C 5147b3d9cbb1c1697e03c616162382d945f35c37347John Porto // br i1 A, label %T, label %F 5157b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5167b3d9cbb1c1697e03c616162382d945f35c37347John Porto // becomes 5177b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5187b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst B 5197b3d9cbb1c1697e03c616162382d945f35c37347John Porto // jne %T 5207b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst B 5217b3d9cbb1c1697e03c616162382d945f35c37347John Porto // jne %T 5227b3d9cbb1c1697e03c616162382d945f35c37347John Porto // j %F 5237b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5247b3d9cbb1c1697e03c616162382d945f35c37347John Porto // and 5257b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5267b3d9cbb1c1697e03c616162382d945f35c37347John Porto // A = and i1 B, C 5277b3d9cbb1c1697e03c616162382d945f35c37347John Porto // br i1 A, label %T, label %F 5287b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5297b3d9cbb1c1697e03c616162382d945f35c37347John Porto // becomes 5307b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5317b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst B 5327b3d9cbb1c1697e03c616162382d945f35c37347John Porto // jeq %F 5337b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst B 5347b3d9cbb1c1697e03c616162382d945f35c37347John Porto // jeq %F 5357b3d9cbb1c1697e03c616162382d945f35c37347John Porto // j %T 5367b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5377b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Arbitrarily long chains are short circuited, e.g 5387b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5397b3d9cbb1c1697e03c616162382d945f35c37347John Porto // A = or i1 B, C 5407b3d9cbb1c1697e03c616162382d945f35c37347John Porto // D = and i1 A, E 5417b3d9cbb1c1697e03c616162382d945f35c37347John Porto // F = and i1 G, H 5427b3d9cbb1c1697e03c616162382d945f35c37347John Porto // I = or i1 D, F 5437b3d9cbb1c1697e03c616162382d945f35c37347John Porto // br i1 I, label %True, label %False 5447b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5457b3d9cbb1c1697e03c616162382d945f35c37347John Porto // becomes 5467b3d9cbb1c1697e03c616162382d945f35c37347John Porto // 5477b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Label[A]: 5487b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst B, 1 5497b3d9cbb1c1697e03c616162382d945f35c37347John Porto // bne Label[D] 5507b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst C, 1 5517b3d9cbb1c1697e03c616162382d945f35c37347John Porto // beq Label[I] 5527b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Label[D]: 5537b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst E, 1 5547b3d9cbb1c1697e03c616162382d945f35c37347John Porto // bne %True 5557b3d9cbb1c1697e03c616162382d945f35c37347John Porto // Label[I] 5567b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst G, 1 5577b3d9cbb1c1697e03c616162382d945f35c37347John Porto // beq %False 5587b3d9cbb1c1697e03c616162382d945f35c37347John Porto // tst H, 1 5597b3d9cbb1c1697e03c616162382d945f35c37347John Porto // beq %False (bne %True) 5607b3d9cbb1c1697e03c616162382d945f35c37347John Porto 5617b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// lowerInt1 materializes Boolean to a Variable. 5627b3d9cbb1c1697e03c616162382d945f35c37347John Porto SafeBoolChain lowerInt1(Variable *Dest, Operand *Boolean); 5637b3d9cbb1c1697e03c616162382d945f35c37347John Porto 5647b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// lowerInt1ForSelect generates the following instruction sequence: 5657b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 5667b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// mov T, FalseValue 5677b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// CC <- eval(Boolean) 5687b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// movCC T, TrueValue 5697b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// mov Dest, T 5707b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 5717b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// It is used for lowering select i1, as well as i1 Sext. 5727b3d9cbb1c1697e03c616162382d945f35c37347John Porto void lowerInt1ForSelect(Variable *Dest, Operand *Boolean, Operand *TrueValue, 5737b3d9cbb1c1697e03c616162382d945f35c37347John Porto Operand *FalseValue); 5747b3d9cbb1c1697e03c616162382d945f35c37347John Porto 5757b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// LowerInt1BranchTarget is used by lowerIntForBranch. It wraps a CfgNode, or 5767b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// an InstARM32Label (but never both) so that, during br i1 lowering, we can 5777b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// create auxiliary labels for short circuiting the condition evaluation. 5787b3d9cbb1c1697e03c616162382d945f35c37347John Porto class LowerInt1BranchTarget { 5797b3d9cbb1c1697e03c616162382d945f35c37347John Porto public: 5807b3d9cbb1c1697e03c616162382d945f35c37347John Porto explicit LowerInt1BranchTarget(CfgNode *const Target) 5817b3d9cbb1c1697e03c616162382d945f35c37347John Porto : NodeTarget(Target) {} 5827b3d9cbb1c1697e03c616162382d945f35c37347John Porto explicit LowerInt1BranchTarget(InstARM32Label *const Target) 5837b3d9cbb1c1697e03c616162382d945f35c37347John Porto : LabelTarget(Target) {} 5847b3d9cbb1c1697e03c616162382d945f35c37347John Porto 5857b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// createForLabelOrDuplicate will return a new LowerInt1BranchTarget that 5867b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// is the exact copy of this if Label is nullptr; otherwise, the returned 5877b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// object will wrap Label instead. 5887b3d9cbb1c1697e03c616162382d945f35c37347John Porto LowerInt1BranchTarget 5897b3d9cbb1c1697e03c616162382d945f35c37347John Porto createForLabelOrDuplicate(InstARM32Label *Label) const { 5907b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (Label != nullptr) 5917b3d9cbb1c1697e03c616162382d945f35c37347John Porto return LowerInt1BranchTarget(Label); 5927b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (NodeTarget) 5937b3d9cbb1c1697e03c616162382d945f35c37347John Porto return LowerInt1BranchTarget(NodeTarget); 5947b3d9cbb1c1697e03c616162382d945f35c37347John Porto return LowerInt1BranchTarget(LabelTarget); 5954a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 5964a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 5977b3d9cbb1c1697e03c616162382d945f35c37347John Porto CfgNode *const NodeTarget = nullptr; 5987b3d9cbb1c1697e03c616162382d945f35c37347John Porto InstARM32Label *const LabelTarget = nullptr; 5997b3d9cbb1c1697e03c616162382d945f35c37347John Porto }; 6004a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 6017b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// LowerInt1AllowShortCircuit is a helper type used by lowerInt1ForBranch for 6027b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// determining which type arithmetic is allowed to be short circuited. This 6037b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// is useful for lowering 6047b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6057b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// t1 = and i1 A, B 6067b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// t2 = and i1 t1, C 6077b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// br i1 t2, label %False, label %True 6087b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6097b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// to 6107b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6117b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst A, 1 6127b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// beq %False 6137b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst B, 1 6147b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// beq %False 6157b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst C, 1 6167b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// bne %True 6177b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// b %False 6187b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6197b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// Without this information, short circuiting would only allow to short 6207b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// circuit a single high level instruction. For example: 6217b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6227b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// t1 = or i1 A, B 6237b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// t2 = and i1 t1, C 6247b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// br i1 t2, label %False, label %True 6257b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6267b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// cannot be lowered to 6277b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6287b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst A, 1 6297b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// bne %True 6307b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst B, 1 6317b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// bne %True 6327b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst C, 1 6337b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// beq %True 6347b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// b %False 6357b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6367b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// It needs to be lowered to 6377b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6387b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst A, 1 6397b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// bne Aux 6407b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst B, 1 6417b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// beq %False 6427b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// Aux: 6437b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// tst C, 1 6447b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// bne %True 6457b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// b %False 6467b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// 6477b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// TODO(jpp): evaluate if this kind of short circuiting hurts performance (it 6487b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// might.) 6497b3d9cbb1c1697e03c616162382d945f35c37347John Porto enum LowerInt1AllowShortCircuit { 6507b3d9cbb1c1697e03c616162382d945f35c37347John Porto SC_And = 1, 6517b3d9cbb1c1697e03c616162382d945f35c37347John Porto SC_Or = 2, 6527b3d9cbb1c1697e03c616162382d945f35c37347John Porto SC_All = SC_And | SC_Or, 6537b3d9cbb1c1697e03c616162382d945f35c37347John Porto }; 6544a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 6557b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// ShortCircuitCondAndLabel wraps the condition codes that should be used 6567b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// after a lowerInt1ForBranch returns to branch to the 6577b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// TrueTarget/FalseTarget. If ShortCircuitLabel is not nullptr, then the 6587b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// called lowerInt1forBranch created an internal (i.e., short-circuit) label 6597b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// used for short circuiting. 6607b3d9cbb1c1697e03c616162382d945f35c37347John Porto class ShortCircuitCondAndLabel { 6617b3d9cbb1c1697e03c616162382d945f35c37347John Porto public: 6627b3d9cbb1c1697e03c616162382d945f35c37347John Porto explicit ShortCircuitCondAndLabel(CondWhenTrue &&C, 6637b3d9cbb1c1697e03c616162382d945f35c37347John Porto InstARM32Label *L = nullptr) 6647b3d9cbb1c1697e03c616162382d945f35c37347John Porto : Cond(std::move(C)), ShortCircuitTarget(L) {} 6657b3d9cbb1c1697e03c616162382d945f35c37347John Porto const CondWhenTrue Cond; 6667b3d9cbb1c1697e03c616162382d945f35c37347John Porto InstARM32Label *const ShortCircuitTarget; 6677b3d9cbb1c1697e03c616162382d945f35c37347John Porto 6687b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondWhenTrue assertNoLabelAndReturnCond() const { 6697b3d9cbb1c1697e03c616162382d945f35c37347John Porto assert(ShortCircuitTarget == nullptr); 6707b3d9cbb1c1697e03c616162382d945f35c37347John Porto return Cond; 6714a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 6727b3d9cbb1c1697e03c616162382d945f35c37347John Porto }; 6734a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 6747b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// lowerInt1ForBranch expands Boolean, and returns the condition codes that 6757b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// are to be used for branching to the branch's TrueTarget. It may return a 6767b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// label that the expansion of Boolean used to short circuit the chain's 6777b3d9cbb1c1697e03c616162382d945f35c37347John Porto /// evaluation. 6787b3d9cbb1c1697e03c616162382d945f35c37347John Porto ShortCircuitCondAndLabel 6797b3d9cbb1c1697e03c616162382d945f35c37347John Porto lowerInt1ForBranch(Operand *Boolean, const LowerInt1BranchTarget &TargetTrue, 6807b3d9cbb1c1697e03c616162382d945f35c37347John Porto const LowerInt1BranchTarget &TargetFalse, 6817b3d9cbb1c1697e03c616162382d945f35c37347John Porto uint32_t ShortCircuitable); 6827b3d9cbb1c1697e03c616162382d945f35c37347John Porto 6837b3d9cbb1c1697e03c616162382d945f35c37347John Porto // _br is a convenience wrapper that emits br instructions to Target. 6847b3d9cbb1c1697e03c616162382d945f35c37347John Porto void _br(const LowerInt1BranchTarget &BrTarget, 6857b3d9cbb1c1697e03c616162382d945f35c37347John Porto CondARM32::Cond Cond = CondARM32::AL) { 6867b3d9cbb1c1697e03c616162382d945f35c37347John Porto assert((BrTarget.NodeTarget == nullptr) != 6877b3d9cbb1c1697e03c616162382d945f35c37347John Porto (BrTarget.LabelTarget == nullptr)); 6887b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (BrTarget.NodeTarget != nullptr) 6897b3d9cbb1c1697e03c616162382d945f35c37347John Porto _br(BrTarget.NodeTarget, Cond); 6907b3d9cbb1c1697e03c616162382d945f35c37347John Porto else 6917b3d9cbb1c1697e03c616162382d945f35c37347John Porto _br(BrTarget.LabelTarget, Cond); 6927b3d9cbb1c1697e03c616162382d945f35c37347John Porto } 6937b3d9cbb1c1697e03c616162382d945f35c37347John Porto 6947b3d9cbb1c1697e03c616162382d945f35c37347John Porto // _br_short_circuit is used when lowering InstArithmetic::And and 6957b3d9cbb1c1697e03c616162382d945f35c37347John Porto // InstArithmetic::Or and a short circuit branch is needed. 6967b3d9cbb1c1697e03c616162382d945f35c37347John Porto void _br_short_circuit(const LowerInt1BranchTarget &Target, 6977b3d9cbb1c1697e03c616162382d945f35c37347John Porto const CondWhenTrue &Cond) { 6987b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (Cond.WhenTrue1 != CondARM32::kNone) { 6997b3d9cbb1c1697e03c616162382d945f35c37347John Porto _br(Target, Cond.WhenTrue1); 7004a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 7017b3d9cbb1c1697e03c616162382d945f35c37347John Porto if (Cond.WhenTrue0 != CondARM32::kNone) { 7027b3d9cbb1c1697e03c616162382d945f35c37347John Porto _br(Target, Cond.WhenTrue0); 7034a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 7044a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 7057b3d9cbb1c1697e03c616162382d945f35c37347John Porto // End of bool folding machinery 7067b3d9cbb1c1697e03c616162382d945f35c37347John Porto // -------------------------------------------------------------------------- 7074a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 70857e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// The Operand can only be a 16-bit immediate or a ConstantRelocatable (with 70957e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull /// an upper16 relocation). 7103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _movt(Variable *Dest, Operand *Src0, 7113bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7121d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Movt>(Dest, Src0, Pred); 7133bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung } 7143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _movw(Variable *Dest, Operand *Src0, 7153bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7161d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Movw>(Dest, Src0, Pred); 717b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 7183bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _mul(Variable *Dest, Variable *Src0, Variable *Src1, 7193bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7201d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Mul>(Dest, Src0, Src1, Pred); 721b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 7223bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _mvn(Variable *Dest, Operand *Src0, 7233bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7241d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Mvn>(Dest, Src0, Pred); 7252971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7263bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _orr(Variable *Dest, Variable *Src0, Operand *Src1, 7273bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7281d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred); 729b3401d27a236b81393092b4d571df473b5bba64bJan Voung } 7306ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _orrs(Variable *Dest, Variable *Src0, Operand *Src1, 7316ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 73286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung constexpr bool SetFlags = true; 7331d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Orr>(Dest, Src0, Src1, Pred, SetFlags); 7347e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 7357e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 7367e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 7370fa6c5a062f465360448a672abed3b916b413ca8Jan Voung } 7381d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto void _push(const VarList &Sources) { Context.insert<InstARM32Push>(Sources); } 7390fa6c5a062f465360448a672abed3b916b413ca8Jan Voung void _pop(const VarList &Dests) { 7401d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Pop>(Dests); 7410fa6c5a062f465360448a672abed3b916b413ca8Jan Voung // Mark dests as modified. 7420fa6c5a062f465360448a672abed3b916b413ca8Jan Voung for (Variable *Dest : Dests) 7431d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeDef>(Dest); 7440fa6c5a062f465360448a672abed3b916b413ca8Jan Voung } 745f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung void _rbit(Variable *Dest, Variable *Src0, 746f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7471d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rbit>(Dest, Src0, Pred); 748f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung } 749f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung void _rev(Variable *Dest, Variable *Src0, 750f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7511d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rev>(Dest, Src0, Pred); 752f645d8539e6dd8d0d7d6b604f36b9cc7b05d1886Jan Voung } 7536ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _ret(Variable *LR, Variable *Src0 = nullptr) { 7541d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Ret>(LR, Src0); 7556ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 756ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _rscs(Variable *Dest, Variable *Src0, Operand *Src1, 757ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 758ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto constexpr bool SetFlags = true; 7591d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred, SetFlags); 7607e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 7617e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 7627e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 763ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 764ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _rsc(Variable *Dest, Variable *Src0, Operand *Src1, 765ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 7661d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rsc>(Dest, Src0, Src1, Pred); 767ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 768ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _rsbs(Variable *Dest, Variable *Src0, Operand *Src1, 769ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 770ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto constexpr bool SetFlags = true; 7711d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred, SetFlags); 7727e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 7737e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 7747e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 775ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 77666c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung void _rsb(Variable *Dest, Variable *Src0, Operand *Src1, 77766c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7781d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Rsb>(Dest, Src0, Src1, Pred); 77966c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung } 7803bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _sbc(Variable *Dest, Variable *Src0, Operand *Src1, 7813bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7821d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred); 7832971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7843bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _sbcs(Variable *Dest, Variable *Src0, Operand *Src1, 7853bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 78686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung constexpr bool SetFlags = true; 7871d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sbc>(Dest, Src0, Src1, Pred, SetFlags); 7887e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 7897e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 7907e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 7912971997a96b7484165cfedead111c7cafb3073aeJan Voung } 7926ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _sdiv(Variable *Dest, Variable *Src0, Variable *Src1, 7936ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 7941d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sdiv>(Dest, Src0, Src1, Pred); 7956ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 796ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// _str, for all your Variable to memory transfers. Addr has the same 797ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto /// restrictions that it does in _ldr. 798befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung void _str(Variable *Value, OperandARM32Mem *Addr, 799befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung CondARM32::Cond Pred = CondARM32::AL) { 8001d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Str>(Value, Addr, Pred); 801befd03ab806aebfa9e69087bcfc63210b2b1642aJan Voung } 802324334e5315db2e67f16a4dffe91e1b1faf8dc8eJohn Porto InstARM32Strex *_strex(Variable *Dest, Variable *Value, OperandARM32Mem *Addr, 803324334e5315db2e67f16a4dffe91e1b1faf8dc8eJohn Porto CondARM32::Cond Pred = CondARM32::AL) { 80416991847500a48932426d979c4f2d4adffaf3649John Porto if (auto *Value64 = llvm::dyn_cast<Variable64On32>(Value)) { 8051d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeUse>(Value64->getLo()); 8061d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstFakeUse>(Value64->getHi()); 80716991847500a48932426d979c4f2d4adffaf3649John Porto } 808324334e5315db2e67f16a4dffe91e1b1faf8dc8eJohn Porto return Context.insert<InstARM32Strex>(Dest, Value, Addr, Pred); 80916991847500a48932426d979c4f2d4adffaf3649John Porto } 8103bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _sub(Variable *Dest, Variable *Src0, Operand *Src1, 8113bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 8121d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred); 8132971997a96b7484165cfedead111c7cafb3073aeJan Voung } 8143bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung void _subs(Variable *Dest, Variable *Src0, Operand *Src1, 8153bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 81686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung constexpr bool SetFlags = true; 8171d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sub>(Dest, Src0, Src1, Pred, SetFlags); 8187e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto if (SetFlags) { 8197e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto Context.insert<InstFakeUse>(Dest); 8207e6aa5a164fdfd306708187529e856b0ed00741cJohn Porto } 8212971997a96b7484165cfedead111c7cafb3073aeJan Voung } 82266c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung void _sxt(Variable *Dest, Variable *Src0, 82366c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 8241d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Sxt>(Dest, Src0, Pred); 82566c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung } 8266ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _tst(Variable *Src0, Operand *Src1, 8276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 8281d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Tst>(Src0, Src1, Pred); 8296ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung } 8301d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto void _trap() { Context.insert<InstARM32Trap>(); } 8316ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung void _udiv(Variable *Dest, Variable *Src0, Variable *Src1, 8326ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 8331d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Udiv>(Dest, Src0, Src1, Pred); 834b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 8352971997a96b7484165cfedead111c7cafb3073aeJan Voung void _umull(Variable *DestLo, Variable *DestHi, Variable *Src0, 8363bfd99a3b3bc534ce11617641fd9123a0e2baec8Jan Voung Variable *Src1, CondARM32::Cond Pred = CondARM32::AL) { 837a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto // umull requires DestLo and DestHi to be assigned to different GPRs. The 838a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto // following lines create overlapping liveness ranges for both variables. If 839a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto // either one of them is live, then they are both going to be live, and thus 840a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto // assigned to different registers; if they are both dead, then DCE will 841a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto // kick in and delete the following three instructions. 842a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto Context.insert<InstFakeDef>(DestHi); 8431d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Umull>(DestLo, DestHi, Src0, Src1, Pred); 844a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto Context.insert<InstFakeDef>(DestHi, DestLo)->setDestRedefined(); 84528df6bad8e70d9930040464791296e192aaa03efJim Stichnoth Context.insert<InstFakeUse>(DestHi); 8462971997a96b7484165cfedead111c7cafb3073aeJan Voung } 84766c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung void _uxt(Variable *Dest, Variable *Src0, 84866c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 8491d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Uxt>(Dest, Src0, Pred); 85066c3d5ecf3b6a6ce3b3a63c85312777ecbacee24Jan Voung } 851ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto void _vabs(Variable *Dest, Variable *Src, 852ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto CondARM32::Cond Pred = CondARM32::AL) { 8531d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vabs>(Dest, Src, Pred); 854ba6a67c960a126d85b94a87c8ea7358bec0da048John Porto } 85586ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void _vadd(Variable *Dest, Variable *Src0, Variable *Src1) { 8561d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vadd>(Dest, Src0, Src1); 85786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 858b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holk void _vand(Variable *Dest, Variable *Src0, Variable *Src1) { 859b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holk Context.insert<InstARM32Vand>(Dest, Src0, Src1); 860b58170c52af100fc57fe2c5f97d14e1deae02902Eric Holk } 861397f602c4e4e5697806bf74e37a651ab78680628John Porto InstARM32Vbsl *_vbsl(Variable *Dest, Variable *Src0, Variable *Src1) { 862397f602c4e4e5697806bf74e37a651ab78680628John Porto return Context.insert<InstARM32Vbsl>(Dest, Src0, Src1); 863397f602c4e4e5697806bf74e37a651ab78680628John Porto } 864a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto void _vceq(Variable *Dest, Variable *Src0, Variable *Src1) { 865a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Context.insert<InstARM32Vceq>(Dest, Src0, Src1); 866a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto } 867a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto InstARM32Vcge *_vcge(Variable *Dest, Variable *Src0, Variable *Src1) { 868a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto return Context.insert<InstARM32Vcge>(Dest, Src0, Src1); 869a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto } 870a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto InstARM32Vcgt *_vcgt(Variable *Dest, Variable *Src0, Variable *Src1) { 871a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto return Context.insert<InstARM32Vcgt>(Dest, Src0, Src1); 872a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto } 873c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto void _vcvt(Variable *Dest, Variable *Src, InstARM32Vcvt::VcvtVariant Variant, 874c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto CondARM32::Cond Pred = CondARM32::AL) { 8751d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vcvt>(Dest, Src, Variant, Pred); 876c31e2ed72ed52bb40e0591dd97b6d6d071631655John Porto } 87786ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void _vdiv(Variable *Dest, Variable *Src0, Variable *Src1) { 8781d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vdiv>(Dest, Src0, Src1); 87986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 8802f5534f1c523eb022880360864f60ce42fb30ee0John Porto void _vcmp(Variable *Src0, Variable *Src1, 8812f5534f1c523eb022880360864f60ce42fb30ee0John Porto CondARM32::Cond Pred = CondARM32::AL) { 8821d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vcmp>(Src0, Src1, Pred); 8832f5534f1c523eb022880360864f60ce42fb30ee0John Porto } 884ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto void _vcmp(Variable *Src0, OperandARM32FlexFpZero *FpZero, 885ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto CondARM32::Cond Pred = CondARM32::AL) { 8861d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vcmp>(Src0, FpZero, Pred); 887ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 888f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vdup(Variable *Dest, Variable *Src, int Idx) { 889f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vdup>(Dest, Src, Idx); 890f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 8913f6b47d53174f4f44d8b7c32d806fc5b5288a218John Porto void _veor(Variable *Dest, Variable *Src0, Variable *Src1) { 8921d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Veor>(Dest, Src0, Src1); 8933f6b47d53174f4f44d8b7c32d806fc5b5288a218John Porto } 894675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vldr1d(Variable *Dest, OperandARM32Mem *Addr, 895675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens CondARM32::Cond Pred = CondARM32::AL) { 896675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vldr1d>(Dest, Addr, Pred); 897675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 898675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vldr1q(Variable *Dest, OperandARM32Mem *Addr, 899675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens CondARM32::Cond Pred = CondARM32::AL) { 900675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vldr1q>(Dest, Addr, Pred); 901675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 9022f5534f1c523eb022880360864f60ce42fb30ee0John Porto void _vmrs(CondARM32::Cond Pred = CondARM32::AL) { 9031d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vmrs>(Pred); 9042f5534f1c523eb022880360864f60ce42fb30ee0John Porto } 905eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto void _vmla(Variable *Dest, Variable *Src0, Variable *Src1) { 9061d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vmla>(Dest, Src0, Src1); 907eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 908675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vmlap(Variable *Dest, Variable *Src0, Variable *Src1) { 909675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vmlap>(Dest, Src0, Src1); 910675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 911eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto void _vmls(Variable *Dest, Variable *Src0, Variable *Src1) { 9121d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vmls>(Dest, Src0, Src1); 913eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto } 914f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vmovl(Variable *Dest, Variable *Src0, Variable *Src1) { 915f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vmovl>(Dest, Src0, Src1); 916f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 917f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vmovh(Variable *Dest, Variable *Src0, Variable *Src1) { 918f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vmovh>(Dest, Src0, Src1); 919f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 920f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vmovhl(Variable *Dest, Variable *Src0, Variable *Src1) { 921f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vmovhl>(Dest, Src0, Src1); 922f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 923f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vmovlh(Variable *Dest, Variable *Src0, Variable *Src1) { 924f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vmovlh>(Dest, Src0, Src1); 925f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 92686ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void _vmul(Variable *Dest, Variable *Src0, Variable *Src1) { 9271d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vmul>(Dest, Src0, Src1); 928ccea793fe4259ba9aa0b6bcd3f281a5c08ac2aa4John Porto } 929675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vmulh(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) { 930675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vmulh>(Dest, Src0, Src1) 931675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed); 932675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 933a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto void _vmvn(Variable *Dest, Variable *Src0) { 934a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto Context.insert<InstARM32Vmvn>(Dest, Src0, CondARM32::AL); 935a4d100ab21814f39591684c59e4c4e113fa0f1f4John Porto } 93615e77d4698df65dfce5072b59df18500ff56daa3John Porto void _vneg(Variable *Dest, Variable *Src0) { 93715e77d4698df65dfce5072b59df18500ff56daa3John Porto Context.insert<InstARM32Vneg>(Dest, Src0, CondARM32::AL) 93815e77d4698df65dfce5072b59df18500ff56daa3John Porto ->setSignType(InstARM32::FS_Signed); 93915e77d4698df65dfce5072b59df18500ff56daa3John Porto } 940cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holk void _vorr(Variable *Dest, Variable *Src0, Variable *Src1) { 941cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holk Context.insert<InstARM32Vorr>(Dest, Src0, Src1); 942cad0b7597cdee839950dae55fccaaa7b54734d79Eric Holk } 943b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin void _vqadd(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) { 944b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin Context.insert<InstARM32Vqadd>(Dest, Src0, Src1) 945b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed); 946b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin } 947675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vqmovn2(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned, 948675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens bool Saturating) { 949675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vqmovn2>(Dest, Src0, Src1) 950675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens ->setSignType(Saturating ? (Unsigned ? InstARM32::FS_Unsigned 951675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens : InstARM32::FS_Signed) 952675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens : InstARM32::FS_None); 953675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 954b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin void _vqsub(Variable *Dest, Variable *Src0, Variable *Src1, bool Unsigned) { 955b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin Context.insert<InstARM32Vqsub>(Dest, Src0, Src1) 956b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin ->setSignType(Unsigned ? InstARM32::FS_Unsigned : InstARM32::FS_Signed); 957b40560b18e145d9523d7ad2d19a30861811d169fCasey Dahlin } 95815e77d4698df65dfce5072b59df18500ff56daa3John Porto InstARM32Vshl *_vshl(Variable *Dest, Variable *Src0, Variable *Src1) { 95915e77d4698df65dfce5072b59df18500ff56daa3John Porto return Context.insert<InstARM32Vshl>(Dest, Src0, Src1); 96015e77d4698df65dfce5072b59df18500ff56daa3John Porto } 961e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto void _vshl(Variable *Dest, Variable *Src0, ConstantInteger32 *Src1) { 962e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto Context.insert<InstARM32Vshl>(Dest, Src0, Src1) 963e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto ->setSignType(InstARM32::FS_Unsigned); 964e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto } 965e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto InstARM32Vshr *_vshr(Variable *Dest, Variable *Src0, 966e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto ConstantInteger32 *Src1) { 967e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto return Context.insert<InstARM32Vshr>(Dest, Src0, Src1); 968e88c7deb72049a08ecad8bb8f9ed3696c9415b0eJohn Porto } 96986ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void _vsqrt(Variable *Dest, Variable *Src, 97086ebec12680b5268fcb7082f770a26394e8b8080Jan Voung CondARM32::Cond Pred = CondARM32::AL) { 9711d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vsqrt>(Dest, Src, Pred); 97286ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 973675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vstr1d(Variable *Value, OperandARM32Mem *Addr, 974675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens CondARM32::Cond Pred = CondARM32::AL) { 975675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 32); 976675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 977675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens void _vstr1q(Variable *Value, OperandARM32Mem *Addr, 978675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens CondARM32::Cond Pred = CondARM32::AL) { 979675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens Context.insert<InstARM32Vstr1>(Value, Addr, Pred, 64); 980675e15b393f53686d8d71a7c0c6a7a4f41ad510dNicolas Capens } 98186ebec12680b5268fcb7082f770a26394e8b8080Jan Voung void _vsub(Variable *Dest, Variable *Src0, Variable *Src1) { 9821d937a8e35b7ae51ee64c32f8f34d51ba33498f4John Porto Context.insert<InstARM32Vsub>(Dest, Src0, Src1); 98386ebec12680b5268fcb7082f770a26394e8b8080Jan Voung } 984f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens void _vzip(Variable *Dest, Variable *Src0, Variable *Src1) { 985f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens Context.insert<InstARM32Vzip>(Dest, Src0, Src1); 986f6951fa3d70fd7ada350a8fabd8aa7952eca097bNicolas Capens } 987b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung 988f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto // Iterates over the CFG and determines the maximum outgoing stack arguments 989614140e2be672234e28e3179eba9f973eb6a19c6John Porto // bytes. This information is later used during addProlog() to pre-allocate 990f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto // the outargs area. 991f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto // TODO(jpp): This could live in the Parser, if we provided a Target-specific 992f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto // method that the Parser could call. 993f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto void findMaxStackOutArgsSize(); 994f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto 995866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Returns true if the given Offset can be represented in a Load/Store Mem 996866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Operand. 997f5f02f7ee856727e2c6dd0063b19932efc4e47f6John Porto bool isLegalMemOffset(Type Ty, int32_t Offset) const; 998866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 999866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto void postLowerLegalization(); 1000866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1001dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// Manages the GotPtr variable, which is used for Nonsfi sandboxing. 1002dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// @{ 1003dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto void createGotPtr(); 1004dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto void insertGotPtrInitPlaceholder(); 1005dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto VariableDeclaration *createGotRelocation(RelocOffset *AddPcReloc); 1006dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto void materializeGotAddr(CfgNode *Node); 1007dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto Variable *GotPtr = nullptr; 1008dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // TODO(jpp): use CfgLocalAllocator. 1009dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// @} 1010dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto 1011dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// Manages the Gotoff relocations created during the function lowering. A 1012dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// single Gotoff relocation is created for each global variable used by the 1013dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// function being lowered. 1014dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// @{ 1015dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // TODO(jpp): if the same global G is used in different functions, then this 1016dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // method will emit one G(gotoff) relocation per function. 1017467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth GlobalString createGotoffRelocation(const ConstantRelocatable *CR); 1018467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth CfgUnorderedSet<GlobalString> KnownGotoffs; 1019dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// @} 1020dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto 1021dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// Loads the constant relocatable Name to Register. Then invoke Finish to 1022dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// finish the relocatable lowering. Finish **must** use PC in its first 1023dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// emitted instruction, or the relocatable in Register will contain the wrong 1024dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto /// value. 1025dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // 1026dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // Lowered sequence: 1027dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // 1028dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // Movw: 1029dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // movw Register, #:lower16:Name - (End - Movw) - 8 . 1030dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // Movt: 1031dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // movt Register, #:upper16:Name - (End - Movt) - 8 . 1032dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // PC = fake-def 1033dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // End: 1034dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // Finish(PC) 1035dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // 1036dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // The -8 in movw/movt above is to account for the PC value that the first 1037dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto // instruction emitted by Finish(PC) will read. 103898ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth void 1039467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth loadNamedConstantRelocatablePIC(GlobalString Name, Variable *Register, 104098ba00666271be1bdcd45b72b3dec04419efe61bJim Stichnoth std::function<void(Variable *PC)> Finish); 1041dc61925cf9de3cba7f310c9e8855c56b8e5b3edcJohn Porto 104252b515717f437804b62c7d24f36414baaf15daa7John Porto /// Sandboxer defines methods for ensuring that "dangerous" operations are 104352b515717f437804b62c7d24f36414baaf15daa7John Porto /// masked during sandboxed code emission. For regular, non-sandboxed code 104452b515717f437804b62c7d24f36414baaf15daa7John Porto /// emission, its methods are simple pass-through methods. 104552b515717f437804b62c7d24f36414baaf15daa7John Porto /// 104652b515717f437804b62c7d24f36414baaf15daa7John Porto /// The Sandboxer also emits BundleLock/BundleUnlock pseudo-instructions 104752b515717f437804b62c7d24f36414baaf15daa7John Porto /// in the constructor/destructor during sandboxed code emission. Therefore, 104852b515717f437804b62c7d24f36414baaf15daa7John Porto /// it is a bad idea to create an object of this type and "keep it around." 104952b515717f437804b62c7d24f36414baaf15daa7John Porto /// The recommended usage is: 105052b515717f437804b62c7d24f36414baaf15daa7John Porto /// 105152b515717f437804b62c7d24f36414baaf15daa7John Porto /// AutoSandboxing(this).<<operation>>(...); 105252b515717f437804b62c7d24f36414baaf15daa7John Porto /// 105352b515717f437804b62c7d24f36414baaf15daa7John Porto /// This usage ensures that no other instructions are inadvertently added to 105452b515717f437804b62c7d24f36414baaf15daa7John Porto /// the bundle. 105552b515717f437804b62c7d24f36414baaf15daa7John Porto class Sandboxer { 105652b515717f437804b62c7d24f36414baaf15daa7John Porto Sandboxer() = delete; 105752b515717f437804b62c7d24f36414baaf15daa7John Porto Sandboxer(const Sandboxer &) = delete; 105852b515717f437804b62c7d24f36414baaf15daa7John Porto Sandboxer &operator=(const Sandboxer &) = delete; 105952b515717f437804b62c7d24f36414baaf15daa7John Porto 106052b515717f437804b62c7d24f36414baaf15daa7John Porto public: 106152b515717f437804b62c7d24f36414baaf15daa7John Porto explicit Sandboxer( 106252b515717f437804b62c7d24f36414baaf15daa7John Porto TargetARM32 *Target, 106352b515717f437804b62c7d24f36414baaf15daa7John Porto InstBundleLock::Option BundleOption = InstBundleLock::Opt_None); 106452b515717f437804b62c7d24f36414baaf15daa7John Porto ~Sandboxer(); 106552b515717f437804b62c7d24f36414baaf15daa7John Porto 106652b515717f437804b62c7d24f36414baaf15daa7John Porto /// Increments sp: 106752b515717f437804b62c7d24f36414baaf15daa7John Porto /// 106852b515717f437804b62c7d24f36414baaf15daa7John Porto /// add sp, sp, AddAmount 106952b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic sp, sp, 0xc0000000 107052b515717f437804b62c7d24f36414baaf15daa7John Porto /// 107152b515717f437804b62c7d24f36414baaf15daa7John Porto /// (for the rationale, see the ARM 32-bit Sandbox Specification.) 107252b515717f437804b62c7d24f36414baaf15daa7John Porto void add_sp(Operand *AddAmount); 107352b515717f437804b62c7d24f36414baaf15daa7John Porto 107452b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits code to align sp to the specified alignment: 107552b515717f437804b62c7d24f36414baaf15daa7John Porto /// 107652b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic/and sp, sp, Alignment 107752b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic, sp, sp, 0xc0000000 107852b515717f437804b62c7d24f36414baaf15daa7John Porto void align_sp(size_t Alignment); 107952b515717f437804b62c7d24f36414baaf15daa7John Porto 108052b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits a call instruction. If CallTarget is a Variable, it emits 108152b515717f437804b62c7d24f36414baaf15daa7John Porto /// 108252b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic CallTarget, CallTarget, 0xc000000f 108352b515717f437804b62c7d24f36414baaf15daa7John Porto /// bl CallTarget 108452b515717f437804b62c7d24f36414baaf15daa7John Porto /// 108552b515717f437804b62c7d24f36414baaf15daa7John Porto /// Otherwise, it emits 108652b515717f437804b62c7d24f36414baaf15daa7John Porto /// 108752b515717f437804b62c7d24f36414baaf15daa7John Porto /// bl CallTarget 108852b515717f437804b62c7d24f36414baaf15daa7John Porto /// 108952b515717f437804b62c7d24f36414baaf15daa7John Porto /// Note: in sandboxed code calls are always emitted in addresses 12 mod 16. 109052b515717f437804b62c7d24f36414baaf15daa7John Porto InstARM32Call *bl(Variable *ReturnReg, Operand *CallTarget); 109152b515717f437804b62c7d24f36414baaf15daa7John Porto 109252b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits a load: 109352b515717f437804b62c7d24f36414baaf15daa7John Porto /// 109452b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic rBase, rBase, 0xc0000000 109552b515717f437804b62c7d24f36414baaf15daa7John Porto /// ldr rDest, [rBase, #Offset] 109652b515717f437804b62c7d24f36414baaf15daa7John Porto /// 109752b515717f437804b62c7d24f36414baaf15daa7John Porto /// Exception: if rBase is r9 or sp, then the load is emitted as: 109852b515717f437804b62c7d24f36414baaf15daa7John Porto /// 109952b515717f437804b62c7d24f36414baaf15daa7John Porto /// ldr rDest, [rBase, #Offset] 110052b515717f437804b62c7d24f36414baaf15daa7John Porto /// 110152b515717f437804b62c7d24f36414baaf15daa7John Porto /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are 110252b515717f437804b62c7d24f36414baaf15daa7John Porto /// always valid. 110352b515717f437804b62c7d24f36414baaf15daa7John Porto void ldr(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred); 110452b515717f437804b62c7d24f36414baaf15daa7John Porto 110552b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits a load exclusive: 110652b515717f437804b62c7d24f36414baaf15daa7John Porto /// 110752b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic rBase, rBase, 0xc0000000 110852b515717f437804b62c7d24f36414baaf15daa7John Porto /// ldrex rDest, [rBase] 110952b515717f437804b62c7d24f36414baaf15daa7John Porto /// 111052b515717f437804b62c7d24f36414baaf15daa7John Porto /// Exception: if rBase is r9 or sp, then the load is emitted as: 111152b515717f437804b62c7d24f36414baaf15daa7John Porto /// 111252b515717f437804b62c7d24f36414baaf15daa7John Porto /// ldrex rDest, [rBase] 111352b515717f437804b62c7d24f36414baaf15daa7John Porto /// 111452b515717f437804b62c7d24f36414baaf15daa7John Porto /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are 111552b515717f437804b62c7d24f36414baaf15daa7John Porto /// always valid. 111652b515717f437804b62c7d24f36414baaf15daa7John Porto void ldrex(Variable *Dest, OperandARM32Mem *Mem, CondARM32::Cond Pred); 111752b515717f437804b62c7d24f36414baaf15daa7John Porto 111852b515717f437804b62c7d24f36414baaf15daa7John Porto /// Resets sp to Src: 111952b515717f437804b62c7d24f36414baaf15daa7John Porto /// 112052b515717f437804b62c7d24f36414baaf15daa7John Porto /// mov sp, Src 112152b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic sp, sp, 0xc0000000 112252b515717f437804b62c7d24f36414baaf15daa7John Porto void reset_sp(Variable *Src); 112352b515717f437804b62c7d24f36414baaf15daa7John Porto 112452b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits code to return from a function: 112552b515717f437804b62c7d24f36414baaf15daa7John Porto /// 112652b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic lr, lr, 0xc000000f 112752b515717f437804b62c7d24f36414baaf15daa7John Porto /// bx lr 112852b515717f437804b62c7d24f36414baaf15daa7John Porto void ret(Variable *RetAddr, Variable *RetValue); 112952b515717f437804b62c7d24f36414baaf15daa7John Porto 113052b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits a store: 113152b515717f437804b62c7d24f36414baaf15daa7John Porto /// 113252b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic rBase, rBase, 0xc0000000 113352b515717f437804b62c7d24f36414baaf15daa7John Porto /// str rSrc, [rBase, #Offset] 113452b515717f437804b62c7d24f36414baaf15daa7John Porto /// 113552b515717f437804b62c7d24f36414baaf15daa7John Porto /// Exception: if rBase is r9 or sp, then the store is emitted as: 113652b515717f437804b62c7d24f36414baaf15daa7John Porto /// 113752b515717f437804b62c7d24f36414baaf15daa7John Porto /// str rDest, [rBase, #Offset] 113852b515717f437804b62c7d24f36414baaf15daa7John Porto /// 113952b515717f437804b62c7d24f36414baaf15daa7John Porto /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are 114052b515717f437804b62c7d24f36414baaf15daa7John Porto /// always valid. 114152b515717f437804b62c7d24f36414baaf15daa7John Porto void str(Variable *Src, OperandARM32Mem *Mem, CondARM32::Cond Pred); 114252b515717f437804b62c7d24f36414baaf15daa7John Porto 114352b515717f437804b62c7d24f36414baaf15daa7John Porto /// Emits a store exclusive: 114452b515717f437804b62c7d24f36414baaf15daa7John Porto /// 114552b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic rBase, rBase, 0xc0000000 114652b515717f437804b62c7d24f36414baaf15daa7John Porto /// strex rDest, rSrc, [rBase] 114752b515717f437804b62c7d24f36414baaf15daa7John Porto /// 114852b515717f437804b62c7d24f36414baaf15daa7John Porto /// Exception: if rBase is r9 or sp, then the store is emitted as: 114952b515717f437804b62c7d24f36414baaf15daa7John Porto /// 115052b515717f437804b62c7d24f36414baaf15daa7John Porto /// strex rDest, rSrc, [rBase] 115152b515717f437804b62c7d24f36414baaf15daa7John Porto /// 115252b515717f437804b62c7d24f36414baaf15daa7John Porto /// because the NaCl ARM 32-bit Sandbox Specification guarantees they are 115352b515717f437804b62c7d24f36414baaf15daa7John Porto /// always valid. 115452b515717f437804b62c7d24f36414baaf15daa7John Porto void strex(Variable *Dest, Variable *Src, OperandARM32Mem *Mem, 115552b515717f437804b62c7d24f36414baaf15daa7John Porto CondARM32::Cond Pred); 115652b515717f437804b62c7d24f36414baaf15daa7John Porto 115752b515717f437804b62c7d24f36414baaf15daa7John Porto /// Decrements sp: 115852b515717f437804b62c7d24f36414baaf15daa7John Porto /// 115952b515717f437804b62c7d24f36414baaf15daa7John Porto /// sub sp, sp, SubAmount 116052b515717f437804b62c7d24f36414baaf15daa7John Porto /// bic sp, sp, 0xc0000000 116152b515717f437804b62c7d24f36414baaf15daa7John Porto void sub_sp(Operand *SubAmount); 116252b515717f437804b62c7d24f36414baaf15daa7John Porto 116352b515717f437804b62c7d24f36414baaf15daa7John Porto private: 1164a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto TargetARM32 *const Target; 1165a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto const InstBundleLock::Option BundleOption; 1166a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto std::unique_ptr<AutoBundle> Bundler; 1167a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto 1168a1cdd57e7b6e28e966d06345d6480913eb777d5bJohn Porto void createAutoBundle(); 116952b515717f437804b62c7d24f36414baaf15daa7John Porto }; 117052b515717f437804b62c7d24f36414baaf15daa7John Porto 1171866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto class PostLoweringLegalizer { 1172866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto PostLoweringLegalizer() = delete; 1173866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto PostLoweringLegalizer(const PostLoweringLegalizer &) = delete; 1174866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto PostLoweringLegalizer &operator=(const PostLoweringLegalizer &) = delete; 1175866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1176866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto public: 1177866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto explicit PostLoweringLegalizer(TargetARM32 *Target) 1178866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto : Target(Target), StackOrFrameReg(Target->getPhysicalRegister( 1179866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto Target->getFrameOrStackReg())) {} 1180866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1181866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto void resetTempBaseIfClobberedBy(const Inst *Instr); 1182866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1183866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto // Ensures that the TempBase register held by the this legalizer (if any) is 1184866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto // assigned to IP. 1185866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto void assertNoTempOrAssignedToIP() const { 1186866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto assert(TempBaseReg == nullptr || 1187866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto TempBaseReg->getRegNum() == Target->getReservedTmpReg()); 1188866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto } 1189866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1190866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto // Legalizes Mem. if Mem.Base is a Reamaterializable variable, Mem.Offset is 1191866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto // fixed up. 1192866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto OperandARM32Mem *legalizeMemOperand(OperandARM32Mem *Mem, 1193866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto bool AllowOffsets = true); 1194866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1195866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Legalizes Mov if its Source (or Destination) is a spilled Variable, or 1196866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// if its Source is a Rematerializable variable (this form is used in lieu 1197866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// of lea, which is not available in ARM.) 1198866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// 1199866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Moves to memory become store instructions, and moves from memory, loads. 1200866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto void legalizeMov(InstARM32Mov *Mov); 1201866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1202866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto private: 1203866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Creates a new Base register centered around [Base, +/- Offset]. 1204866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto Variable *newBaseRegister(Variable *Base, int32_t Offset, 12058aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth RegNumT ScratchRegNum); 1206866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto 1207866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// Creates a new, legal OperandARM32Mem for accessing Base + Offset. 1208866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// The returned mem operand is a legal operand for accessing memory that is 1209866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// of type Ty. 1210866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// 1211866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// If [Base, #Offset] is encodable, then the method returns a Mem operand 1212866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// expressing it. Otherwise, 1213866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// 1214866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// if [TempBaseReg, #Offset-TempBaseOffset] is a valid memory operand, the 1215866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// method will return that. Otherwise, 1216866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// 1217866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// a new base register ip=Base+Offset is created, and the method returns a 1218866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto /// memory operand expressing [ip, #0]. 1219866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto OperandARM32Mem *createMemOperand(Type Ty, Variable *Base, int32_t Offset, 1220866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto bool AllowOffsets = true); 1221866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto TargetARM32 *const Target; 1222866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto Variable *const StackOrFrameReg; 1223866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto Variable *TempBaseReg = nullptr; 1224866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto int32_t TempBaseOffset = 0; 1225866b6b19378691d0c07cd9c9b9c84036c201dfa2John Porto }; 122628068adbf34a4602090efddc18b4dd123ffdeb6aJan Voung 122752b515717f437804b62c7d24f36414baaf15daa7John Porto const bool NeedSandboxing; 12286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung TargetARM32Features CPUFeatures; 1229eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool UsesFramePointer = false; 1230eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool NeedsStackAlignment = false; 1231eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth bool MaybeLeafFunc = true; 1232eafb56cbab02dbf11071efbc56b4a7098bd40dc7Jim Stichnoth size_t SpillAreaSizeBytes = 0; 1233614140e2be672234e28e3179eba9f973eb6a19c6John Porto size_t FixedAllocaSizeBytes = 0; 1234614140e2be672234e28e3179eba9f973eb6a19c6John Porto size_t FixedAllocaAlignBytes = 0; 1235614140e2be672234e28e3179eba9f973eb6a19c6John Porto bool PrologEmitsFixedAllocas = false; 1236f4198548d27ec3f4d169361e3a5ed95b893d54daJohn Porto uint32_t MaxOutArgsSizeBytes = 0; 1237bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto // TODO(jpp): std::array instead of array. 1238e82b560e649f8a68bcb252b9b002708e74d962d3John Porto static SmallBitVector TypeToRegisterSet[RegARM32::RCARM32_NUM]; 1239e82b560e649f8a68bcb252b9b002708e74d962d3John Porto static SmallBitVector TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; 1240e82b560e649f8a68bcb252b9b002708e74d962d3John Porto static SmallBitVector RegisterAliases[RegARM32::Reg_NUM]; 1241e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector RegsUsed; 1242b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung VarList PhysicalRegisters[IceType_NUM]; 1243eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto VarList PreservedGPRs; 1244eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto VarList PreservedSRegs; 1245b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 12469612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// Helper class that understands the Calling Convention and register 12479612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// assignments. The first few integer type parameters can use r0-r3, 12489612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// regardless of their position relative to the floating-point/vector 1249385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// arguments in the argument list. Floating-point and vector arguments 1250385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// can use q0-q3 (aka d0-d7, s0-s15). For more information on the topic, 1251385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// see the ARM Architecture Procedure Calling Standards (AAPCS). 1252385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// 1253385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// Technically, arguments that can start with registers but extend beyond the 1254385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// available registers can be split between the registers and the stack. 1255385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// However, this is typically for passing GPR structs by value, and PNaCl 1256385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// transforms expand this out. 12579612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull /// 1258385351bab561a0992dbbfe617bf5f81f58db1674John Porto /// At (public) function entry, the stack must be 8-byte aligned. 1259b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung class CallingConv { 1260b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung CallingConv(const CallingConv &) = delete; 1261b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung CallingConv &operator=(const CallingConv &) = delete; 1262b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung 1263b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung public: 12642187c84aaf770db0e70024d8781c414e270625a0John Porto CallingConv(); 1265b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung ~CallingConv() = default; 1266b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung 12672187c84aaf770db0e70024d8781c414e270625a0John Porto /// argInGPR returns true if there is a GPR available for the requested 12682187c84aaf770db0e70024d8781c414e270625a0John Porto /// type, and false otherwise. If it returns true, Reg is set to the 12692187c84aaf770db0e70024d8781c414e270625a0John Porto /// appropriate register number. Note that, when Ty == IceType_i64, Reg will 12702187c84aaf770db0e70024d8781c414e270625a0John Porto /// be an I64 register pair. 12718aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth bool argInGPR(Type Ty, RegNumT *Reg); 1272b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung 12732187c84aaf770db0e70024d8781c414e270625a0John Porto /// argInVFP is to floating-point/vector types what argInGPR is for integer 12742187c84aaf770db0e70024d8781c414e270625a0John Porto /// types. 12758aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth bool argInVFP(Type Ty, RegNumT *Reg); 1276b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung 1277b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung private: 12788aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth void discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> *Regs); 1279e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector GPRegsUsed; 12808aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth CfgVector<RegNumT> GPRArgs; 12818aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth CfgVector<RegNumT> I64Args; 12822187c84aaf770db0e70024d8781c414e270625a0John Porto 12838aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth void discardUnavailableVFPRegs(CfgVector<RegNumT> *Regs); 1284e82b560e649f8a68bcb252b9b002708e74d962d3John Porto SmallBitVector VFPRegsUsed; 12858aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth CfgVector<RegNumT> FP32Args; 12868aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth CfgVector<RegNumT> FP64Args; 12878aa396610b7baf728631a43ea16ad3d13e38397aJim Stichnoth CfgVector<RegNumT> Vec128Args; 1288b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung }; 1289b0a8c24ecd98f4b6748f8fa8f8c4a254a48d4889Jan Voung 1290b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungprivate: 129153611e2c39b36db641a1b0cd9c6eb2174f696f79John Porto ENABLE_MAKE_UNIQUE; 12924a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 1293f5f02f7ee856727e2c6dd0063b19932efc4e47f6John Porto OperandARM32Mem *formAddressingMode(Type Ty, Cfg *Func, const Inst *LdSt, 1294f5f02f7ee856727e2c6dd0063b19932efc4e47f6John Porto Operand *Base); 1295f5f02f7ee856727e2c6dd0063b19932efc4e47f6John Porto 1296c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto void postambleCtpop64(const InstCall *Instr); 1297c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto void preambleDivRem(const InstCall *Instr); 1298e82b560e649f8a68bcb252b9b002708e74d962d3John Porto CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)> 1299c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto ARM32HelpersPreamble; 1300e82b560e649f8a68bcb252b9b002708e74d962d3John Porto CfgUnorderedMap<Operand *, void (TargetARM32::*)(const InstCall *Instr)> 1301c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto ARM32HelpersPostamble; 1302c39ec10e12aaeb07672a72d4e64f9fc55e71d5e4John Porto 1303eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto class ComputationTracker { 13044a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto public: 1305eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto ComputationTracker() = default; 1306eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto ~ComputationTracker() = default; 13074a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13084a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void forgetProducers() { KnownComputations.clear(); } 13094a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void recordProducers(CfgNode *Node); 13104a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13114a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto const Inst *getProducerOf(const Operand *Opnd) const { 13124a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto auto *Var = llvm::dyn_cast<Variable>(Opnd); 13134a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto if (Var == nullptr) { 13144a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto return nullptr; 13154a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 13164a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13174a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto auto Iter = KnownComputations.find(Var->getIndex()); 13184a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto if (Iter == KnownComputations.end()) { 13194a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto return nullptr; 13204a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 13214a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13224a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto return Iter->second.Instr; 13234a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 13244a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13254a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto void dump(const Cfg *Func) const { 13264a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto if (!BuildDefs::dump() || !Func->isVerbose(IceV_Folding)) 13274a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto return; 13284a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto OstreamLocker L(Func->getContext()); 13294a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Ostream &Str = Func->getContext()->getStrDump(); 13307b3d9cbb1c1697e03c616162382d945f35c37347John Porto Str << "foldable producer:\n"; 13314a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto for (const auto &Computation : KnownComputations) { 13324a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Str << " "; 13334a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Computation.second.Instr->dump(Func); 13344a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Str << "\n"; 13354a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 13364a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Str << "\n"; 13374a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto } 13384a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 13394a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto private: 1340eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto class ComputationEntry { 13414a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto public: 1342eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto ComputationEntry(Inst *I, Type Ty) : Instr(I), ComputationType(Ty) {} 13434a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto Inst *const Instr; 13444a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // Boolean folding is disabled for variables whose live range is multi 13454a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // block. We conservatively initialize IsLiveOut to true, and set it to 13464a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // false once we find the end of the live range for the variable defined 13474a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // by this instruction. If liveness analysis is not performed (e.g., in 13484a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // Om1 mode) IsLiveOut will never be set to false, and folding will be 13494a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto // disabled. 13504a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto bool IsLiveOut = true; 13517b3d9cbb1c1697e03c616162382d945f35c37347John Porto int32_t NumUses = 0; 1352eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto Type ComputationType; 13534a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto }; 13544a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 1355eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto // ComputationMap maps a Variable number to a payload identifying which 1356eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto // instruction defined it. 1357e82b560e649f8a68bcb252b9b002708e74d962d3John Porto using ComputationMap = CfgUnorderedMap<SizeT, ComputationEntry>; 1358eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto ComputationMap KnownComputations; 13594a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto }; 13604a5e6d05151ba1b52f1425ff22aa0398328b89f7John Porto 1361eb13acc6221f60642d17473b6329a82b02ae557aJohn Porto ComputationTracker Computations; 1362614140e2be672234e28e3179eba9f973eb6a19c6John Porto 1363614140e2be672234e28e3179eba9f973eb6a19c6John Porto // AllowTemporaryWithNoReg indicates if TargetARM32::makeReg() can be invoked 1364614140e2be672234e28e3179eba9f973eb6a19c6John Porto // without specifying a physical register. This is needed for creating unbound 1365614140e2be672234e28e3179eba9f973eb6a19c6John Porto // temporaries during Ice -> ARM lowering, but before register allocation. 136698cc08ca9749fbdd0142ea3152616cd5476d727dJohn Porto // This a safe-guard that no unbound temporaries are created during the 136798cc08ca9749fbdd0142ea3152616cd5476d727dJohn Porto // legalization post-passes. 1368614140e2be672234e28e3179eba9f973eb6a19c6John Porto bool AllowTemporaryWithNoReg = true; 1369614140e2be672234e28e3179eba9f973eb6a19c6John Porto // ForbidTemporaryWithoutReg is a RAII class that manages 1370614140e2be672234e28e3179eba9f973eb6a19c6John Porto // AllowTemporaryWithNoReg. 1371614140e2be672234e28e3179eba9f973eb6a19c6John Porto class ForbidTemporaryWithoutReg { 1372614140e2be672234e28e3179eba9f973eb6a19c6John Porto ForbidTemporaryWithoutReg() = delete; 137398cc08ca9749fbdd0142ea3152616cd5476d727dJohn Porto ForbidTemporaryWithoutReg(const ForbidTemporaryWithoutReg &) = delete; 137498cc08ca9749fbdd0142ea3152616cd5476d727dJohn Porto ForbidTemporaryWithoutReg & 137598cc08ca9749fbdd0142ea3152616cd5476d727dJohn Porto operator=(const ForbidTemporaryWithoutReg &) = delete; 1376614140e2be672234e28e3179eba9f973eb6a19c6John Porto 1377614140e2be672234e28e3179eba9f973eb6a19c6John Porto public: 1378614140e2be672234e28e3179eba9f973eb6a19c6John Porto explicit ForbidTemporaryWithoutReg(TargetARM32 *Target) : Target(Target) { 1379614140e2be672234e28e3179eba9f973eb6a19c6John Porto Target->AllowTemporaryWithNoReg = false; 1380614140e2be672234e28e3179eba9f973eb6a19c6John Porto } 1381614140e2be672234e28e3179eba9f973eb6a19c6John Porto ~ForbidTemporaryWithoutReg() { Target->AllowTemporaryWithNoReg = true; } 1382614140e2be672234e28e3179eba9f973eb6a19c6John Porto 1383614140e2be672234e28e3179eba9f973eb6a19c6John Porto private: 1384614140e2be672234e28e3179eba9f973eb6a19c6John Porto TargetARM32 *const Target; 1385614140e2be672234e28e3179eba9f973eb6a19c6John Porto }; 1386b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung}; 1387b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 13880f86d03ca2e44639ba03c659413f39eedcc75541John Portoclass TargetDataARM32 final : public TargetDataLowering { 1389b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetDataARM32() = delete; 1390b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetDataARM32(const TargetDataARM32 &) = delete; 1391b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung TargetDataARM32 &operator=(const TargetDataARM32 &) = delete; 1392b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1393b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungpublic: 1394fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { 1395fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung return std::unique_ptr<TargetDataLowering>(new TargetDataARM32(Ctx)); 1396b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung } 1397b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 13988b1a705165292328a3db53da273420989b46e443John Porto void lowerGlobals(const VariableDeclarationList &Vars, 1399467ffe51bebcb3ae3e3ce745c38fc20e8837c31cJim Stichnoth const std::string &SectionSuffix) override; 14000f86d03ca2e44639ba03c659413f39eedcc75541John Porto void lowerConstants() override; 140186df4e9e6d183f07638440afd2c225b485c03917Andrew Scull void lowerJumpTables() override; 1402b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1403b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungprotected: 1404b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung explicit TargetDataARM32(GlobalContext *Ctx); 1405b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1406b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voungprivate: 1407e587d9494fa95920943fafa0f1dac470a298a251Jim Stichnoth ~TargetDataARM32() override = default; 1408b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung}; 1409b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1410fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voungclass TargetHeaderARM32 final : public TargetHeaderLowering { 1411fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung TargetHeaderARM32() = delete; 1412fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung TargetHeaderARM32(const TargetHeaderARM32 &) = delete; 1413fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung TargetHeaderARM32 &operator=(const TargetHeaderARM32 &) = delete; 1414fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung 1415fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voungpublic: 1416fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { 1417fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderARM32(Ctx)); 1418fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung } 1419fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung 14200f86d03ca2e44639ba03c659413f39eedcc75541John Porto void lower() override; 1421fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung 1422fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voungprotected: 1423fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung explicit TargetHeaderARM32(GlobalContext *Ctx); 1424fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung 1425fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voungprivate: 1426fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung ~TargetHeaderARM32() = default; 14276ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung 14286ec369ebee62c3aab7fb7334d0bf3fac3a7133e5Jan Voung TargetARM32Features CPUFeatures; 1429fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung}; 1430fb79284d5dd6ea823fa907f3b60015a3d557ce54Jan Voung 14314a56686b5b56db6803f90ad53514bf2fa190d9f7John Porto} // end of namespace ARM32 1432b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung} // end of namespace Ice 1433b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung 1434b36ad9b4021b409dfb925ce51196a1abb4dfcb62Jan Voung#endif // SUBZERO_SRC_ICETARGETLOWERINGARM32_H 1435