[Subzero][MIPS32] Fix stack offset assignment of spilled variables on MIPS32

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/2166643003 .

Patch from Sagar Thakur <sagar.thakur@imgtec.com>.
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 365e65d..c635b9c 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -105,6 +105,36 @@
 
 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {}
 
+void TargetMIPS32::assignVarStackSlots(VarList &SortedSpilledVariables,
+                                       size_t SpillAreaPaddingBytes,
+                                       size_t SpillAreaSizeBytes,
+                                       size_t GlobalsAndSubsequentPaddingSize) {
+  const VariablesMetadata *VMetadata = Func->getVMetadata();
+  size_t GlobalsSpaceUsed = SpillAreaPaddingBytes;
+  size_t NextStackOffset = SpillAreaPaddingBytes;
+  CfgVector<size_t> LocalsSize(Func->getNumNodes());
+  const bool SimpleCoalescing = !callsReturnsTwice();
+
+  for (Variable *Var : SortedSpilledVariables) {
+    size_t Increment = typeWidthInBytesOnStack(Var->getType());
+    if (SimpleCoalescing && VMetadata->isTracked(Var)) {
+      if (VMetadata->isMultiBlock(Var)) {
+        GlobalsSpaceUsed += Increment;
+        NextStackOffset = GlobalsSpaceUsed;
+      } else {
+        SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex();
+        LocalsSize[NodeIndex] += Increment;
+        NextStackOffset = SpillAreaPaddingBytes +
+                          GlobalsAndSubsequentPaddingSize +
+                          LocalsSize[NodeIndex];
+      }
+    } else {
+      NextStackOffset += Increment;
+    }
+    Var->setStackOffset(SpillAreaSizeBytes - NextStackOffset);
+  }
+}
+
 void TargetMIPS32::staticInit(GlobalContext *Ctx) {
   (void)Ctx;
   RegNumT::setLimit(RegMIPS32::Reg_NUM);
@@ -853,9 +883,20 @@
       GlobalsSize + LocalsSlotsPaddingBytes;
 
   // Adds the out args space to the stack, and align SP if necessary.
-  TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes +
-                        FixedAllocaSizeBytes +
-                        (MaxOutArgsSizeBytes * (VariableAllocaUsed ? 0 : 1));
+  if (!NeedsStackAlignment) {
+    SpillAreaSizeBytes += MaxOutArgsSizeBytes * (VariableAllocaUsed ? 0 : 1);
+  } else {
+    uint32_t StackOffset = PreservedRegsSizeBytes;
+    uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes);
+    if (!VariableAllocaUsed)
+      StackSize = applyStackAlignment(StackSize + MaxOutArgsSizeBytes);
+    SpillAreaSizeBytes = StackSize - StackOffset;
+  }
+
+  // Combine fixed alloca with SpillAreaSize.
+  SpillAreaSizeBytes += FixedAllocaSizeBytes;
+
+  TotalStackSizeBytes = PreservedRegsSizeBytes + SpillAreaSizeBytes;
 
   // Generate "addiu sp, sp, -TotalStackSizeBytes"
   if (TotalStackSizeBytes) {
@@ -911,8 +952,7 @@
 
   // Fill in stack offsets for locals.
   assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes,
-                      SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize,
-                      UsesFramePointer);
+                      SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize);
   this->HasComputedFrame = true;
 
   if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) {
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 5d49b01..70fed4e 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -420,6 +420,16 @@
 
   void lowerArguments() override;
 
+  /// Make a pass through the SortedSpilledVariables and actually assign stack
+  /// slots. SpillAreaPaddingBytes takes into account stack alignment padding.
+  /// The SpillArea starts after that amount of padding. This matches the scheme
+  /// in getVarStackSlotParams, where there may be a separate multi-block global
+  /// var spill area and a local var spill area.
+  void assignVarStackSlots(VarList &SortedSpilledVariables,
+                           size_t SpillAreaPaddingBytes,
+                           size_t SpillAreaSizeBytes,
+                           size_t GlobalsAndSubsequentPaddingSize);
+
   /// Operand legalization helpers.  To deal with address mode constraints,
   /// the helpers will create a new Operand and emit instructions that
   /// guarantee that the Operand kind is one of those indicated by the