109467b48Spatrick //===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick // 909467b48Spatrick // The file defines the MachineFrameInfo class. 1009467b48Spatrick // 1109467b48Spatrick //===----------------------------------------------------------------------===// 1209467b48Spatrick 1309467b48Spatrick #ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H 1409467b48Spatrick #define LLVM_CODEGEN_MACHINEFRAMEINFO_H 1509467b48Spatrick 1609467b48Spatrick #include "llvm/ADT/SmallVector.h" 17a0747c9fSpatrick #include "llvm/CodeGen/Register.h" 18*a96b3639Srobert #include "llvm/CodeGen/TargetFrameLowering.h" 1909467b48Spatrick #include "llvm/Support/Alignment.h" 2009467b48Spatrick #include <cassert> 2109467b48Spatrick #include <vector> 2209467b48Spatrick 2309467b48Spatrick namespace llvm { 2409467b48Spatrick class raw_ostream; 2509467b48Spatrick class MachineFunction; 2609467b48Spatrick class MachineBasicBlock; 2709467b48Spatrick class BitVector; 2809467b48Spatrick class AllocaInst; 2909467b48Spatrick 3009467b48Spatrick /// The CalleeSavedInfo class tracks the information need to locate where a 3109467b48Spatrick /// callee saved register is in the current frame. 3209467b48Spatrick /// Callee saved reg can also be saved to a different register rather than 3309467b48Spatrick /// on the stack by setting DstReg instead of FrameIdx. 3409467b48Spatrick class CalleeSavedInfo { 35a0747c9fSpatrick Register Reg; 3609467b48Spatrick union { 3709467b48Spatrick int FrameIdx; 3809467b48Spatrick unsigned DstReg; 3909467b48Spatrick }; 4009467b48Spatrick /// Flag indicating whether the register is actually restored in the epilog. 4109467b48Spatrick /// In most cases, if a register is saved, it is also restored. There are 4209467b48Spatrick /// some situations, though, when this is not the case. For example, the 4309467b48Spatrick /// LR register on ARM is usually saved, but on exit from the function its 4409467b48Spatrick /// saved value may be loaded directly into PC. Since liveness tracking of 4509467b48Spatrick /// physical registers treats callee-saved registers are live outside of 4609467b48Spatrick /// the function, LR would be treated as live-on-exit, even though in these 4709467b48Spatrick /// scenarios it is not. This flag is added to indicate that the saved 4809467b48Spatrick /// register described by this object is not restored in the epilog. 4909467b48Spatrick /// The long-term solution is to model the liveness of callee-saved registers 5009467b48Spatrick /// by implicit uses on the return instructions, however, the required 5109467b48Spatrick /// changes in the ARM backend would be quite extensive. 52*a96b3639Srobert bool Restored = true; 5309467b48Spatrick /// Flag indicating whether the register is spilled to stack or another 5409467b48Spatrick /// register. 55*a96b3639Srobert bool SpilledToReg = false; 5609467b48Spatrick 5709467b48Spatrick public: Reg(R)58*a96b3639Srobert explicit CalleeSavedInfo(unsigned R, int FI = 0) : Reg(R), FrameIdx(FI) {} 5909467b48Spatrick 6009467b48Spatrick // Accessors. getReg()61a0747c9fSpatrick Register getReg() const { return Reg; } getFrameIdx()6209467b48Spatrick int getFrameIdx() const { return FrameIdx; } getDstReg()6309467b48Spatrick unsigned getDstReg() const { return DstReg; } setFrameIdx(int FI)6409467b48Spatrick void setFrameIdx(int FI) { 6509467b48Spatrick FrameIdx = FI; 6609467b48Spatrick SpilledToReg = false; 6709467b48Spatrick } setDstReg(Register SpillReg)68a0747c9fSpatrick void setDstReg(Register SpillReg) { 6909467b48Spatrick DstReg = SpillReg; 7009467b48Spatrick SpilledToReg = true; 7109467b48Spatrick } isRestored()7209467b48Spatrick bool isRestored() const { return Restored; } setRestored(bool R)7309467b48Spatrick void setRestored(bool R) { Restored = R; } isSpilledToReg()7409467b48Spatrick bool isSpilledToReg() const { return SpilledToReg; } 7509467b48Spatrick }; 7609467b48Spatrick 7709467b48Spatrick /// The MachineFrameInfo class represents an abstract stack frame until 7809467b48Spatrick /// prolog/epilog code is inserted. This class is key to allowing stack frame 7909467b48Spatrick /// representation optimizations, such as frame pointer elimination. It also 8009467b48Spatrick /// allows more mundane (but still important) optimizations, such as reordering 8109467b48Spatrick /// of abstract objects on the stack frame. 8209467b48Spatrick /// 8309467b48Spatrick /// To support this, the class assigns unique integer identifiers to stack 8409467b48Spatrick /// objects requested clients. These identifiers are negative integers for 8509467b48Spatrick /// fixed stack objects (such as arguments passed on the stack) or nonnegative 8609467b48Spatrick /// for objects that may be reordered. Instructions which refer to stack 8709467b48Spatrick /// objects use a special MO_FrameIndex operand to represent these frame 8809467b48Spatrick /// indexes. 8909467b48Spatrick /// 9009467b48Spatrick /// Because this class keeps track of all references to the stack frame, it 9109467b48Spatrick /// knows when a variable sized object is allocated on the stack. This is the 9209467b48Spatrick /// sole condition which prevents frame pointer elimination, which is an 9309467b48Spatrick /// important optimization on register-poor architectures. Because original 9409467b48Spatrick /// variable sized alloca's in the source program are the only source of 9509467b48Spatrick /// variable sized stack objects, it is safe to decide whether there will be 9609467b48Spatrick /// any variable sized objects before all stack objects are known (for 9709467b48Spatrick /// example, register allocator spill code never needs variable sized 9809467b48Spatrick /// objects). 9909467b48Spatrick /// 10009467b48Spatrick /// When prolog/epilog code emission is performed, the final stack frame is 10109467b48Spatrick /// built and the machine instructions are modified to refer to the actual 10209467b48Spatrick /// stack offsets of the object, eliminating all MO_FrameIndex operands from 10309467b48Spatrick /// the program. 10409467b48Spatrick /// 10509467b48Spatrick /// Abstract Stack Frame Information 10609467b48Spatrick class MachineFrameInfo { 10709467b48Spatrick public: 10809467b48Spatrick /// Stack Smashing Protection (SSP) rules require that vulnerable stack 10909467b48Spatrick /// allocations are located close the stack protector. 11009467b48Spatrick enum SSPLayoutKind { 11109467b48Spatrick SSPLK_None, ///< Did not trigger a stack protector. No effect on data 11209467b48Spatrick ///< layout. 11309467b48Spatrick SSPLK_LargeArray, ///< Array or nested array >= SSP-buffer-size. Closest 11409467b48Spatrick ///< to the stack protector. 11509467b48Spatrick SSPLK_SmallArray, ///< Array or nested array < SSP-buffer-size. 2nd closest 11609467b48Spatrick ///< to the stack protector. 11709467b48Spatrick SSPLK_AddrOf ///< The address of this allocation is exposed and 11809467b48Spatrick ///< triggered protection. 3rd closest to the protector. 11909467b48Spatrick }; 12009467b48Spatrick 12109467b48Spatrick private: 12209467b48Spatrick // Represent a single object allocated on the stack. 12309467b48Spatrick struct StackObject { 12409467b48Spatrick // The offset of this object from the stack pointer on entry to 12509467b48Spatrick // the function. This field has no meaning for a variable sized element. 12609467b48Spatrick int64_t SPOffset; 12709467b48Spatrick 12809467b48Spatrick // The size of this object on the stack. 0 means a variable sized object, 12909467b48Spatrick // ~0ULL means a dead object. 13009467b48Spatrick uint64_t Size; 13109467b48Spatrick 13209467b48Spatrick // The required alignment of this stack slot. 13309467b48Spatrick Align Alignment; 13409467b48Spatrick 13509467b48Spatrick // If true, the value of the stack object is set before 13609467b48Spatrick // entering the function and is not modified inside the function. By 13709467b48Spatrick // default, fixed objects are immutable unless marked otherwise. 13809467b48Spatrick bool isImmutable; 13909467b48Spatrick 14009467b48Spatrick // If true the stack object is used as spill slot. It 14109467b48Spatrick // cannot alias any other memory objects. 14209467b48Spatrick bool isSpillSlot; 14309467b48Spatrick 14409467b48Spatrick /// If true, this stack slot is used to spill a value (could be deopt 14509467b48Spatrick /// and/or GC related) over a statepoint. We know that the address of the 14609467b48Spatrick /// slot can't alias any LLVM IR value. This is very similar to a Spill 14709467b48Spatrick /// Slot, but is created by statepoint lowering is SelectionDAG, not the 14809467b48Spatrick /// register allocator. 14909467b48Spatrick bool isStatepointSpillSlot = false; 15009467b48Spatrick 15109467b48Spatrick /// Identifier for stack memory type analagous to address space. If this is 15209467b48Spatrick /// non-0, the meaning is target defined. Offsets cannot be directly 15309467b48Spatrick /// compared between objects with different stack IDs. The object may not 15409467b48Spatrick /// necessarily reside in the same contiguous memory block as other stack 15509467b48Spatrick /// objects. Objects with differing stack IDs should not be merged or 15609467b48Spatrick /// replaced substituted for each other. 15709467b48Spatrick // 15809467b48Spatrick /// It is assumed a target uses consecutive, increasing stack IDs starting 15909467b48Spatrick /// from 1. 16009467b48Spatrick uint8_t StackID; 16109467b48Spatrick 16209467b48Spatrick /// If this stack object is originated from an Alloca instruction 16309467b48Spatrick /// this value saves the original IR allocation. Can be NULL. 16409467b48Spatrick const AllocaInst *Alloca; 16509467b48Spatrick 16609467b48Spatrick // If true, the object was mapped into the local frame 16709467b48Spatrick // block and doesn't need additional handling for allocation beyond that. 16809467b48Spatrick bool PreAllocated = false; 16909467b48Spatrick 17009467b48Spatrick // If true, an LLVM IR value might point to this object. 17109467b48Spatrick // Normally, spill slots and fixed-offset objects don't alias IR-accessible 17209467b48Spatrick // objects, but there are exceptions (on PowerPC, for example, some byval 17309467b48Spatrick // arguments have ABI-prescribed offsets). 17409467b48Spatrick bool isAliased; 17509467b48Spatrick 17609467b48Spatrick /// If true, the object has been zero-extended. 17709467b48Spatrick bool isZExt = false; 17809467b48Spatrick 179a0747c9fSpatrick /// If true, the object has been sign-extended. 18009467b48Spatrick bool isSExt = false; 18109467b48Spatrick 182*a96b3639Srobert uint8_t SSPLayout = SSPLK_None; 18309467b48Spatrick 18409467b48Spatrick StackObject(uint64_t Size, Align Alignment, int64_t SPOffset, 18509467b48Spatrick bool IsImmutable, bool IsSpillSlot, const AllocaInst *Alloca, 18609467b48Spatrick bool IsAliased, uint8_t StackID = 0) SPOffsetStackObject18709467b48Spatrick : SPOffset(SPOffset), Size(Size), Alignment(Alignment), 18809467b48Spatrick isImmutable(IsImmutable), isSpillSlot(IsSpillSlot), StackID(StackID), 189*a96b3639Srobert Alloca(Alloca), isAliased(IsAliased) {} 19009467b48Spatrick }; 19109467b48Spatrick 19209467b48Spatrick /// The alignment of the stack. 19309467b48Spatrick Align StackAlignment; 19409467b48Spatrick 19509467b48Spatrick /// Can the stack be realigned. This can be false if the target does not 19609467b48Spatrick /// support stack realignment, or if the user asks us not to realign the 19709467b48Spatrick /// stack. In this situation, overaligned allocas are all treated as dynamic 19809467b48Spatrick /// allocations and the target must handle them as part of DYNAMIC_STACKALLOC 19909467b48Spatrick /// lowering. All non-alloca stack objects have their alignment clamped to the 20009467b48Spatrick /// base ABI stack alignment. 20109467b48Spatrick /// FIXME: There is room for improvement in this case, in terms of 20209467b48Spatrick /// grouping overaligned allocas into a "secondary stack frame" and 20309467b48Spatrick /// then only use a single alloca to allocate this frame and only a 20409467b48Spatrick /// single virtual register to access it. Currently, without such an 20509467b48Spatrick /// optimization, each such alloca gets its own dynamic realignment. 20609467b48Spatrick bool StackRealignable; 20709467b48Spatrick 20809467b48Spatrick /// Whether the function has the \c alignstack attribute. 20909467b48Spatrick bool ForcedRealign; 21009467b48Spatrick 21109467b48Spatrick /// The list of stack objects allocated. 21209467b48Spatrick std::vector<StackObject> Objects; 21309467b48Spatrick 21409467b48Spatrick /// This contains the number of fixed objects contained on 21509467b48Spatrick /// the stack. Because fixed objects are stored at a negative index in the 21609467b48Spatrick /// Objects list, this is also the index to the 0th object in the list. 21709467b48Spatrick unsigned NumFixedObjects = 0; 21809467b48Spatrick 21909467b48Spatrick /// This boolean keeps track of whether any variable 22009467b48Spatrick /// sized objects have been allocated yet. 22109467b48Spatrick bool HasVarSizedObjects = false; 22209467b48Spatrick 22309467b48Spatrick /// This boolean keeps track of whether there is a call 22409467b48Spatrick /// to builtin \@llvm.frameaddress. 22509467b48Spatrick bool FrameAddressTaken = false; 22609467b48Spatrick 22709467b48Spatrick /// This boolean keeps track of whether there is a call 22809467b48Spatrick /// to builtin \@llvm.returnaddress. 22909467b48Spatrick bool ReturnAddressTaken = false; 23009467b48Spatrick 23109467b48Spatrick /// This boolean keeps track of whether there is a call 23209467b48Spatrick /// to builtin \@llvm.experimental.stackmap. 23309467b48Spatrick bool HasStackMap = false; 23409467b48Spatrick 23509467b48Spatrick /// This boolean keeps track of whether there is a call 23609467b48Spatrick /// to builtin \@llvm.experimental.patchpoint. 23709467b48Spatrick bool HasPatchPoint = false; 23809467b48Spatrick 23909467b48Spatrick /// The prolog/epilog code inserter calculates the final stack 24009467b48Spatrick /// offsets for all of the fixed size objects, updating the Objects list 24109467b48Spatrick /// above. It then updates StackSize to contain the number of bytes that need 24209467b48Spatrick /// to be allocated on entry to the function. 24309467b48Spatrick uint64_t StackSize = 0; 24409467b48Spatrick 24509467b48Spatrick /// The amount that a frame offset needs to be adjusted to 24609467b48Spatrick /// have the actual offset from the stack/frame pointer. The exact usage of 24709467b48Spatrick /// this is target-dependent, but it is typically used to adjust between 24809467b48Spatrick /// SP-relative and FP-relative offsets. E.G., if objects are accessed via 24909467b48Spatrick /// SP then OffsetAdjustment is zero; if FP is used, OffsetAdjustment is set 25009467b48Spatrick /// to the distance between the initial SP and the value in FP. For many 25109467b48Spatrick /// targets, this value is only used when generating debug info (via 25209467b48Spatrick /// TargetRegisterInfo::getFrameIndexReference); when generating code, the 25309467b48Spatrick /// corresponding adjustments are performed directly. 25409467b48Spatrick int OffsetAdjustment = 0; 25509467b48Spatrick 25609467b48Spatrick /// The prolog/epilog code inserter may process objects that require greater 25709467b48Spatrick /// alignment than the default alignment the target provides. 25809467b48Spatrick /// To handle this, MaxAlignment is set to the maximum alignment 25909467b48Spatrick /// needed by the objects on the current frame. If this is greater than the 26009467b48Spatrick /// native alignment maintained by the compiler, dynamic alignment code will 26109467b48Spatrick /// be needed. 26209467b48Spatrick /// 26309467b48Spatrick Align MaxAlignment; 26409467b48Spatrick 26509467b48Spatrick /// Set to true if this function adjusts the stack -- e.g., 26609467b48Spatrick /// when calling another function. This is only valid during and after 26709467b48Spatrick /// prolog/epilog code insertion. 26809467b48Spatrick bool AdjustsStack = false; 26909467b48Spatrick 27009467b48Spatrick /// Set to true if this function has any function calls. 27109467b48Spatrick bool HasCalls = false; 27209467b48Spatrick 27309467b48Spatrick /// The frame index for the stack protector. 27409467b48Spatrick int StackProtectorIdx = -1; 27509467b48Spatrick 276adae0cfdSpatrick struct ReturnProtector { 277adae0cfdSpatrick /// The register to use for return protector calculations 278adae0cfdSpatrick unsigned Register = 0; 279adae0cfdSpatrick /// Set to true if this function needs return protectors 280adae0cfdSpatrick bool Needed = false; 281adae0cfdSpatrick /// Does the return protector cookie need to be stored in frame 282adae0cfdSpatrick bool NeedsStore = true; 283adae0cfdSpatrick } RPI; 284adae0cfdSpatrick 28509467b48Spatrick /// The frame index for the function context. Used for SjLj exceptions. 28609467b48Spatrick int FunctionContextIdx = -1; 28709467b48Spatrick 28809467b48Spatrick /// This contains the size of the largest call frame if the target uses frame 28909467b48Spatrick /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo 29009467b48Spatrick /// class). This information is important for frame pointer elimination. 29109467b48Spatrick /// It is only valid during and after prolog/epilog code insertion. 29209467b48Spatrick unsigned MaxCallFrameSize = ~0u; 29309467b48Spatrick 29409467b48Spatrick /// The number of bytes of callee saved registers that the target wants to 29509467b48Spatrick /// report for the current function in the CodeView S_FRAMEPROC record. 29609467b48Spatrick unsigned CVBytesOfCalleeSavedRegisters = 0; 29709467b48Spatrick 29809467b48Spatrick /// The prolog/epilog code inserter fills in this vector with each 29909467b48Spatrick /// callee saved register saved in either the frame or a different 30009467b48Spatrick /// register. Beyond its use by the prolog/ epilog code inserter, 30109467b48Spatrick /// this data is used for debug info and exception handling. 30209467b48Spatrick std::vector<CalleeSavedInfo> CSInfo; 30309467b48Spatrick 30409467b48Spatrick /// Has CSInfo been set yet? 30509467b48Spatrick bool CSIValid = false; 30609467b48Spatrick 30709467b48Spatrick /// References to frame indices which are mapped 30809467b48Spatrick /// into the local frame allocation block. <FrameIdx, LocalOffset> 30909467b48Spatrick SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects; 31009467b48Spatrick 31109467b48Spatrick /// Size of the pre-allocated local frame block. 31209467b48Spatrick int64_t LocalFrameSize = 0; 31309467b48Spatrick 31409467b48Spatrick /// Required alignment of the local object blob, which is the strictest 31509467b48Spatrick /// alignment of any object in it. 31609467b48Spatrick Align LocalFrameMaxAlign; 31709467b48Spatrick 31809467b48Spatrick /// Whether the local object blob needs to be allocated together. If not, 31909467b48Spatrick /// PEI should ignore the isPreAllocated flags on the stack objects and 32009467b48Spatrick /// just allocate them normally. 32109467b48Spatrick bool UseLocalStackAllocationBlock = false; 32209467b48Spatrick 32309467b48Spatrick /// True if the function dynamically adjusts the stack pointer through some 32409467b48Spatrick /// opaque mechanism like inline assembly or Win32 EH. 32509467b48Spatrick bool HasOpaqueSPAdjustment = false; 32609467b48Spatrick 32709467b48Spatrick /// True if the function contains operations which will lower down to 32809467b48Spatrick /// instructions which manipulate the stack pointer. 32909467b48Spatrick bool HasCopyImplyingStackAdjustment = false; 33009467b48Spatrick 33109467b48Spatrick /// True if the function contains a call to the llvm.vastart intrinsic. 33209467b48Spatrick bool HasVAStart = false; 33309467b48Spatrick 33409467b48Spatrick /// True if this is a varargs function that contains a musttail call. 33509467b48Spatrick bool HasMustTailInVarArgFunc = false; 33609467b48Spatrick 33709467b48Spatrick /// True if this function contains a tail call. If so immutable objects like 33809467b48Spatrick /// function arguments are no longer so. A tail call *can* override fixed 33909467b48Spatrick /// stack objects like arguments so we can't treat them as immutable. 34009467b48Spatrick bool HasTailCall = false; 34109467b48Spatrick 34209467b48Spatrick /// Not null, if shrink-wrapping found a better place for the prologue. 34309467b48Spatrick MachineBasicBlock *Save = nullptr; 34409467b48Spatrick /// Not null, if shrink-wrapping found a better place for the epilogue. 34509467b48Spatrick MachineBasicBlock *Restore = nullptr; 34609467b48Spatrick 347*a96b3639Srobert /// Size of the UnsafeStack Frame 348*a96b3639Srobert uint64_t UnsafeStackSize = 0; 349*a96b3639Srobert 35009467b48Spatrick public: MachineFrameInfo(Align StackAlignment,bool StackRealignable,bool ForcedRealign)351*a96b3639Srobert explicit MachineFrameInfo(Align StackAlignment, bool StackRealignable, 35209467b48Spatrick bool ForcedRealign) 353*a96b3639Srobert : StackAlignment(StackAlignment), 35409467b48Spatrick StackRealignable(StackRealignable), ForcedRealign(ForcedRealign) {} 35509467b48Spatrick 356*a96b3639Srobert MachineFrameInfo(const MachineFrameInfo &) = delete; 357*a96b3639Srobert 35809467b48Spatrick /// Return true if there are any stack objects in this function. hasStackObjects()35909467b48Spatrick bool hasStackObjects() const { return !Objects.empty(); } 36009467b48Spatrick 36109467b48Spatrick /// This method may be called any time after instruction 36209467b48Spatrick /// selection is complete to determine if the stack frame for this function 36309467b48Spatrick /// contains any variable sized objects. hasVarSizedObjects()36409467b48Spatrick bool hasVarSizedObjects() const { return HasVarSizedObjects; } 36509467b48Spatrick 36609467b48Spatrick /// Return the index for the stack protector object. getStackProtectorIndex()36709467b48Spatrick int getStackProtectorIndex() const { return StackProtectorIdx; } setStackProtectorIndex(int I)36809467b48Spatrick void setStackProtectorIndex(int I) { StackProtectorIdx = I; } hasStackProtectorIndex()36909467b48Spatrick bool hasStackProtectorIndex() const { return StackProtectorIdx != -1; } 37009467b48Spatrick 371adae0cfdSpatrick /// Get / Set return protector calculation register getReturnProtectorRegister()372adae0cfdSpatrick unsigned getReturnProtectorRegister() const { return RPI.Register; } setReturnProtectorRegister(unsigned I)373adae0cfdSpatrick void setReturnProtectorRegister(unsigned I) { RPI.Register = I; } hasReturnProtectorRegister()374adae0cfdSpatrick bool hasReturnProtectorRegister() const { return RPI.Register != 0; } 375adae0cfdSpatrick /// Get / Set if this frame needs a return protector setReturnProtectorNeeded(bool I)376adae0cfdSpatrick void setReturnProtectorNeeded(bool I) { RPI.Needed = I; } getReturnProtectorNeeded()377adae0cfdSpatrick bool getReturnProtectorNeeded() const { return RPI.Needed; } 378adae0cfdSpatrick /// Get / Set if the return protector cookie needs to be stored in frame setReturnProtectorNeedsStore(bool I)379adae0cfdSpatrick void setReturnProtectorNeedsStore(bool I) { RPI.NeedsStore = I; } getReturnProtectorNeedsStore()380adae0cfdSpatrick bool getReturnProtectorNeedsStore() const { return RPI.NeedsStore; } 381adae0cfdSpatrick 38209467b48Spatrick /// Return the index for the function context object. 38309467b48Spatrick /// This object is used for SjLj exceptions. getFunctionContextIndex()38409467b48Spatrick int getFunctionContextIndex() const { return FunctionContextIdx; } setFunctionContextIndex(int I)38509467b48Spatrick void setFunctionContextIndex(int I) { FunctionContextIdx = I; } hasFunctionContextIndex()386*a96b3639Srobert bool hasFunctionContextIndex() const { return FunctionContextIdx != -1; } 38709467b48Spatrick 38809467b48Spatrick /// This method may be called any time after instruction 38909467b48Spatrick /// selection is complete to determine if there is a call to 39009467b48Spatrick /// \@llvm.frameaddress in this function. isFrameAddressTaken()39109467b48Spatrick bool isFrameAddressTaken() const { return FrameAddressTaken; } setFrameAddressIsTaken(bool T)39209467b48Spatrick void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } 39309467b48Spatrick 39409467b48Spatrick /// This method may be called any time after 39509467b48Spatrick /// instruction selection is complete to determine if there is a call to 39609467b48Spatrick /// \@llvm.returnaddress in this function. isReturnAddressTaken()39709467b48Spatrick bool isReturnAddressTaken() const { return ReturnAddressTaken; } setReturnAddressIsTaken(bool s)39809467b48Spatrick void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } 39909467b48Spatrick 40009467b48Spatrick /// This method may be called any time after instruction 40109467b48Spatrick /// selection is complete to determine if there is a call to builtin 40209467b48Spatrick /// \@llvm.experimental.stackmap. hasStackMap()40309467b48Spatrick bool hasStackMap() const { return HasStackMap; } 40409467b48Spatrick void setHasStackMap(bool s = true) { HasStackMap = s; } 40509467b48Spatrick 40609467b48Spatrick /// This method may be called any time after instruction 40709467b48Spatrick /// selection is complete to determine if there is a call to builtin 40809467b48Spatrick /// \@llvm.experimental.patchpoint. hasPatchPoint()40909467b48Spatrick bool hasPatchPoint() const { return HasPatchPoint; } 41009467b48Spatrick void setHasPatchPoint(bool s = true) { HasPatchPoint = s; } 41109467b48Spatrick 412*a96b3639Srobert /// Return true if this function requires a split stack prolog, even if it 413*a96b3639Srobert /// uses no stack space. This is only meaningful for functions where 414*a96b3639Srobert /// MachineFunction::shouldSplitStack() returns true. 415*a96b3639Srobert // 416*a96b3639Srobert // For non-leaf functions we have to allow for the possibility that the call 417*a96b3639Srobert // is to a non-split function, as in PR37807. This function could also take 418*a96b3639Srobert // the address of a non-split function. When the linker tries to adjust its 419*a96b3639Srobert // non-existent prologue, it would fail with an error. Mark the object file so 420*a96b3639Srobert // that such failures are not errors. See this Go language bug-report 421*a96b3639Srobert // https://go-review.googlesource.com/c/go/+/148819/ needsSplitStackProlog()422*a96b3639Srobert bool needsSplitStackProlog() const { 423*a96b3639Srobert return getStackSize() != 0 || hasTailCall(); 424*a96b3639Srobert } 425*a96b3639Srobert 42609467b48Spatrick /// Return the minimum frame object index. getObjectIndexBegin()42709467b48Spatrick int getObjectIndexBegin() const { return -NumFixedObjects; } 42809467b48Spatrick 42909467b48Spatrick /// Return one past the maximum frame object index. getObjectIndexEnd()43009467b48Spatrick int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; } 43109467b48Spatrick 43209467b48Spatrick /// Return the number of fixed objects. getNumFixedObjects()43309467b48Spatrick unsigned getNumFixedObjects() const { return NumFixedObjects; } 43409467b48Spatrick 43509467b48Spatrick /// Return the number of objects. getNumObjects()43609467b48Spatrick unsigned getNumObjects() const { return Objects.size(); } 43709467b48Spatrick 43809467b48Spatrick /// Map a frame index into the local object block mapLocalFrameObject(int ObjectIndex,int64_t Offset)43909467b48Spatrick void mapLocalFrameObject(int ObjectIndex, int64_t Offset) { 44009467b48Spatrick LocalFrameObjects.push_back(std::pair<int, int64_t>(ObjectIndex, Offset)); 44109467b48Spatrick Objects[ObjectIndex + NumFixedObjects].PreAllocated = true; 44209467b48Spatrick } 44309467b48Spatrick 44409467b48Spatrick /// Get the local offset mapping for a for an object. getLocalFrameObjectMap(int i)44509467b48Spatrick std::pair<int, int64_t> getLocalFrameObjectMap(int i) const { 44609467b48Spatrick assert (i >= 0 && (unsigned)i < LocalFrameObjects.size() && 44709467b48Spatrick "Invalid local object reference!"); 44809467b48Spatrick return LocalFrameObjects[i]; 44909467b48Spatrick } 45009467b48Spatrick 45109467b48Spatrick /// Return the number of objects allocated into the local object block. getLocalFrameObjectCount()45209467b48Spatrick int64_t getLocalFrameObjectCount() const { return LocalFrameObjects.size(); } 45309467b48Spatrick 45409467b48Spatrick /// Set the size of the local object blob. setLocalFrameSize(int64_t sz)45509467b48Spatrick void setLocalFrameSize(int64_t sz) { LocalFrameSize = sz; } 45609467b48Spatrick 45709467b48Spatrick /// Get the size of the local object blob. getLocalFrameSize()45809467b48Spatrick int64_t getLocalFrameSize() const { return LocalFrameSize; } 45909467b48Spatrick 46009467b48Spatrick /// Required alignment of the local object blob, 46109467b48Spatrick /// which is the strictest alignment of any object in it. setLocalFrameMaxAlign(Align Alignment)46209467b48Spatrick void setLocalFrameMaxAlign(Align Alignment) { 46309467b48Spatrick LocalFrameMaxAlign = Alignment; 46409467b48Spatrick } 46509467b48Spatrick 46609467b48Spatrick /// Return the required alignment of the local object blob. getLocalFrameMaxAlign()46709467b48Spatrick Align getLocalFrameMaxAlign() const { return LocalFrameMaxAlign; } 46809467b48Spatrick 46909467b48Spatrick /// Get whether the local allocation blob should be allocated together or 47009467b48Spatrick /// let PEI allocate the locals in it directly. getUseLocalStackAllocationBlock()47109467b48Spatrick bool getUseLocalStackAllocationBlock() const { 47209467b48Spatrick return UseLocalStackAllocationBlock; 47309467b48Spatrick } 47409467b48Spatrick 47509467b48Spatrick /// setUseLocalStackAllocationBlock - Set whether the local allocation blob 47609467b48Spatrick /// should be allocated together or let PEI allocate the locals in it 47709467b48Spatrick /// directly. setUseLocalStackAllocationBlock(bool v)47809467b48Spatrick void setUseLocalStackAllocationBlock(bool v) { 47909467b48Spatrick UseLocalStackAllocationBlock = v; 48009467b48Spatrick } 48109467b48Spatrick 48209467b48Spatrick /// Return true if the object was pre-allocated into the local block. isObjectPreAllocated(int ObjectIdx)48309467b48Spatrick bool isObjectPreAllocated(int ObjectIdx) const { 48409467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 48509467b48Spatrick "Invalid Object Idx!"); 48609467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].PreAllocated; 48709467b48Spatrick } 48809467b48Spatrick 48909467b48Spatrick /// Return the size of the specified object. getObjectSize(int ObjectIdx)49009467b48Spatrick int64_t getObjectSize(int ObjectIdx) const { 49109467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 49209467b48Spatrick "Invalid Object Idx!"); 49309467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].Size; 49409467b48Spatrick } 49509467b48Spatrick 49609467b48Spatrick /// Change the size of the specified stack object. setObjectSize(int ObjectIdx,int64_t Size)49709467b48Spatrick void setObjectSize(int ObjectIdx, int64_t Size) { 49809467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 49909467b48Spatrick "Invalid Object Idx!"); 50009467b48Spatrick Objects[ObjectIdx+NumFixedObjects].Size = Size; 50109467b48Spatrick } 50209467b48Spatrick 50309467b48Spatrick /// Return the alignment of the specified stack object. getObjectAlign(int ObjectIdx)504097a140dSpatrick Align getObjectAlign(int ObjectIdx) const { 50509467b48Spatrick assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && 50609467b48Spatrick "Invalid Object Idx!"); 507097a140dSpatrick return Objects[ObjectIdx + NumFixedObjects].Alignment; 50809467b48Spatrick } 50909467b48Spatrick 510*a96b3639Srobert /// Should this stack ID be considered in MaxAlignment. contributesToMaxAlignment(uint8_t StackID)511*a96b3639Srobert bool contributesToMaxAlignment(uint8_t StackID) { 512*a96b3639Srobert return StackID == TargetStackID::Default || 513*a96b3639Srobert StackID == TargetStackID::ScalableVector; 514*a96b3639Srobert } 515*a96b3639Srobert 51609467b48Spatrick /// setObjectAlignment - Change the alignment of the specified stack object. setObjectAlignment(int ObjectIdx,Align Alignment)517097a140dSpatrick void setObjectAlignment(int ObjectIdx, Align Alignment) { 51809467b48Spatrick assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && 51909467b48Spatrick "Invalid Object Idx!"); 520097a140dSpatrick Objects[ObjectIdx + NumFixedObjects].Alignment = Alignment; 52109467b48Spatrick 522*a96b3639Srobert // Only ensure max alignment for the default and scalable vector stack. 523*a96b3639Srobert uint8_t StackID = getStackID(ObjectIdx); 524*a96b3639Srobert if (contributesToMaxAlignment(StackID)) 525097a140dSpatrick ensureMaxAlignment(Alignment); 526097a140dSpatrick } 527097a140dSpatrick 52809467b48Spatrick /// Return the underlying Alloca of the specified 52909467b48Spatrick /// stack object if it exists. Returns 0 if none exists. getObjectAllocation(int ObjectIdx)53009467b48Spatrick const AllocaInst* getObjectAllocation(int ObjectIdx) const { 53109467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 53209467b48Spatrick "Invalid Object Idx!"); 53309467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].Alloca; 53409467b48Spatrick } 53509467b48Spatrick 536*a96b3639Srobert /// Remove the underlying Alloca of the specified stack object if it 537*a96b3639Srobert /// exists. This generally should not be used and is for reduction tooling. clearObjectAllocation(int ObjectIdx)538*a96b3639Srobert void clearObjectAllocation(int ObjectIdx) { 539*a96b3639Srobert assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && 540*a96b3639Srobert "Invalid Object Idx!"); 541*a96b3639Srobert Objects[ObjectIdx + NumFixedObjects].Alloca = nullptr; 542*a96b3639Srobert } 543*a96b3639Srobert 54409467b48Spatrick /// Return the assigned stack offset of the specified object 54509467b48Spatrick /// from the incoming stack pointer. getObjectOffset(int ObjectIdx)54609467b48Spatrick int64_t getObjectOffset(int ObjectIdx) const { 54709467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 54809467b48Spatrick "Invalid Object Idx!"); 54909467b48Spatrick assert(!isDeadObjectIndex(ObjectIdx) && 55009467b48Spatrick "Getting frame offset for a dead object?"); 55109467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].SPOffset; 55209467b48Spatrick } 55309467b48Spatrick isObjectZExt(int ObjectIdx)55409467b48Spatrick bool isObjectZExt(int ObjectIdx) const { 55509467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 55609467b48Spatrick "Invalid Object Idx!"); 55709467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isZExt; 55809467b48Spatrick } 55909467b48Spatrick setObjectZExt(int ObjectIdx,bool IsZExt)56009467b48Spatrick void setObjectZExt(int ObjectIdx, bool IsZExt) { 56109467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 56209467b48Spatrick "Invalid Object Idx!"); 56309467b48Spatrick Objects[ObjectIdx+NumFixedObjects].isZExt = IsZExt; 56409467b48Spatrick } 56509467b48Spatrick isObjectSExt(int ObjectIdx)56609467b48Spatrick bool isObjectSExt(int ObjectIdx) const { 56709467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 56809467b48Spatrick "Invalid Object Idx!"); 56909467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isSExt; 57009467b48Spatrick } 57109467b48Spatrick setObjectSExt(int ObjectIdx,bool IsSExt)57209467b48Spatrick void setObjectSExt(int ObjectIdx, bool IsSExt) { 57309467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 57409467b48Spatrick "Invalid Object Idx!"); 57509467b48Spatrick Objects[ObjectIdx+NumFixedObjects].isSExt = IsSExt; 57609467b48Spatrick } 57709467b48Spatrick 57809467b48Spatrick /// Set the stack frame offset of the specified object. The 57909467b48Spatrick /// offset is relative to the stack pointer on entry to the function. setObjectOffset(int ObjectIdx,int64_t SPOffset)58009467b48Spatrick void setObjectOffset(int ObjectIdx, int64_t SPOffset) { 58109467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 58209467b48Spatrick "Invalid Object Idx!"); 58309467b48Spatrick assert(!isDeadObjectIndex(ObjectIdx) && 58409467b48Spatrick "Setting frame offset for a dead object?"); 58509467b48Spatrick Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; 58609467b48Spatrick } 58709467b48Spatrick getObjectSSPLayout(int ObjectIdx)58809467b48Spatrick SSPLayoutKind getObjectSSPLayout(int ObjectIdx) const { 58909467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 59009467b48Spatrick "Invalid Object Idx!"); 59109467b48Spatrick return (SSPLayoutKind)Objects[ObjectIdx+NumFixedObjects].SSPLayout; 59209467b48Spatrick } 59309467b48Spatrick setObjectSSPLayout(int ObjectIdx,SSPLayoutKind Kind)59409467b48Spatrick void setObjectSSPLayout(int ObjectIdx, SSPLayoutKind Kind) { 59509467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 59609467b48Spatrick "Invalid Object Idx!"); 59709467b48Spatrick assert(!isDeadObjectIndex(ObjectIdx) && 59809467b48Spatrick "Setting SSP layout for a dead object?"); 59909467b48Spatrick Objects[ObjectIdx+NumFixedObjects].SSPLayout = Kind; 60009467b48Spatrick } 60109467b48Spatrick 60209467b48Spatrick /// Return the number of bytes that must be allocated to hold 60309467b48Spatrick /// all of the fixed size frame objects. This is only valid after 60409467b48Spatrick /// Prolog/Epilog code insertion has finalized the stack frame layout. getStackSize()60509467b48Spatrick uint64_t getStackSize() const { return StackSize; } 60609467b48Spatrick 60709467b48Spatrick /// Set the size of the stack. setStackSize(uint64_t Size)60809467b48Spatrick void setStackSize(uint64_t Size) { StackSize = Size; } 60909467b48Spatrick 61009467b48Spatrick /// Estimate and return the size of the stack frame. 61109467b48Spatrick uint64_t estimateStackSize(const MachineFunction &MF) const; 61209467b48Spatrick 61309467b48Spatrick /// Return the correction for frame offsets. getOffsetAdjustment()61409467b48Spatrick int getOffsetAdjustment() const { return OffsetAdjustment; } 61509467b48Spatrick 61609467b48Spatrick /// Set the correction for frame offsets. setOffsetAdjustment(int Adj)61709467b48Spatrick void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } 61809467b48Spatrick 61909467b48Spatrick /// Return the alignment in bytes that this function must be aligned to, 62009467b48Spatrick /// which is greater than the default stack alignment provided by the target. getMaxAlign()621097a140dSpatrick Align getMaxAlign() const { return MaxAlignment; } 62209467b48Spatrick 62309467b48Spatrick /// Make sure the function is at least Align bytes aligned. 62409467b48Spatrick void ensureMaxAlignment(Align Alignment); 625097a140dSpatrick 62609467b48Spatrick /// Return true if this function adjusts the stack -- e.g., 62709467b48Spatrick /// when calling another function. This is only valid during and after 62809467b48Spatrick /// prolog/epilog code insertion. adjustsStack()62909467b48Spatrick bool adjustsStack() const { return AdjustsStack; } setAdjustsStack(bool V)63009467b48Spatrick void setAdjustsStack(bool V) { AdjustsStack = V; } 63109467b48Spatrick 63209467b48Spatrick /// Return true if the current function has any function calls. hasCalls()63309467b48Spatrick bool hasCalls() const { return HasCalls; } setHasCalls(bool V)63409467b48Spatrick void setHasCalls(bool V) { HasCalls = V; } 63509467b48Spatrick 63609467b48Spatrick /// Returns true if the function contains opaque dynamic stack adjustments. hasOpaqueSPAdjustment()63709467b48Spatrick bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; } setHasOpaqueSPAdjustment(bool B)63809467b48Spatrick void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; } 63909467b48Spatrick 64009467b48Spatrick /// Returns true if the function contains operations which will lower down to 64109467b48Spatrick /// instructions which manipulate the stack pointer. hasCopyImplyingStackAdjustment()64209467b48Spatrick bool hasCopyImplyingStackAdjustment() const { 64309467b48Spatrick return HasCopyImplyingStackAdjustment; 64409467b48Spatrick } setHasCopyImplyingStackAdjustment(bool B)64509467b48Spatrick void setHasCopyImplyingStackAdjustment(bool B) { 64609467b48Spatrick HasCopyImplyingStackAdjustment = B; 64709467b48Spatrick } 64809467b48Spatrick 64909467b48Spatrick /// Returns true if the function calls the llvm.va_start intrinsic. hasVAStart()65009467b48Spatrick bool hasVAStart() const { return HasVAStart; } setHasVAStart(bool B)65109467b48Spatrick void setHasVAStart(bool B) { HasVAStart = B; } 65209467b48Spatrick 65309467b48Spatrick /// Returns true if the function is variadic and contains a musttail call. hasMustTailInVarArgFunc()65409467b48Spatrick bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } setHasMustTailInVarArgFunc(bool B)65509467b48Spatrick void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } 65609467b48Spatrick 65709467b48Spatrick /// Returns true if the function contains a tail call. hasTailCall()65809467b48Spatrick bool hasTailCall() const { return HasTailCall; } 659a0747c9fSpatrick void setHasTailCall(bool V = true) { HasTailCall = V; } 66009467b48Spatrick 66109467b48Spatrick /// Computes the maximum size of a callframe and the AdjustsStack property. 66209467b48Spatrick /// This only works for targets defining 66309467b48Spatrick /// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(), 66409467b48Spatrick /// and getFrameSize(). 66509467b48Spatrick /// This is usually computed by the prologue epilogue inserter but some 66609467b48Spatrick /// targets may call this to compute it earlier. 66709467b48Spatrick void computeMaxCallFrameSize(const MachineFunction &MF); 66809467b48Spatrick 66909467b48Spatrick /// Return the maximum size of a call frame that must be 67009467b48Spatrick /// allocated for an outgoing function call. This is only available if 67109467b48Spatrick /// CallFrameSetup/Destroy pseudo instructions are used by the target, and 67209467b48Spatrick /// then only during or after prolog/epilog code insertion. 67309467b48Spatrick /// getMaxCallFrameSize()67409467b48Spatrick unsigned getMaxCallFrameSize() const { 67509467b48Spatrick // TODO: Enable this assert when targets are fixed. 67609467b48Spatrick //assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet"); 67709467b48Spatrick if (!isMaxCallFrameSizeComputed()) 67809467b48Spatrick return 0; 67909467b48Spatrick return MaxCallFrameSize; 68009467b48Spatrick } isMaxCallFrameSizeComputed()68109467b48Spatrick bool isMaxCallFrameSizeComputed() const { 68209467b48Spatrick return MaxCallFrameSize != ~0u; 68309467b48Spatrick } setMaxCallFrameSize(unsigned S)68409467b48Spatrick void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } 68509467b48Spatrick 68609467b48Spatrick /// Returns how many bytes of callee-saved registers the target pushed in the 68709467b48Spatrick /// prologue. Only used for debug info. getCVBytesOfCalleeSavedRegisters()68809467b48Spatrick unsigned getCVBytesOfCalleeSavedRegisters() const { 68909467b48Spatrick return CVBytesOfCalleeSavedRegisters; 69009467b48Spatrick } setCVBytesOfCalleeSavedRegisters(unsigned S)69109467b48Spatrick void setCVBytesOfCalleeSavedRegisters(unsigned S) { 69209467b48Spatrick CVBytesOfCalleeSavedRegisters = S; 69309467b48Spatrick } 69409467b48Spatrick 69509467b48Spatrick /// Create a new object at a fixed location on the stack. 69609467b48Spatrick /// All fixed objects should be created before other objects are created for 69709467b48Spatrick /// efficiency. By default, fixed objects are not pointed to by LLVM IR 69809467b48Spatrick /// values. This returns an index with a negative value. 69909467b48Spatrick int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, 70009467b48Spatrick bool isAliased = false); 70109467b48Spatrick 70209467b48Spatrick /// Create a spill slot at a fixed location on the stack. 70309467b48Spatrick /// Returns an index with a negative value. 70409467b48Spatrick int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, 70509467b48Spatrick bool IsImmutable = false); 70609467b48Spatrick 70709467b48Spatrick /// Returns true if the specified index corresponds to a fixed stack object. isFixedObjectIndex(int ObjectIdx)70809467b48Spatrick bool isFixedObjectIndex(int ObjectIdx) const { 70909467b48Spatrick return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); 71009467b48Spatrick } 71109467b48Spatrick 71209467b48Spatrick /// Returns true if the specified index corresponds 71309467b48Spatrick /// to an object that might be pointed to by an LLVM IR value. isAliasedObjectIndex(int ObjectIdx)71409467b48Spatrick bool isAliasedObjectIndex(int ObjectIdx) const { 71509467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 71609467b48Spatrick "Invalid Object Idx!"); 71709467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isAliased; 71809467b48Spatrick } 71909467b48Spatrick 72009467b48Spatrick /// Returns true if the specified index corresponds to an immutable object. isImmutableObjectIndex(int ObjectIdx)72109467b48Spatrick bool isImmutableObjectIndex(int ObjectIdx) const { 72209467b48Spatrick // Tail calling functions can clobber their function arguments. 72309467b48Spatrick if (HasTailCall) 72409467b48Spatrick return false; 72509467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 72609467b48Spatrick "Invalid Object Idx!"); 72709467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isImmutable; 72809467b48Spatrick } 72909467b48Spatrick 73009467b48Spatrick /// Marks the immutability of an object. setIsImmutableObjectIndex(int ObjectIdx,bool IsImmutable)73109467b48Spatrick void setIsImmutableObjectIndex(int ObjectIdx, bool IsImmutable) { 73209467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 73309467b48Spatrick "Invalid Object Idx!"); 73409467b48Spatrick Objects[ObjectIdx+NumFixedObjects].isImmutable = IsImmutable; 73509467b48Spatrick } 73609467b48Spatrick 73709467b48Spatrick /// Returns true if the specified index corresponds to a spill slot. isSpillSlotObjectIndex(int ObjectIdx)73809467b48Spatrick bool isSpillSlotObjectIndex(int ObjectIdx) const { 73909467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 74009467b48Spatrick "Invalid Object Idx!"); 74109467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isSpillSlot; 74209467b48Spatrick } 74309467b48Spatrick isStatepointSpillSlotObjectIndex(int ObjectIdx)74409467b48Spatrick bool isStatepointSpillSlotObjectIndex(int ObjectIdx) const { 74509467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 74609467b48Spatrick "Invalid Object Idx!"); 74709467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].isStatepointSpillSlot; 74809467b48Spatrick } 74909467b48Spatrick 75009467b48Spatrick /// \see StackID getStackID(int ObjectIdx)75109467b48Spatrick uint8_t getStackID(int ObjectIdx) const { 75209467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].StackID; 75309467b48Spatrick } 75409467b48Spatrick 75509467b48Spatrick /// \see StackID setStackID(int ObjectIdx,uint8_t ID)75609467b48Spatrick void setStackID(int ObjectIdx, uint8_t ID) { 75709467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 75809467b48Spatrick "Invalid Object Idx!"); 75909467b48Spatrick Objects[ObjectIdx+NumFixedObjects].StackID = ID; 76009467b48Spatrick // If ID > 0, MaxAlignment may now be overly conservative. 76109467b48Spatrick // If ID == 0, MaxAlignment will need to be updated separately. 76209467b48Spatrick } 76309467b48Spatrick 76409467b48Spatrick /// Returns true if the specified index corresponds to a dead object. isDeadObjectIndex(int ObjectIdx)76509467b48Spatrick bool isDeadObjectIndex(int ObjectIdx) const { 76609467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 76709467b48Spatrick "Invalid Object Idx!"); 76809467b48Spatrick return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; 76909467b48Spatrick } 77009467b48Spatrick 77109467b48Spatrick /// Returns true if the specified index corresponds to a variable sized 77209467b48Spatrick /// object. isVariableSizedObjectIndex(int ObjectIdx)77309467b48Spatrick bool isVariableSizedObjectIndex(int ObjectIdx) const { 77409467b48Spatrick assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && 77509467b48Spatrick "Invalid Object Idx!"); 77609467b48Spatrick return Objects[ObjectIdx + NumFixedObjects].Size == 0; 77709467b48Spatrick } 77809467b48Spatrick markAsStatepointSpillSlotObjectIndex(int ObjectIdx)77909467b48Spatrick void markAsStatepointSpillSlotObjectIndex(int ObjectIdx) { 78009467b48Spatrick assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && 78109467b48Spatrick "Invalid Object Idx!"); 78209467b48Spatrick Objects[ObjectIdx+NumFixedObjects].isStatepointSpillSlot = true; 78309467b48Spatrick assert(isStatepointSpillSlotObjectIndex(ObjectIdx) && "inconsistent"); 78409467b48Spatrick } 78509467b48Spatrick 78609467b48Spatrick /// Create a new statically sized stack object, returning 78709467b48Spatrick /// a nonnegative identifier to represent it. 78809467b48Spatrick int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, 78909467b48Spatrick const AllocaInst *Alloca = nullptr, uint8_t ID = 0); 79009467b48Spatrick 79109467b48Spatrick /// Create a new statically sized stack object that represents a spill slot, 79209467b48Spatrick /// returning a nonnegative identifier to represent it. 79309467b48Spatrick int CreateSpillStackObject(uint64_t Size, Align Alignment); 79409467b48Spatrick 79509467b48Spatrick /// Remove or mark dead a statically sized stack object. RemoveStackObject(int ObjectIdx)79609467b48Spatrick void RemoveStackObject(int ObjectIdx) { 79709467b48Spatrick // Mark it dead. 79809467b48Spatrick Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL; 79909467b48Spatrick } 80009467b48Spatrick 80109467b48Spatrick /// Notify the MachineFrameInfo object that a variable sized object has been 80209467b48Spatrick /// created. This must be created whenever a variable sized object is 80309467b48Spatrick /// created, whether or not the index returned is actually used. 80409467b48Spatrick int CreateVariableSizedObject(Align Alignment, const AllocaInst *Alloca); 80509467b48Spatrick 80609467b48Spatrick /// Returns a reference to call saved info vector for the current function. getCalleeSavedInfo()80709467b48Spatrick const std::vector<CalleeSavedInfo> &getCalleeSavedInfo() const { 80809467b48Spatrick return CSInfo; 80909467b48Spatrick } 81009467b48Spatrick /// \copydoc getCalleeSavedInfo() getCalleeSavedInfo()81109467b48Spatrick std::vector<CalleeSavedInfo> &getCalleeSavedInfo() { return CSInfo; } 81209467b48Spatrick 81309467b48Spatrick /// Used by prolog/epilog inserter to set the function's callee saved 81409467b48Spatrick /// information. setCalleeSavedInfo(std::vector<CalleeSavedInfo> CSI)815097a140dSpatrick void setCalleeSavedInfo(std::vector<CalleeSavedInfo> CSI) { 816097a140dSpatrick CSInfo = std::move(CSI); 81709467b48Spatrick } 81809467b48Spatrick 81909467b48Spatrick /// Has the callee saved info been calculated yet? isCalleeSavedInfoValid()82009467b48Spatrick bool isCalleeSavedInfoValid() const { return CSIValid; } 82109467b48Spatrick setCalleeSavedInfoValid(bool v)82209467b48Spatrick void setCalleeSavedInfoValid(bool v) { CSIValid = v; } 82309467b48Spatrick getSavePoint()82409467b48Spatrick MachineBasicBlock *getSavePoint() const { return Save; } setSavePoint(MachineBasicBlock * NewSave)82509467b48Spatrick void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; } getRestorePoint()82609467b48Spatrick MachineBasicBlock *getRestorePoint() const { return Restore; } setRestorePoint(MachineBasicBlock * NewRestore)82709467b48Spatrick void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; } 82809467b48Spatrick getUnsafeStackSize()829*a96b3639Srobert uint64_t getUnsafeStackSize() const { return UnsafeStackSize; } setUnsafeStackSize(uint64_t Size)830*a96b3639Srobert void setUnsafeStackSize(uint64_t Size) { UnsafeStackSize = Size; } 831*a96b3639Srobert 83209467b48Spatrick /// Return a set of physical registers that are pristine. 83309467b48Spatrick /// 83409467b48Spatrick /// Pristine registers hold a value that is useless to the current function, 83509467b48Spatrick /// but that must be preserved - they are callee saved registers that are not 83609467b48Spatrick /// saved. 83709467b48Spatrick /// 83809467b48Spatrick /// Before the PrologueEpilogueInserter has placed the CSR spill code, this 83909467b48Spatrick /// method always returns an empty set. 84009467b48Spatrick BitVector getPristineRegs(const MachineFunction &MF) const; 84109467b48Spatrick 84209467b48Spatrick /// Used by the MachineFunction printer to print information about 84309467b48Spatrick /// stack objects. Implemented in MachineFunction.cpp. 84409467b48Spatrick void print(const MachineFunction &MF, raw_ostream &OS) const; 84509467b48Spatrick 84609467b48Spatrick /// dump - Print the function to stderr. 84709467b48Spatrick void dump(const MachineFunction &MF) const; 84809467b48Spatrick }; 84909467b48Spatrick 85009467b48Spatrick } // End llvm namespace 85109467b48Spatrick 85209467b48Spatrick #endif 853