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

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: 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
« src/IceRegistersMIPS32.h ('K') | « 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..a9bfabbdd78fc6416354bcaea672dbf25d6f770e 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,93 @@ 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()) {}
+
+bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
+ CfgVector<RegNumT> *Source;
+
+ switch (Ty) {
+ default: {
+ assert(isScalarIntegerType(Ty));
+ Source = &GPRArgs;
+ } break;
+ case IceType_i64: {
+ 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;
+}
+
+// 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()]) {
+ GPRegsUsed |= RegisterAliases[Regs->back()];
+ Regs->pop_back();
+ }
+}
+
+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;
+ }
+
+ discardUnavailableVFPRegs(Source);
+
+ if (Source->empty()) {
+ VFPRegsUsed.set();
+ return false;
+ }
+
+ *Reg = Source->back();
+ VFPRegsUsed |= RegisterAliases[*Reg];
+ return true;
+}
+
+// Arguments in VFP registers are not packed, so we don't mark the popped
+// registers' aliases as unavailable.
+void TargetMIPS32::CallingConv::discardUnavailableVFPRegs(
+ 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
« src/IceRegistersMIPS32.h ('K') | « src/IceTargetLoweringMIPS32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698