implement the null function for the Mips32 subzero compiler
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4167
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/1176133004 .
Patch from Reed Kotler <reed.kotler@imgtec.com>.
diff --git a/Makefile.standalone b/Makefile.standalone
index b4c33b7..83eddac 100644
--- a/Makefile.standalone
+++ b/Makefile.standalone
@@ -189,6 +189,7 @@
IceGlobalInits.cpp \
IceInst.cpp \
IceInstARM32.cpp \
+ IceInstMIPS32.cpp \
IceInstX8632.cpp \
IceIntrinsics.cpp \
IceLiveness.cpp \
diff --git a/pydir/run-pnacl-sz.py b/pydir/run-pnacl-sz.py
index 787910c..72b6a0b 100755
--- a/pydir/run-pnacl-sz.py
+++ b/pydir/run-pnacl-sz.py
@@ -15,14 +15,18 @@
# TODO(stichnot): -triple=i686-nacl should be used for a
# sandboxing test. This means there should be an args.sandbox
# argument that also gets passed through to pnacl-sz.
+ # TODO(reed kotler). Need to find out exactly we need to
+ # add here for Mips32.
flags = { 'x8632': ['-triple=i686'],
- 'arm32': ['-triple=armv7a', '-mcpu=cortex-a9', '-mattr=+neon'] }
+ 'arm32': ['-triple=armv7a', '-mcpu=cortex-a9', '-mattr=+neon'],
+ 'mips32': ['-triple=mipsel-none-nacl' ] }
return flags[target]
def TargetDisassemblerFlags(target):
flags = { 'x8632': ['-Mintel'],
- 'arm32': [] }
+ 'arm32': [],
+ 'mips32':[] }
return flags[target]
@@ -73,7 +77,7 @@
choices=['obj', 'asm', 'iasm'],
help='Output file type. Default %(default)s.')
argparser.add_argument('--target', default='x8632', dest='target',
- choices=['x8632','arm32'],
+ choices=['x8632','arm32','mips32'],
help='Target architecture. Default %(default)s.')
argparser.add_argument('--echo-cmd', required=False,
action='store_true',
diff --git a/src/IceAssemblerMIPS32.h b/src/IceAssemblerMIPS32.h
index b088d56..06b1487 100644
--- a/src/IceAssemblerMIPS32.h
+++ b/src/IceAssemblerMIPS32.h
@@ -49,10 +49,12 @@
SizeT getBundleAlignLog2Bytes() const override { return 4; }
- const char *getNonExecPadDirective() const override { return ".TBD"; }
+ const char *getNonExecPadDirective() const override { return ".p2alignl"; }
llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
- llvm::report_fatal_error("Not yet implemented.");
+ // TODO(reed kotler) . Find out what this should be.
+ static const uint8_t Padding[] = {0xE7, 0xFE, 0xDE, 0xF0};
+ return llvm::ArrayRef<uint8_t>(Padding, 4);
}
void padWithNop(intptr_t Padding) override {
diff --git a/src/IceInstMIPS32.cpp b/src/IceInstMIPS32.cpp
new file mode 100644
index 0000000..af6aaf1
--- /dev/null
+++ b/src/IceInstMIPS32.cpp
@@ -0,0 +1,62 @@
+//===- subzero/src/IceInstMips32.cpp - Mips32 instruction implementation --===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file implements the InstMips32 and OperandMips32 classes,
+/// primarily the constructors and the dump()/emit() methods.
+///
+//===----------------------------------------------------------------------===//
+
+#include "IceAssemblerMIPS32.h"
+#include "IceCfg.h"
+#include "IceCfgNode.h"
+#include "IceInst.h"
+#include "IceInstMIPS32.h"
+#include "IceOperand.h"
+#include "IceRegistersMIPS32.h"
+#include "IceTargetLoweringMIPS32.h"
+
+namespace Ice {
+
+
+InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
+ : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
+ addSource(RA);
+ if (Source)
+ addSource(Source);
+}
+
+void InstMIPS32Ret::emit(const Cfg *Func) const {
+ if (!ALLOW_DUMP)
+ return;
+ assert(getSrcSize() > 0);
+ Variable *RA = llvm::cast<Variable>(getSrc(0));
+ assert(RA->hasReg());
+ assert(RA->getRegNum() == RegMIPS32::Reg_RA);
+ Ostream &Str = Func->getContext()->getStrEmit();
+ Str << "\t"
+ << "jr $ra"
+ << "\t";
+ RA->emit(Func);
+}
+
+void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
+ (void)Func;
+ llvm_unreachable("Not yet implemented");
+}
+
+void InstMIPS32Ret::dump(const Cfg *Func) const {
+ if (!ALLOW_DUMP)
+ return;
+ Ostream &Str = Func->getContext()->getStrDump();
+ Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
+ Str << "ret." << Ty << " ";
+ dumpSources(Func);
+}
+}
diff --git a/src/IceInstMIPS32.def b/src/IceInstMIPS32.def
index 3b6f387..351ecce 100644
--- a/src/IceInstMIPS32.def
+++ b/src/IceInstMIPS32.def
@@ -15,7 +15,7 @@
#define SUBZERO_SRC_ICEINSTMIPS32_DEF
// NOTE: PC and SP are not considered isInt, to avoid register allocating.
-// TODO (reed kotler). This needs to be scrubbed and is a placeholder to get
+// TODO(reed kotler). This needs to be scrubbed and is a placeholder to get
// the Mips skeleton in.
//
#define REGMIPS32_GPR_TABLE \
diff --git a/src/IceInstMIPS32.h b/src/IceInstMIPS32.h
index 17c2583..d608a1c 100644
--- a/src/IceInstMIPS32.h
+++ b/src/IceInstMIPS32.h
@@ -18,11 +18,64 @@
#define SUBZERO_SRC_ICEINSTMIPS32_H
#include "IceDefs.h"
+#include "IceInst.h"
+#include "IceInstMIPS32.def"
+#include "IceOperand.h"
namespace Ice {
class TargetMIPS32;
-// Fill this in.
+
+/// Base class for Mips instructions.
+class InstMIPS32 : public InstTarget {
+ InstMIPS32() = delete;
+ InstMIPS32(const InstMIPS32 &) = delete;
+ InstMIPS32 &operator=(const InstMIPS32 &) = delete;
+
+public:
+ enum InstKindMIPS32 { k__Start = Inst::Target, Ret };
+
+ static const char *getWidthString(Type Ty);
+
+ void dump(const Cfg *Func) const override;
+
+protected:
+ InstMIPS32(Cfg *Func, InstKindMIPS32 Kind, SizeT Maxsrcs, Variable *Dest)
+ : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {}
+ ~InstMIPS32() override {}
+ static bool isClassof(const Inst *Inst, InstKindMIPS32 MyKind) {
+ return Inst->getKind() == static_cast<InstKind>(MyKind);
+ }
+};
+
+/// Ret pseudo-instruction. This is actually a "jr" instruction with
+/// an "ra" register operand, but epilogue lowering will search for a Ret
+/// instead of a generic "jr". This instruction also takes a Source
+/// operand (for non-void returning functions) for liveness analysis, though
+/// a FakeUse before the ret would do just as well.
+/// TODO(reed kotler): This needs was take from the ARM port and needs to be
+/// scrubbed in the future.
+class InstMIPS32Ret : public InstMIPS32 {
+
+ InstMIPS32Ret() = delete;
+ InstMIPS32Ret(const InstMIPS32Ret &) = delete;
+ InstMIPS32Ret &operator=(const InstMIPS32Ret &) = delete;
+
+public:
+ static InstMIPS32Ret *create(Cfg *Func, Variable *RA,
+ Variable *Source = nullptr) {
+ return new (Func->allocate<InstMIPS32Ret>())
+ InstMIPS32Ret(Func, RA, Source);
+ }
+ void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
+ void dump(const Cfg *Func) const override;
+ static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); }
+
+private:
+ InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source);
+ ~InstMIPS32Ret() override {}
+};
} // end of namespace Ice
diff --git a/src/IceTargetLoweringMIPS32.cpp b/src/IceTargetLoweringMIPS32.cpp
index 6c0793f..a7e85a8 100644
--- a/src/IceTargetLoweringMIPS32.cpp
+++ b/src/IceTargetLoweringMIPS32.cpp
@@ -31,6 +31,17 @@
namespace Ice {
+namespace {
+void UnimplementedError(const ClFlags &Flags) {
+ if (!Flags.getSkipUnimplemented()) {
+ // Use llvm_unreachable instead of report_fatal_error, which gives better
+ // stack traces.
+ llvm_unreachable("Not yet implemented");
+ abort();
+ }
+}
+} // end of anonymous namespace
+
TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {
// TODO: Don't initialize IntegerRegisters and friends every time.
// Instead, initialize in some sort of static initializer for the
@@ -205,7 +216,8 @@
bool TargetMIPS32::doBranchOpt(Inst *I, const CfgNode *NextNode) {
(void)I;
(void)NextNode;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
+ return false;
}
IceString TargetMIPS32::RegNames[] = {
@@ -247,23 +259,25 @@
Ostream &Str = Ctx->getStrEmit();
(void)Var;
(void)Str;
- llvm::report_fatal_error("emitVariable: Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerArguments() {
- llvm::report_fatal_error("lowerArguments: Not yet implemented");
+ VarList &Args = Func->getArgs();
+ if (Args.size() > 0)
+ UnimplementedError(Func->getContext()->getFlags());
}
Type TargetMIPS32::stackSlotType() { return IceType_i32; }
void TargetMIPS32::addProlog(CfgNode *Node) {
(void)Node;
- llvm::report_fatal_error("addProlog: Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::addEpilog(CfgNode *Node) {
(void)Node;
- llvm::report_fatal_error("addEpilog: Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
llvm::SmallBitVector TargetMIPS32::getRegisterSet(RegSetMask Include,
@@ -305,84 +319,84 @@
// restriction can be relaxed in some cases.
NeedsStackAlignment = true;
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerArithmetic(const InstArithmetic *Inst) {
switch (Inst->getOp()) {
case InstArithmetic::_num:
- llvm_unreachable("Unknown arithmetic operator");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Add:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::And:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Or:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Xor:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Sub:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Mul:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Shl:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Lshr:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Ashr:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Udiv:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Sdiv:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Urem:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Srem:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Fadd:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Fsub:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Fmul:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Fdiv:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstArithmetic::Frem:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
}
void TargetMIPS32::lowerAssign(const InstAssign *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerBr(const InstBr *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerCall(const InstCall *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerCast(const InstCast *Inst) {
@@ -392,39 +406,39 @@
Func->setError("Cast type not supported");
return;
case InstCast::Sext: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
case InstCast::Zext: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
case InstCast::Trunc: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
case InstCast::Fptrunc:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Fpext: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
case InstCast::Fptosi:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Fptoui:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Sitofp:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
case InstCast::Uitofp: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
case InstCast::Bitcast: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
break;
}
}
@@ -432,72 +446,72 @@
void TargetMIPS32::lowerExtractElement(const InstExtractElement *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerFcmp(const InstFcmp *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerIcmp(const InstIcmp *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerInsertElement(const InstInsertElement *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) {
switch (Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID) {
case Intrinsics::AtomicCmpxchg: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::AtomicFence:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
case Intrinsics::AtomicFenceAll:
// NOTE: FenceAll should prevent and load/store from being moved
// across the fence (both atomic and non-atomic). The InstMIPS32Mfence
// instruction is currently marked coarsely as "HasSideEffects".
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
case Intrinsics::AtomicIsLockFree: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::AtomicLoad: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::AtomicRMW:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
case Intrinsics::AtomicStore: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Bswap: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Ctpop: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Ctlz: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Cttz: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Fabs: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Longjmp: {
@@ -542,7 +556,7 @@
}
case Intrinsics::NaClReadTP: {
if (Ctx->getFlags().getUseSandboxing()) {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
} else {
InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0);
lowerCall(Call);
@@ -556,19 +570,19 @@
return;
}
case Intrinsics::Sqrt: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Stacksave: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Stackrestore: {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
}
case Intrinsics::Trap:
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
return;
case Intrinsics::UnknownIntrinsic:
Func->setError("Should not be lowering UnknownIntrinsic");
@@ -579,17 +593,17 @@
void TargetMIPS32::lowerLoad(const InstLoad *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::doAddressOptLoad() {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::randomlyInsertNop(float Probability) {
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
if (RNG.getTrueWithProbability(Probability)) {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
}
@@ -598,31 +612,33 @@
}
void TargetMIPS32::lowerRet(const InstRet *Inst) {
- (void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ Variable *Reg = nullptr;
+ if (Inst->hasRetValue())
+ UnimplementedError(Func->getContext()->getFlags());
+ _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg);
}
void TargetMIPS32::lowerSelect(const InstSelect *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerStore(const InstStore *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::doAddressOptStore() {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerSwitch(const InstSwitch *Inst) {
(void)Inst;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::lowerUnreachable(const InstUnreachable * /*Inst*/) {
- llvm_unreachable("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to
@@ -630,7 +646,7 @@
// turned into zeroes, since loOperand() and hiOperand() don't expect
// Undef input.
void TargetMIPS32::prelowerPhis() {
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
// Lower the pre-ordered list of assignments into mov instructions.
@@ -639,7 +655,7 @@
const AssignList &Assignments) {
(void)Node;
(void)Assignments;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::postLower() {
@@ -647,7 +663,7 @@
return;
// Find two-address non-SSA instructions where Dest==Src0, and set
// the DestNonKillable flag to keep liveness analysis consistent.
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::makeRandomRegisterPermutation(
@@ -655,7 +671,7 @@
const llvm::SmallBitVector &ExcludeRegisters) const {
(void)Permutation;
(void)ExcludeRegisters;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Func->getContext()->getFlags());
}
/* TODO(jvoung): avoid duplicate symbols with multiple targets.
@@ -694,7 +710,7 @@
void TargetDataMIPS32::lowerConstants() {
if (Ctx->getFlags().getDisableTranslation())
return;
- llvm::report_fatal_error("Not yet implemented");
+ UnimplementedError(Ctx->getFlags());
}
TargetHeaderMIPS32::TargetHeaderMIPS32(GlobalContext *Ctx)
diff --git a/src/IceTargetLoweringMIPS32.h b/src/IceTargetLoweringMIPS32.h
index f872af0..a72c8db 100644
--- a/src/IceTargetLoweringMIPS32.h
+++ b/src/IceTargetLoweringMIPS32.h
@@ -76,6 +76,9 @@
(void)C;
llvm::report_fatal_error("Not yet implemented");
}
+ void _ret(Variable *RA, Variable *Src0 = nullptr) {
+ Context.insert(InstMIPS32Ret::create(Func, RA, Src0));
+ }
void lowerArguments() override;
void addProlog(CfgNode *Node) override;
diff --git a/tests_lit/llvm2ice_tests/function_aligned.ll b/tests_lit/llvm2ice_tests/function_aligned.ll
index 23d2ca7..03da464 100644
--- a/tests_lit/llvm2ice_tests/function_aligned.ll
+++ b/tests_lit/llvm2ice_tests/function_aligned.ll
@@ -13,6 +13,11 @@
; RUN: --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
; RUN: | %if --need=target_ARM32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix ARM32 %s
+; 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: | %if --need=target_MIPS32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix MIPS32 %s
define void @foo() {
ret void
@@ -25,6 +30,10 @@
; ARM32-NEXT: 4: e7fedef0 udf
; ARM32-NEXT: 8: e7fedef0 udf
; ARM32-NEXT: c: e7fedef0 udf
+; MIPS32-LABEL: foo
+; MIPS32: 4: {{.*}} jr ra
+; MIPS32-NEXT: 8: {{.*}} nop
+; MIPS32-NEXT: c: e7fedef0
define void @bar() {
ret void
@@ -33,3 +42,6 @@
; CHECK-NEXT: 20: {{.*}} ret
; ARM32-LABEL: bar
; ARM32-NEXT: 10: {{.*}} bx lr
+; MIPS32-LABEL: bar
+; MIPS32: 14: {{.*}} jr ra
+; MIPS32-NEXT: 18: {{.*}} nop