252 lines
10 KiB
C++
252 lines
10 KiB
C++
//===-- M68kCallLowering.cpp - Call lowering --------------------*- C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
/// \file
|
|
/// This file implements the lowering of LLVM calls to machine code calls for
|
|
/// GlobalISel.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "M68kCallLowering.h"
|
|
#include "M68kISelLowering.h"
|
|
#include "M68kInstrInfo.h"
|
|
#include "M68kSubtarget.h"
|
|
#include "M68kTargetMachine.h"
|
|
#include "llvm/CodeGen/CallingConvLower.h"
|
|
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
|
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/TargetCallingConv.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
struct M68kFormalArgHandler : public M68kIncomingValueHandler {
|
|
M68kFormalArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)
|
|
: M68kIncomingValueHandler(MIRBuilder, MRI) {}
|
|
};
|
|
|
|
struct CallReturnHandler : public M68kIncomingValueHandler {
|
|
CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
|
MachineInstrBuilder &MIB)
|
|
: M68kIncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {}
|
|
|
|
private:
|
|
void assignValueToReg(Register ValVReg, Register PhysReg,
|
|
const CCValAssign &VA) override;
|
|
|
|
MachineInstrBuilder &MIB;
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
M68kCallLowering::M68kCallLowering(const M68kTargetLowering &TLI)
|
|
: CallLowering(&TLI) {}
|
|
|
|
struct M68kOutgoingArgHandler : public CallLowering::OutgoingValueHandler {
|
|
M68kOutgoingArgHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI,
|
|
MachineInstrBuilder MIB)
|
|
: OutgoingValueHandler(MIRBuilder, MRI), MIB(MIB),
|
|
DL(MIRBuilder.getMF().getDataLayout()),
|
|
STI(MIRBuilder.getMF().getSubtarget<M68kSubtarget>()) {}
|
|
|
|
void assignValueToReg(Register ValVReg, Register PhysReg,
|
|
const CCValAssign &VA) override {
|
|
MIB.addUse(PhysReg, RegState::Implicit);
|
|
Register ExtReg = extendRegister(ValVReg, VA);
|
|
MIRBuilder.buildCopy(PhysReg, ExtReg);
|
|
}
|
|
|
|
void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
|
|
const MachinePointerInfo &MPO,
|
|
const CCValAssign &VA) override {
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
Register ExtReg = extendRegister(ValVReg, VA);
|
|
|
|
auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOStore, MemTy,
|
|
inferAlignFromPtrInfo(MF, MPO));
|
|
MIRBuilder.buildStore(ExtReg, Addr, *MMO);
|
|
}
|
|
|
|
Register getStackAddress(uint64_t Size, int64_t Offset,
|
|
MachinePointerInfo &MPO,
|
|
ISD::ArgFlagsTy Flags) override {
|
|
LLT p0 = LLT::pointer(0, DL.getPointerSizeInBits(0));
|
|
LLT SType = LLT::scalar(DL.getPointerSizeInBits(0));
|
|
Register StackReg = STI.getRegisterInfo()->getStackRegister();
|
|
auto SPReg = MIRBuilder.buildCopy(p0, StackReg).getReg(0);
|
|
auto OffsetReg = MIRBuilder.buildConstant(SType, Offset);
|
|
auto AddrReg = MIRBuilder.buildPtrAdd(p0, SPReg, OffsetReg);
|
|
MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset);
|
|
return AddrReg.getReg(0);
|
|
}
|
|
MachineInstrBuilder MIB;
|
|
const DataLayout &DL;
|
|
const M68kSubtarget &STI;
|
|
};
|
|
bool M68kCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
|
|
const Value *Val, ArrayRef<Register> VRegs,
|
|
FunctionLoweringInfo &FLI,
|
|
Register SwiftErrorVReg) const {
|
|
|
|
auto MIB = MIRBuilder.buildInstrNoInsert(M68k::RTS);
|
|
bool Success = true;
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
const Function &F = MF.getFunction();
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
|
|
CCAssignFn *AssignFn =
|
|
TLI.getCCAssignFn(F.getCallingConv(), true, F.isVarArg());
|
|
auto &DL = F.getParent()->getDataLayout();
|
|
if (!VRegs.empty()) {
|
|
SmallVector<ArgInfo, 8> SplitArgs;
|
|
ArgInfo OrigArg{VRegs, Val->getType(), 0};
|
|
setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F);
|
|
splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
|
|
OutgoingValueAssigner ArgAssigner(AssignFn);
|
|
M68kOutgoingArgHandler ArgHandler(MIRBuilder, MRI, MIB);
|
|
Success = determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
|
|
MIRBuilder, F.getCallingConv(),
|
|
F.isVarArg());
|
|
}
|
|
MIRBuilder.insertInstr(MIB);
|
|
return Success;
|
|
}
|
|
|
|
bool M68kCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
|
|
const Function &F,
|
|
ArrayRef<ArrayRef<Register>> VRegs,
|
|
FunctionLoweringInfo &FLI) const {
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
const auto &DL = F.getParent()->getDataLayout();
|
|
auto &TLI = *getTLI<M68kTargetLowering>();
|
|
|
|
SmallVector<ArgInfo, 8> SplitArgs;
|
|
unsigned I = 0;
|
|
for (const auto &Arg : F.args()) {
|
|
ArgInfo OrigArg{VRegs[I], Arg.getType(), I};
|
|
setArgFlags(OrigArg, I + AttributeList::FirstArgIndex, DL, F);
|
|
splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
|
|
++I;
|
|
}
|
|
|
|
CCAssignFn *AssignFn =
|
|
TLI.getCCAssignFn(F.getCallingConv(), false, F.isVarArg());
|
|
IncomingValueAssigner ArgAssigner(AssignFn);
|
|
M68kFormalArgHandler ArgHandler(MIRBuilder, MRI);
|
|
return determineAndHandleAssignments(ArgHandler, ArgAssigner, SplitArgs,
|
|
MIRBuilder, F.getCallingConv(),
|
|
F.isVarArg());
|
|
}
|
|
|
|
void M68kIncomingValueHandler::assignValueToReg(Register ValVReg,
|
|
Register PhysReg,
|
|
const CCValAssign &VA) {
|
|
MIRBuilder.getMRI()->addLiveIn(PhysReg);
|
|
MIRBuilder.getMBB().addLiveIn(PhysReg);
|
|
IncomingValueHandler::assignValueToReg(ValVReg, PhysReg, VA);
|
|
}
|
|
|
|
void M68kIncomingValueHandler::assignValueToAddress(
|
|
Register ValVReg, Register Addr, LLT MemTy, const MachinePointerInfo &MPO,
|
|
const CCValAssign &VA) {
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
auto *MMO = MF.getMachineMemOperand(MPO, MachineMemOperand::MOLoad, MemTy,
|
|
inferAlignFromPtrInfo(MF, MPO));
|
|
MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
|
|
}
|
|
|
|
Register M68kIncomingValueHandler::getStackAddress(uint64_t Size,
|
|
int64_t Offset,
|
|
MachinePointerInfo &MPO,
|
|
ISD::ArgFlagsTy Flags) {
|
|
auto &MFI = MIRBuilder.getMF().getFrameInfo();
|
|
const bool IsImmutable = !Flags.isByVal();
|
|
int FI = MFI.CreateFixedObject(Size, Offset, IsImmutable);
|
|
MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI);
|
|
|
|
// Build Frame Index
|
|
llvm::LLT FramePtr = LLT::pointer(
|
|
0, MIRBuilder.getMF().getDataLayout().getPointerSizeInBits());
|
|
MachineInstrBuilder AddrReg = MIRBuilder.buildFrameIndex(FramePtr, FI);
|
|
StackUsed = std::max(StackUsed, Size + Offset);
|
|
return AddrReg.getReg(0);
|
|
}
|
|
|
|
void CallReturnHandler::assignValueToReg(Register ValVReg, Register PhysReg,
|
|
const CCValAssign &VA) {
|
|
MIB.addDef(PhysReg, RegState::Implicit);
|
|
MIRBuilder.buildCopy(ValVReg, PhysReg);
|
|
}
|
|
|
|
bool M68kCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
|
|
CallLoweringInfo &Info) const {
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
Function &F = MF.getFunction();
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
auto &DL = F.getParent()->getDataLayout();
|
|
const M68kTargetLowering &TLI = *getTLI<M68kTargetLowering>();
|
|
const M68kSubtarget &STI = MF.getSubtarget<M68kSubtarget>();
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
|
const M68kRegisterInfo *TRI = STI.getRegisterInfo();
|
|
|
|
SmallVector<ArgInfo, 8> OutArgs;
|
|
for (auto &OrigArg : Info.OrigArgs)
|
|
splitToValueTypes(OrigArg, OutArgs, DL, Info.CallConv);
|
|
|
|
SmallVector<ArgInfo, 8> InArgs;
|
|
if (!Info.OrigRet.Ty->isVoidTy())
|
|
splitToValueTypes(Info.OrigRet, InArgs, DL, Info.CallConv);
|
|
|
|
unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
|
|
auto CallSeqStart = MIRBuilder.buildInstr(AdjStackDown);
|
|
|
|
unsigned Opc = TLI.getTargetMachine().isPositionIndependent() ? M68k::CALLq
|
|
: Info.Callee.isReg() ? M68k::CALLj
|
|
: M68k::CALLb;
|
|
|
|
auto MIB = MIRBuilder.buildInstrNoInsert(Opc)
|
|
.add(Info.Callee)
|
|
.addRegMask(TRI->getCallPreservedMask(MF, Info.CallConv));
|
|
|
|
CCAssignFn *AssignFn = TLI.getCCAssignFn(Info.CallConv, false, Info.IsVarArg);
|
|
OutgoingValueAssigner Assigner(AssignFn);
|
|
M68kOutgoingArgHandler Handler(MIRBuilder, MRI, MIB);
|
|
if (!determineAndHandleAssignments(Handler, Assigner, OutArgs, MIRBuilder,
|
|
Info.CallConv, Info.IsVarArg))
|
|
return false;
|
|
|
|
if (Info.Callee.isReg())
|
|
constrainOperandRegClass(MF, *TRI, MRI, *STI.getInstrInfo(),
|
|
*STI.getRegBankInfo(), *MIB, MIB->getDesc(),
|
|
Info.Callee, 0);
|
|
|
|
MIRBuilder.insertInstr(MIB);
|
|
|
|
if (!Info.OrigRet.Ty->isVoidTy()) {
|
|
CCAssignFn *RetAssignFn =
|
|
TLI.getCCAssignFn(Info.CallConv, true, Info.IsVarArg);
|
|
|
|
OutgoingValueAssigner Assigner(RetAssignFn, RetAssignFn);
|
|
CallReturnHandler Handler(MIRBuilder, MRI, MIB);
|
|
if (!determineAndHandleAssignments(Handler, Assigner, InArgs, MIRBuilder,
|
|
Info.CallConv, Info.IsVarArg))
|
|
return false;
|
|
}
|
|
|
|
CallSeqStart.addImm(Assigner.StackSize).addImm(0);
|
|
|
|
unsigned AdjStackUp = TII.getCallFrameDestroyOpcode();
|
|
MIRBuilder.buildInstr(AdjStackUp).addImm(Assigner.StackSize).addImm(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool M68kCallLowering::enableBigEndian() const { return true; }
|