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