Commit 9b4c3c3a by Mohit Bhakkad Committed by Jim Stichnoth

LowerCall for MIPS32

Lower call instructions for MIPS32. R=stichnot@chromium.org Review URL: https://codereview.chromium.org/2063653003 . Patch from Mohit Bhakkad <mohit.bhakkad@imgtec.com>.
parent 2e4b960b
......@@ -95,6 +95,12 @@ uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
return Utils::applyAlignment(Value, typeAlignInBytes);
}
// Value is in bytes. Return Value adjusted to the next highest multiple of the
// stack alignment.
uint32_t applyStackAlignment(uint32_t Value) {
return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES);
}
} // end of anonymous namespace
TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {}
......@@ -1417,11 +1423,75 @@ void TargetMIPS32::lowerBr(const InstBr *Instr) {
}
void TargetMIPS32::lowerCall(const InstCall *Instr) {
// TODO(rkotler): assign arguments to registers and stack. Also reserve stack.
if (Instr->getNumArgs()) {
UnimplementedLoweringError(this, Instr);
return;
NeedsStackAlignment = true;
// Assign arguments to registers and stack. Also reserve stack.
TargetMIPS32::CallingConv CC;
// Pair of Arg Operand -> GPR number assignments.
llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs;
llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_FP_ARG> FPArgs;
// Pair of Arg Operand -> stack offset.
llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
size_t ParameterAreaSizeBytes = 16;
// Classify each argument operand according to the location where the
// argument is passed.
for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
Operand *Arg = legalizeUndef(Instr->getArg(i));
const Type Ty = Arg->getType();
bool InReg = false;
RegNumT Reg;
InReg = CC.argInReg(Ty, i, &Reg);
if (!InReg) {
ParameterAreaSizeBytes =
applyStackAlignmentTy(ParameterAreaSizeBytes, Ty);
StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes));
ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty);
continue;
}
if (Ty == IceType_i64) {
Operand *Lo = loOperand(Arg);
Operand *Hi = hiOperand(Arg);
GPRArgs.push_back(
std::make_pair(Lo, RegMIPS32::getI64PairFirstGPRNum(Reg)));
GPRArgs.push_back(
std::make_pair(Hi, RegMIPS32::getI64PairSecondGPRNum(Reg)));
} else if (isScalarIntegerType(Ty)) {
GPRArgs.push_back(std::make_pair(Arg, Reg));
} else {
FPArgs.push_back(std::make_pair(Arg, Reg));
}
}
// Adjust the parameter area so that the stack is aligned. It is assumed that
// the stack is already aligned at the start of the calling sequence.
ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
// Copy arguments that are passed on the stack to the appropriate stack
// locations.
Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
for (auto &StackArg : StackArgs) {
ConstantInteger32 *Loc =
llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second));
Type Ty = StackArg.first->getType();
OperandMIPS32Mem *Addr;
constexpr bool SignExt = false;
if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) {
Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc);
} else {
Variable *NewBase = Func->makeVariable(SP->getType());
lowerArithmetic(
InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc));
Addr = formMemoryOperand(NewBase, Ty);
}
lowerStore(InstStore::create(Func, StackArg.first, Addr));
}
// Generate the call instruction. Assign its result to a temporary with high
// register allocation weight.
Variable *Dest = Instr->getDest();
......@@ -1467,6 +1537,24 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
CallTarget = legalize(CallTarget, Legal_Reg);
}
// Copy arguments to be passed in registers to the appropriate registers.
CfgVector<Variable *> RegArgs;
for (auto &FPArg : FPArgs) {
RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second));
}
for (auto &GPRArg : GPRArgs) {
RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second));
}
// Generate a FakeUse of register arguments so that they do not get dead code
// eliminated as a result of the FakeKill of scratch registers after the call.
// These fake-uses need to be placed here to avoid argument registers from
// being used during the legalizeToReg() calls above.
for (auto *RegArg : RegArgs) {
Context.insert<InstFakeUse>(RegArg);
}
Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget);
Context.insert(NewCall);
if (ReturnRegHi)
......@@ -1475,7 +1563,7 @@ void TargetMIPS32::lowerCall(const InstCall *Instr) {
Context.insert(InstFakeKill::create(Func, NewCall));
// Generate a FakeUse to keep the call live if necessary.
if (Instr->hasSideEffects() && ReturnReg) {
Context.insert<InstFakeDef>(ReturnReg);
Context.insert<InstFakeUse>(ReturnReg);
}
if (Dest == nullptr)
return;
......
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target mips32 -i %s --args -O2 --skip-unimplemented \
; RUN: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
declare void @voidCall5i32(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5)
declare void @voidCall5i64(i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5)
declare void @voidCalli32i64i32(i32 %a1, i64 %a2, i32 %a3)
;TODO(mohit.bhakkad): Add tests for f32/f64 once legalize() or lowerArgument is
;available for f32/f64
define internal void @Call() {
call void @voidCall5i32(i32 1, i32 2, i32 3, i32 4, i32 5)
call void @voidCall5i64(i64 1, i64 2, i64 3, i64 4, i64 5)
call void @voidCalli32i64i32(i32 1, i64 2, i32 3)
ret void
}
; MIPS32: li {{.*}},5
; MIPS32: sw {{.*}},16(sp)
; MIPS32: li a0,1
; MIPS32: li a1,2
; MIPS32: li a2,3
; MIPS32: li a3,4
; MIPS32: jal
; MIPS32: li {{.*}},0
; MIPS32: li {{.*}},3
; MIPS32: sw {{.*}},20(sp)
; MIPS32: sw {{.*}},16(sp)
; MIPS32: li {{.*}},0
; MIPS32: li {{.*}},4
; MIPS32: sw {{.*}},28(sp)
; MIPS32: sw {{.*}},24(sp)
; MIPS32: li {{.*}},0
; MIPS32: li {{.*}},5
; MIPS32: sw {{.*}},36(sp)
; MIPS32: sw {{.*}},32(sp)
; MIPS32: li a0,1
; MIPS32: li a1,0
; MIPS32: li a2,2
; MIPS32: li a3,0
; MIPS32: jal
; MIPS32: li {{.*}},3
; MIPS32: sw {{.*}},16(sp)
; MIPS32: li a0,1
; MIPS32: li a2,2
; MIPS32: li a3,0
; MIPS32: jal
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment