Commit 3fe4b570 by Reed Kotler Committed by Jim Stichnoth

Subzero: Basic unconditional branch for Mips.

This is part of ARM patch: https://codereview.chromium.org/1151663004/ BUG= R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1724643002 . Patch from Reed Kotler <rkotlerimgtec@gmail.com>.
parent a80cdbc2
......@@ -818,6 +818,8 @@ InstARM32Label::InstARM32Label(Cfg *Func, TargetARM32 *Target)
Number(Target->makeNextLabelNumber()) {}
IceString InstARM32Label::getName(const Cfg *Func) const {
if (!BuildDefs::dump())
return IceString();
return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
}
......
......@@ -106,6 +106,34 @@ template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
emitThreeAddrLoHi(Opcode, this, Func);
}
InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
const CfgNode *TargetFalse,
const InstMIPS32Label *Label)
: InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
TargetFalse(TargetFalse), Label(Label) {}
InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
: InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
Number(Target->makeNextLabelNumber()) {}
IceString InstMIPS32Label::getName(const Cfg *Func) const {
if (!BuildDefs::dump())
return IceString();
return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
}
void InstMIPS32Label::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrDump();
Str << getName(Func) << ":";
}
void InstMIPS32Label::emitIAS(const Cfg *Func) const {
(void)Func;
llvm_unreachable("Not yet implemented");
}
InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
: InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
HasSideEffects = true;
......@@ -225,6 +253,24 @@ void InstMIPS32Ret::emit(const Cfg *Func) const {
RA->emit(Func);
}
void InstMIPS32Br::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t"
"b"
<< "\t";
if (Label) {
Str << Label->getName(Func);
} else {
if (isUnconditionalBranch()) {
Str << getTargetFalse()->getAsmName();
} else {
// TODO(reed kotler): Finish implementing conditional branch.
}
}
}
void InstMIPS32Call::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
......
......@@ -121,8 +121,10 @@ public:
Addu,
And,
Addiu,
Br,
Call,
La,
Label,
Lui,
Mfhi,
Mflo,
......@@ -292,6 +294,73 @@ private:
static const char *Opcode;
};
// InstMIPS32Label represents an intra-block label that is the target of an
// intra-block branch. The offset between the label and the branch must be fit
// in the instruction immediate (considered "near").
class InstMIPS32Label : public InstMIPS32 {
InstMIPS32Label() = delete;
InstMIPS32Label(const InstMIPS32Label &) = delete;
InstMIPS32Label &operator=(const InstMIPS32Label &) = delete;
public:
static InstMIPS32Label *create(Cfg *Func, TargetMIPS32 *Target) {
return new (Func->allocate<InstMIPS32Label>())
InstMIPS32Label(Func, Target);
}
uint32_t getEmitInstCount() const override { return 0; }
IceString getName(const Cfg *Func) const;
SizeT getNumber() const { return Number; }
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 *Instr) { return isClassof(Instr, Label); }
private:
InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target);
RelocOffset *OffsetReloc = nullptr;
SizeT Number; // used for unique label generation.
};
/// Direct branch instruction.
class InstMIPS32Br : public InstMIPS32 {
InstMIPS32Br() = delete;
InstMIPS32Br(const InstMIPS32Br &) = delete;
InstMIPS32Br &operator=(const InstMIPS32Br &) = delete;
public:
/// Create an unconditional branch to a node.
static InstMIPS32Br *create(Cfg *Func, CfgNode *Target) {
constexpr CfgNode *NoCondTarget = nullptr;
constexpr InstMIPS32Label *NoLabel = nullptr;
return new (Func->allocate<InstMIPS32Br>())
InstMIPS32Br(Func, NoCondTarget, Target, NoLabel);
}
const CfgNode *getTargetTrue() const { return TargetTrue; }
const CfgNode *getTargetFalse() const { return TargetFalse; }
bool isUnconditionalBranch() const override { return true; }
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override {
(void)OldNode;
(void)NewNode;
return true;
};
void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override { (void)Func; };
void dump(const Cfg *Func) const override { (void)Func; };
static bool classof(const Inst *Instr) { return isClassof(Instr, Br); }
private:
InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
const InstMIPS32Label *Label);
const CfgNode *TargetTrue;
const CfgNode *TargetFalse;
const InstMIPS32Label *Label; // Intra-block branch target
};
class InstMIPS32Call : public InstMIPS32 {
InstMIPS32Call() = delete;
InstMIPS32Call(const InstMIPS32Call &) = delete;
......
......@@ -98,6 +98,8 @@ InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func,
template <typename TraitsType>
IceString InstImpl<TraitsType>::InstX86Label::getName(const Cfg *Func) const {
if (!BuildDefs::dump())
return IceString();
return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number);
}
......
......@@ -804,6 +804,10 @@ void TargetMIPS32::lowerAssign(const InstAssign *Instr) {
}
void TargetMIPS32::lowerBr(const InstBr *Instr) {
if (Instr->isUnconditional()) {
_br(Instr->getTargetUnconditional());
return;
}
UnimplementedLoweringError(this, Instr);
}
......
......@@ -147,6 +147,8 @@ public:
Context.insert<InstMIPS32And>(Dest, Src0, Src1);
}
void _br(CfgNode *Target) { Context.insert<InstMIPS32Br>(Target); }
void _ret(Variable *RA, Variable *Src0 = nullptr) {
Context.insert<InstMIPS32Ret>(RA, Src0);
}
......
; TODO(rkotler): Stop skipping unimplemented parts (via --skip-unimplemented)
; once enough infrastructure is in. Also, switch to --filetype=obj
; when possible.
; 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: -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
define internal void @uncond1(i32 %i) {
%1 = alloca i8, i32 4, align 4
%.bc = bitcast i8* %1 to i32*
store i32 %i, i32* %.bc, align 1
br label %target
target:
%.bc1 = bitcast i8* %1 to i32*
%2 = load i32, i32* %.bc1, align 1
%3 = add i32 %2, 1
%.bc2 = bitcast i8* %1 to i32*
store i32 %3, i32* %.bc2, align 1
br label %target
}
; MIPS32-LABEL: uncond1
; MIPS32: b 8 <.Luncond1$target>
; MIPS32: <.Luncond1$target>:
; MIPS32: li
; MIPS32: addu
; MIPS32: b 8 <.Luncond1$target>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment