Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Unified Diff: src/IceTargetLoweringMIPS32.cpp

Issue 2052793003: Calling convention for MIPS32 (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero@master
Patch Set: Addressed review comments Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceTargetLoweringMIPS32.cpp
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 70ddef531f88350f82bf5fc12e8d6b01cdca4ba9..79db2a1fa788d7ea7d0bd61f8221ad56e61dd942 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -64,6 +64,14 @@ namespace {
// The maximum number of arguments to pass in GPR registers.
constexpr uint32_t MIPS32_MAX_GPR_ARG = 4;
+std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer;
+std::array<RegNumT, MIPS32_MAX_GPR_ARG / 2> I64ArgInitializer;
+
+constexpr uint32_t MIPS32_MAX_FP_ARG = 2;
+
+std::array<RegNumT, MIPS32_MAX_FP_ARG> FP32ArgInitializer;
+std::array<RegNumT, MIPS32_MAX_FP_ARG> FP64ArgInitializer;
+
const char *getRegClassName(RegClass C) {
auto ClassNum = static_cast<RegClassMIPS32>(C);
assert(ClassNum < RCMIPS32_NUM);
@@ -105,6 +113,20 @@ void TargetMIPS32::staticInit(GlobalContext *Ctx) {
assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]);
REGMIPS32_TABLE;
#undef X
+
+ // TODO(mohit.bhakkad): Change these inits once we provide argument related
+ // field in register tables
+ for (size_t i = 0; i < MIPS32_MAX_GPR_ARG; i++)
+ GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i);
+
+ for (size_t i = 0; i < MIPS32_MAX_GPR_ARG / 2; i++)
+ I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i);
+
+ for (size_t i = 0; i < MIPS32_MAX_FP_ARG; i++) {
+ FP32ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12 + i * 2);
+ FP64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_F12F13 + i);
+ }
+
TypeToRegisterSet[IceType_void] = InvalidRegisters;
TypeToRegisterSet[IceType_i1] = IntegerRegisters;
TypeToRegisterSet[IceType_i8] = IntegerRegisters;
@@ -406,6 +428,135 @@ void TargetMIPS32::emitVariable(const Variable *Var) const {
UnimplementedError(getFlags());
}
+TargetMIPS32::CallingConv::CallingConv()
+ : GPRegsUsed(RegMIPS32::Reg_NUM),
+ GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()),
+ I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()),
+ VFPRegsUsed(RegMIPS32::Reg_NUM),
+ FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()),
+ FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {}
+
+// In MIPS O32 abi FP argument registers can be used only if first argument is
+// of type float/double. UseFPRegs flag is used to care of that. Also FP arg
+// registers can be used only for first 2 arguments, so we require argument
+// number to make register allocation decisions.
+bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo,
+ RegNumT *Reg) {
+ if (isScalarIntegerType(Ty))
+ return argInGPR(Ty, Reg);
+ if (isScalarFloatingType(Ty)) {
+ if (ArgNo == 0) {
+ UseFPRegs = true;
+ return argInVFP(Ty, Reg);
+ }
+ if (UseFPRegs && ArgNo == 1) {
+ UseFPRegs = false;
+ return argInVFP(Ty, Reg);
+ }
+ return argInGPR(Ty, Reg);
+ }
+ UnimplementedError(getFlags());
+ return false;
+}
+
+bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
+ CfgVector<RegNumT> *Source;
+
+ switch (Ty) {
+ default: {
+ UnimplementedError(getFlags());
+ return false;
+ } break;
+ case IceType_i32:
+ case IceType_f32: {
+ Source = &GPRArgs;
+ } break;
+ case IceType_i64:
+ case IceType_f64: {
+ Source = &I64Args;
+ } break;
+ }
+
+ discardUnavailableGPRsAndTheirAliases(Source);
+
+ if (Source->empty()) {
+ GPRegsUsed.set();
+ return false;
+ }
+
+ *Reg = Source->back();
+ // Note that we don't Source->pop_back() here. This is intentional. Notice how
+ // we mark all of Reg's aliases as Used. So, for the next argument,
+ // Source->back() is marked as unavailable, and it is thus implicitly popped
+ // from the stack.
+ GPRegsUsed |= RegisterAliases[*Reg];
+ return true;
+}
+
+inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases(
+ CfgVector<RegNumT> *Regs) {
+ GPRegsUsed |= RegisterAliases[Regs->back()];
+ Regs->pop_back();
+}
+
+// GPR are not packed when passing parameters. Thus, a function foo(i32, i64,
+// i32) will have the first argument in a0, the second in a2-a3, and the third
+// on the stack. To model this behavior, whenever we pop a register from Regs,
+// we remove all of its aliases from the pool of available GPRs. This has the
+// effect of computing the "closure" on the GPR registers.
+void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases(
+ CfgVector<RegNumT> *Regs) {
+ while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
+ discardNextGPRAndItsAliases(Regs);
+ }
+}
+
+bool TargetMIPS32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
+ CfgVector<RegNumT> *Source;
+
+ switch (Ty) {
+ default: {
+ UnimplementedError(getFlags());
+ return false;
+ } break;
+ case IceType_f32: {
+ Source = &FP32Args;
+ } break;
+ case IceType_f64: {
+ Source = &FP64Args;
+ } break;
+ }
+
+ discardUnavailableVFPRegsAndTheirAliases(Source);
+
+ if (Source->empty()) {
+ VFPRegsUsed.set();
+ return false;
+ }
+
+ *Reg = Source->back();
+ VFPRegsUsed |= RegisterAliases[*Reg];
+
+ // In MIPS O32 abi if fun arguments are (f32, i32) then one can not use reg_a0
+ // for second argument even though it's free. f32 arg goes in reg_f12, i32 arg
+ // goes in reg_a1. Similarly if arguments are (f64, i32) second argument goes
+ // in reg_a3 and a0, a1 are not used.
+ Source = &GPRArgs;
+ // Discard one GPR reg for f32(4 bytes), two for f64(4 + 4 bytes)
+ discardNextGPRAndItsAliases(Source);
+ if (Ty == IceType_f64)
+ discardNextGPRAndItsAliases(Source);
+
+ return true;
+}
+
+void TargetMIPS32::CallingConv::discardUnavailableVFPRegsAndTheirAliases(
+ CfgVector<RegNumT> *Regs) {
+ while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
+ Regs->pop_back();
+ }
+}
+
void TargetMIPS32::lowerArguments() {
VarList &Args = Func->getArgs();
// We are only handling integer registers for now. The Mips o32 ABI is
« no previous file with comments | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698