Subzero, MIPS32: Stacksave/Stackrestore implementation

Implemets Stacksave/Stackrestore; test_stacksave runs successfully
when jal implementation is present, both in forceasm as well as in
elf mode

R=stichnot@chromium.org

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

Patch from Stefan Maksimovic <makdstefan@gmail.com>.
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 9957112..fa6bce1 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -4443,11 +4443,18 @@
     return;
   }
   case Intrinsics::Stacksave: {
-    UnimplementedLoweringError(this, Instr);
+    Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
+    _mov(Dest, SP);
     return;
   }
   case Intrinsics::Stackrestore: {
-    UnimplementedLoweringError(this, Instr);
+    if (getFlags().getUseSandboxing()) {
+      UnimplementedLoweringError(this, Instr);
+      return;
+    }
+    Variable *Val = legalizeToReg(Instr->getArg(0));
+    Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP);
+    _mov_redefined(SP, Val);
     return;
   }
   case Intrinsics::Trap: {
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index 6da7e5b..5406087 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -369,6 +369,21 @@
     }
   }
 
+  void _mov_redefined(Variable *Dest, Operand *Src0, Operand *Src1 = nullptr) {
+    if (llvm::isa<ConstantRelocatable>(Src0)) {
+      Context.insert<InstMIPS32La>(Dest, Src0);
+    } else {
+      auto *Instr = Context.insert<InstMIPS32Mov>(Dest, Src0, Src1);
+      Instr->setDestRedefined();
+      if (Instr->getDestHi() != nullptr) {
+        // If Instr is multi-dest, then Dest must be a Variable64On32. We add a
+        // fake-def for Instr.DestHi here.
+        assert(llvm::isa<Variable64On32>(Dest));
+        Context.insert<InstFakeDef>(Instr->getDestHi());
+      }
+    }
+  }
+
   void _mov_d(Variable *Dest, Variable *Src) {
     Context.insert<InstMIPS32Mov_d>(Dest, Src);
   }
diff --git a/tests_lit/llvm2ice_tests/nacl-other-intrinsics.ll b/tests_lit/llvm2ice_tests/nacl-other-intrinsics.ll
index eacce41..003fe38 100644
--- a/tests_lit/llvm2ice_tests/nacl-other-intrinsics.ll
+++ b/tests_lit/llvm2ice_tests/nacl-other-intrinsics.ll
@@ -658,6 +658,10 @@
 ; ARM32-LABEL: test_stacksave_noalloca
 ; ARM32: mov {{.*}}, sp
 ; ARM32: mov sp, {{.*}}
+; MIPS32-LABEL: test_stacksave_noalloca
+; MIPS32: 	sw	sp,{{.*}}
+; MIPS32: 	lw	[[REG:.*]],0(sp)
+; MIPS32: 	move	sp,[[REG]]
 
 declare i32 @foo(i32 %x)
 
@@ -702,3 +706,9 @@
 ; ARM32: mov {{.*}}, sp
 ; ARM32: mov {{.*}}, sp
 ; ARM32: mov sp, {{.*}}
+; MIPS32-LABEL: test_stacksave_multiple
+; MIPS32: 	sw	sp,[[MEMLOC:.*]]
+; MIPS32: 	sw	sp,{{.*}}
+; MIPS32: 	sw	sp,{{.*}}
+; MIPS32: 	lw	[[REG:.*]],[[MEMLOC]]
+; MIPS32: 	move	sp,[[REG]]