return getReg(ValNo, ValVT, RegNo, LocVT, HTP, /*IsCustom=*/true);
}
- static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset,
+ static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset,
MVT LocVT, LocInfo HTP, bool IsCustom = false) {
CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom);
- Ret.Data = int64_t(Offset);
+ Ret.Data = Offset;
return Ret;
}
- static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, unsigned Offset,
+ static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, int64_t Offset,
MVT LocVT, LocInfo HTP) {
return getMem(ValNo, ValVT, Offset, LocVT, HTP, /*IsCustom=*/true);
}
void convertToReg(unsigned RegNo) { Data = Register(RegNo); }
- void convertToMem(unsigned Offset) { Data = int64_t(Offset); }
+ void convertToMem(int64_t Offset) { Data = Offset; }
unsigned getValNo() const { return ValNo; }
MVT getValVT() const { return ValVT; }
bool needsCustom() const { return isCustom; }
Register getLocReg() const { return std::get<Register>(Data); }
- unsigned getLocMemOffset() const { return std::get<int64_t>(Data); }
+ int64_t getLocMemOffset() const { return std::get<int64_t>(Data); }
unsigned getExtraInfo() const { return std::get<unsigned>(Data); }
MVT getLocVT() const { return LocVT; }
const TargetRegisterInfo &TRI;
SmallVectorImpl<CCValAssign> &Locs;
LLVMContext &Context;
+ // True if arguments should be allocated at negative offsets.
+ bool NegativeOffsets;
- unsigned StackSize;
+ uint64_t StackSize;
Align MaxStackArgAlign;
SmallVector<uint32_t, 16> UsedRegs;
SmallVector<CCValAssign, 4> PendingLocs;
unsigned InRegsParamsProcessed;
public:
- CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
- SmallVectorImpl<CCValAssign> &locs, LLVMContext &C);
+ CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
+ SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
+ bool NegativeOffsets = false);
void addLoc(const CCValAssign &V) {
Locs.push_back(V);
bool isVarArg() const { return IsVarArg; }
/// Returns the size of the currently allocated portion of the stack.
- unsigned getStackSize() const { return StackSize; }
+ uint64_t getStackSize() const { return StackSize; }
/// getAlignedCallFrameSize - Return the size of the call frame needed to
/// be able to store all arguments and such that the alignment requirement
/// of each of the arguments is satisfied.
- unsigned getAlignedCallFrameSize() const {
+ uint64_t getAlignedCallFrameSize() const {
return alignTo(StackSize, MaxStackArgAlign);
}
/// AllocateStack - Allocate a chunk of stack space with the specified size
/// and alignment.
- unsigned AllocateStack(unsigned Size, Align Alignment) {
- StackSize = alignTo(StackSize, Alignment);
- unsigned Result = StackSize;
- StackSize += Size;
+ int64_t AllocateStack(unsigned Size, Align Alignment) {
+ int64_t Offset;
+ if (NegativeOffsets) {
+ StackSize = alignTo(StackSize + Size, Alignment);
+ Offset = -StackSize;
+ } else {
+ Offset = alignTo(StackSize, Alignment);
+ StackSize = Offset + Size;
+ }
MaxStackArgAlign = std::max(Alignment, MaxStackArgAlign);
ensureMaxAlignment(Alignment);
- return Result;
+ return Offset;
}
void ensureMaxAlignment(Align Alignment);
/// Version of AllocateStack with list of extra registers to be shadowed.
/// Note that, unlike AllocateReg, this shadows ALL of the shadow registers.
- unsigned AllocateStack(unsigned Size, Align Alignment,
- ArrayRef<MCPhysReg> ShadowRegs) {
+ int64_t AllocateStack(unsigned Size, Align Alignment,
+ ArrayRef<MCPhysReg> ShadowRegs) {
for (MCPhysReg Reg : ShadowRegs)
MarkAllocated(Reg);
return AllocateStack(Size, Alignment);
using namespace llvm;
-CCState::CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &mf,
- SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)
- : CallingConv(CC), IsVarArg(isVarArg), MF(mf),
- TRI(*MF.getSubtarget().getRegisterInfo()), Locs(locs), Context(C) {
+CCState::CCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
+ SmallVectorImpl<CCValAssign> &Locs, LLVMContext &Context,
+ bool NegativeOffsets)
+ : CallingConv(CC), IsVarArg(IsVarArg), MF(MF),
+ TRI(*MF.getSubtarget().getRegisterInfo()), Locs(Locs), Context(Context),
+ NegativeOffsets(NegativeOffsets) {
+
// No stack is used.
StackSize = 0;
ensureMaxAlignment(Alignment);
MF.getSubtarget().getTargetLowering()->HandleByVal(this, Size, Alignment);
Size = unsigned(alignTo(Size, MinAlign));
- unsigned Offset = AllocateStack(Size, Alignment);
+ uint64_t Offset = AllocateStack(Size, Alignment);
addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
}
void CCState::getRemainingRegParmsForType(SmallVectorImpl<MCPhysReg> &Regs,
MVT VT, CCAssignFn Fn) {
- unsigned SavedStackSize = StackSize;
+ uint64_t SavedStackSize = StackSize;
Align SavedMaxStackArgAlign = MaxStackArgAlign;
unsigned NumLocs = Locs.size();
// On AIX a minimum of 8 words is saved to the parameter save area.
const unsigned MinParameterSaveArea = 8 * PtrByteSize;
// Area that is at least reserved in the caller of this function.
- unsigned CallerReservedArea =
- std::max(CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
+ unsigned CallerReservedArea = std::max<unsigned>(
+ CCInfo.getStackSize(), LinkageSize + MinParameterSaveArea);
// Set the size that is at least reserved in caller of this function. Tail
// call optimized function's reserved stack space needs to be aligned so
// conservatively assume that it is needed. As such, make sure we have at
// least enough stack space for the caller to store the 8 GPRs.
const unsigned MinParameterSaveAreaSize = 8 * PtrByteSize;
- const unsigned NumBytes =
- std::max(LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
+ const unsigned NumBytes = std::max<unsigned>(
+ LinkageSize + MinParameterSaveAreaSize, CCInfo.getStackSize());
// Adjust the stack pointer for the new arguments...
// These operations are automatically eliminated by the prolog/epilog pass.
// Called functions expect 6 argument words to exist in the stack frame, used
// or not.
unsigned StackReserved = 6 * 8u;
- unsigned ArgsSize = std::max(StackReserved, CCInfo.getStackSize());
+ unsigned ArgsSize = std::max<unsigned>(StackReserved, CCInfo.getStackSize());
// Keep stack frames 16-byte aligned.
ArgsSize = alignTo(ArgsSize, 16);
--- /dev/null
+//===- CCStateTest.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+#include "MFCommon.inc"
+
+TEST(CCStateTest, NegativeOffsets) {
+ LLVMContext Ctx;
+ Module Mod("Module", Ctx);
+ auto MF = createMachineFunction(Ctx, Mod);
+
+ SmallVector<CCValAssign, 8> Locs;
+ CCState Info(CallingConv::C, /*IsVarArg=*/false, *MF, Locs, Ctx,
+ /*NegativeOffsets=*/true);
+
+ ASSERT_EQ(Info.AllocateStack(1, Align(1)), -1);
+ ASSERT_EQ(Info.AllocateStack(1, Align(2)), -2);
+ ASSERT_EQ(Info.AllocateStack(1, Align(2)), -4);
+ ASSERT_EQ(Info.AllocateStack(1, Align(1)), -5);
+ ASSERT_EQ(Info.AllocateStack(2, Align(2)), -8);
+ ASSERT_EQ(Info.AllocateStack(2, Align(2)), -10);
+ ASSERT_EQ(Info.AllocateStack(2, Align(1)), -12);
+ ASSERT_EQ(Info.AllocateStack(1, Align(1)), -13);
+ ASSERT_EQ(Info.getStackSize(), 13u);
+ ASSERT_EQ(Info.getAlignedCallFrameSize(), 14u);
+}
+
+} // namespace
AllocationOrderTest.cpp
AMDGPUMetadataTest.cpp
AsmPrinterDwarfTest.cpp
+ CCStateTest.cpp
DIEHashTest.cpp
DIETest.cpp
DwarfStringPoolEntryRefTest.cpp
int Size = Action->getValueAsInt("Size");
int Align = Action->getValueAsInt("Align");
- O << IndentStr << "unsigned Offset" << ++Counter
+ O << IndentStr << "int64_t Offset" << ++Counter
<< " = State.AllocateStack(";
if (Size)
O << Size << ", ";
O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
O << "\n" << IndentStr << "};\n";
- O << IndentStr << "unsigned Offset" << ++Counter
+ O << IndentStr << "int64_t Offset" << ++Counter
<< " = State.AllocateStack(" << Size << ", Align(" << Align << "), "
<< "ShadowRegList" << ShadowRegListNumber << ");\n";
O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"