summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86CallLowering.cpp180
-rw-r--r--llvm/lib/Target/X86/X86CallLowering.h4
2 files changed, 171 insertions, 13 deletions
diff --git a/llvm/lib/Target/X86/X86CallLowering.cpp b/llvm/lib/Target/X86/X86CallLowering.cpp
index c8a3b2b51c8..cbe9e60864d 100644
--- a/llvm/lib/Target/X86/X86CallLowering.cpp
+++ b/llvm/lib/Target/X86/X86CallLowering.cpp
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Target/TargetSubtargetInfo.h"
@@ -78,14 +79,29 @@ bool X86CallLowering::splitToValueTypes(const ArgInfo &OrigArg,
}
namespace {
-struct FuncReturnHandler : public CallLowering::ValueHandler {
- FuncReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
- : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
+struct OutgoingValueHandler : public CallLowering::ValueHandler {
+ OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ MachineInstrBuilder &MIB, CCAssignFn *AssignFn)
+ : ValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB), StackSize(0),
+ DL(MIRBuilder.getMF().getDataLayout()),
+ STI(MIRBuilder.getMF().getSubtarget<X86Subtarget>()) {}
unsigned getStackAddress(uint64_t Size, int64_t Offset,
MachinePointerInfo &MPO) override {
- llvm_unreachable("Don't know how to get a stack address yet");
+
+ LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));
+ LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));
+ unsigned SPReg = MRI.createGenericVirtualRegister(p0);
+ MIRBuilder.buildCopy(SPReg, STI.getRegisterInfo()->getStackRegister());
+
+ unsigned OffsetReg = MRI.createGenericVirtualRegister(SType);
+ MIRBuilder.buildConstant(OffsetReg, Offset);
+
+ unsigned AddrReg = MRI.createGenericVirtualRegister(p0);
+ MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg);
+
+ MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
+ return AddrReg;
}
void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
@@ -97,10 +113,33 @@ struct FuncReturnHandler : public CallLowering::ValueHandler {
void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size,
MachinePointerInfo &MPO, CCValAssign &VA) override {
- llvm_unreachable("Don't know how to assign a value to an address yet");
+
+ unsigned ExtReg = extendRegister(ValVReg, VA);
+ auto MMO = MIRBuilder.getMF().getMachineMemOperand(
+ MPO, MachineMemOperand::MOStore, VA.getLocVT().getStoreSize(),
+ /* Alignment */ 0);
+ MIRBuilder.buildStore(ExtReg, Addr, *MMO);
}
+ bool assignArg(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo,
+ const CallLowering::ArgInfo &Info, CCState &State) override {
+
+ if (!Info.IsFixed)
+ return true; // TODO: handle variadic function
+
+ bool Res = AssignFn(ValNo, ValVT, LocVT, LocInfo, Info.Flags, State);
+ StackSize = State.getNextStackOffset();
+ return Res;
+ }
+
+ uint64_t getStackSize() { return StackSize; }
+
+protected:
MachineInstrBuilder &MIB;
+ uint64_t StackSize;
+ const DataLayout &DL;
+ const X86Subtarget &STI;
};
} // End anonymous namespace.
@@ -127,7 +166,7 @@ bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
}))
return false;
- FuncReturnHandler Handler(MIRBuilder, MRI, MIB, RetCC_X86);
+ OutgoingValueHandler Handler(MIRBuilder, MRI, MIB, RetCC_X86);
if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
return false;
}
@@ -137,10 +176,11 @@ bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
}
namespace {
-struct FormalArgHandler : public CallLowering::ValueHandler {
- FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
- CCAssignFn *AssignFn, const DataLayout &DL)
- : ValueHandler(MIRBuilder, MRI, AssignFn), DL(DL) {}
+struct IncomingValueHandler : public CallLowering::ValueHandler {
+ IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn *AssignFn)
+ : ValueHandler(MIRBuilder, MRI, AssignFn),
+ DL(MIRBuilder.getMF().getDataLayout()) {}
unsigned getStackAddress(uint64_t Size, int64_t Offset,
MachinePointerInfo &MPO) override {
@@ -164,14 +204,37 @@ struct FormalArgHandler : public CallLowering::ValueHandler {
MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
}
+protected:
+ const DataLayout &DL;
+};
+
+struct FormalArgHandler : public IncomingValueHandler {
+ FormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn *AssignFn)
+ : IncomingValueHandler(MIRBuilder, MRI, AssignFn) {}
+
void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
CCValAssign &VA) override {
MIRBuilder.getMBB().addLiveIn(PhysReg);
MIRBuilder.buildCopy(ValVReg, PhysReg);
}
+};
- const DataLayout &DL;
+struct CallReturnHandler : public IncomingValueHandler {
+ CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
+ CCAssignFn *AssignFn, MachineInstrBuilder &MIB)
+ : IncomingValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
+
+ void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
+ CCValAssign &VA) override {
+ MIB.addDef(PhysReg, RegState::Implicit);
+ MIRBuilder.buildCopy(ValVReg, PhysReg);
+ }
+
+protected:
+ MachineInstrBuilder &MIB;
};
+
} // namespace
bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
@@ -215,7 +278,7 @@ bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
if (!MBB.empty())
MIRBuilder.setInstr(*MBB.begin());
- FormalArgHandler Handler(MIRBuilder, MRI, CC_X86, DL);
+ FormalArgHandler Handler(MIRBuilder, MRI, CC_X86);
if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
return false;
@@ -224,3 +287,94 @@ bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
return true;
}
+
+bool X86CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
+ CallingConv::ID CallConv,
+ const MachineOperand &Callee,
+ const ArgInfo &OrigRet,
+ ArrayRef<ArgInfo> OrigArgs) const {
+
+ MachineFunction &MF = MIRBuilder.getMF();
+ const Function &F = *MF.getFunction();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ auto &DL = F.getParent()->getDataLayout();
+ const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
+ const TargetInstrInfo &TII = *STI.getInstrInfo();
+ auto TRI = STI.getRegisterInfo();
+
+ // Handle only Linux C, X86_64_SysV calling conventions for now.
+ if (!STI.isTargetLinux() ||
+ !(CallConv == CallingConv::C || CallConv == CallingConv::X86_64_SysV))
+ return false;
+
+ unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
+ auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);
+
+ // Create a temporarily-floating call instruction so we can add the implicit
+ // uses of arg registers.
+ bool Is64Bit = STI.is64Bit();
+ unsigned CallOpc = Callee.isReg()
+ ? (Is64Bit ? X86::CALL64r : X86::CALL32r)
+ : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
+
+ auto MIB = MIRBuilder.buildInstrNoInsert(CallOpc).add(Callee).addRegMask(
+ TRI->getCallPreservedMask(MF, CallConv));
+
+ SmallVector<ArgInfo, 8> SplitArgs;
+ for (const auto &OrigArg : OrigArgs) {
+ if (!splitToValueTypes(OrigArg, SplitArgs, DL, MRI,
+ [&](ArrayRef<unsigned> Regs) {
+ MIRBuilder.buildUnmerge(Regs, OrigArg.Reg);
+ }))
+ return false;
+ }
+ // Do the actual argument marshalling.
+ OutgoingValueHandler Handler(MIRBuilder, MRI, MIB, CC_X86);
+ if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
+ return false;
+
+ // Now we can add the actual call instruction to the correct basic block.
+ MIRBuilder.insertInstr(MIB);
+
+ // If Callee is a reg, since it is used by a target specific
+ // instruction, it must have a register class matching the
+ // constraint of that instruction.
+ if (Callee.isReg())
+ MIB->getOperand(0).setReg(constrainOperandRegClass(
+ MF, *TRI, MRI, *MF.getSubtarget().getInstrInfo(),
+ *MF.getSubtarget().getRegBankInfo(), *MIB, MIB->getDesc(),
+ Callee.getReg(), 0));
+
+ // Finally we can copy the returned value back into its virtual-register. In
+ // symmetry with the arguments, the physical register must be an
+ // implicit-define of the call instruction.
+
+ if (OrigRet.Reg) {
+ SplitArgs.clear();
+ SmallVector<unsigned, 8> NewRegs;
+
+ if (!splitToValueTypes(OrigRet, SplitArgs, DL, MRI,
+ [&](ArrayRef<unsigned> Regs) {
+ NewRegs.assign(Regs.begin(), Regs.end());
+ }))
+ return false;
+
+ CallReturnHandler Handler(MIRBuilder, MRI, RetCC_X86, MIB);
+ if (!handleAssignments(MIRBuilder, SplitArgs, Handler))
+ return false;
+
+ if (!NewRegs.empty())
+ MIRBuilder.buildMerge(OrigRet.Reg, NewRegs);
+ }
+
+ CallSeqStart.addImm(Handler.getStackSize())
+ .addImm(0 /* see getFrameTotalSize */)
+ .addImm(0 /* see getFrameAdjustment */);
+
+ unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
+ MIRBuilder.buildInstr(AdjStackUp)
+ .addImm(Handler.getStackSize())
+ .addImm(0 /* NumBytesForCalleeToPop */);
+
+ return true;
+}
diff --git a/llvm/lib/Target/X86/X86CallLowering.h b/llvm/lib/Target/X86/X86CallLowering.h
index 6a5dabf33a0..f8f83717586 100644
--- a/llvm/lib/Target/X86/X86CallLowering.h
+++ b/llvm/lib/Target/X86/X86CallLowering.h
@@ -35,6 +35,10 @@ public:
bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
ArrayRef<unsigned> VRegs) const override;
+ bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv,
+ const MachineOperand &Callee, const ArgInfo &OrigRet,
+ ArrayRef<ArgInfo> OrigArgs) const override;
+
private:
/// A function of this type is used to perform value split action.
typedef std::function<void(ArrayRef<unsigned>)> SplitArgTy;
OpenPOWER on IntegriCloud