Skip to content

Commit

Permalink
Merging r217432:
Browse files Browse the repository at this point in the history
------------------------------------------------------------------------
r217432 | tomatabacu | 2014-09-09 11:15:38 +0100 (Tue, 09 Sep 2014) | 12 lines

[mips] Add assembler support for .set push/pop directive.

Summary:
These directives are used to save the current assembler options (in the case of ".set push") and restore the previously saved options (in the case of ".set pop").

Contains work done by Matheus Almeida.

Reviewers: dsanders

Reviewed By: dsanders

Differential Revision: http://reviews.llvm.org/D4821
------------------------------------------------------------------------

llvm-svn: 232082
  • Loading branch information
dsandersllvm committed Mar 12, 2015
1 parent fedffd7 commit af61ee8
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 17 deletions.
100 changes: 83 additions & 17 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Expand Up @@ -13,6 +13,7 @@
#include "MipsTargetStreamer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
Expand All @@ -26,6 +27,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
#include <memory>

using namespace llvm;

Expand All @@ -38,23 +40,35 @@ class MCInstrInfo;
namespace {
class MipsAssemblerOptions {
public:
MipsAssemblerOptions() : ATReg(1), Reorder(true), Macro(true) {}
MipsAssemblerOptions(uint64_t Features_) :
ATReg(1), Reorder(true), Macro(true), Features(Features_) {}

unsigned getATRegNum() { return ATReg; }
MipsAssemblerOptions(const MipsAssemblerOptions *Opts) {
ATReg = Opts->getATRegNum();
Reorder = Opts->isReorder();
Macro = Opts->isMacro();
Features = Opts->getFeatures();
}

unsigned getATRegNum() const { return ATReg; }
bool setATReg(unsigned Reg);

bool isReorder() { return Reorder; }
bool isReorder() const { return Reorder; }
void setReorder() { Reorder = true; }
void setNoReorder() { Reorder = false; }

bool isMacro() { return Macro; }
bool isMacro() const { return Macro; }
void setMacro() { Macro = true; }
void setNoMacro() { Macro = false; }

uint64_t getFeatures() const { return Features; }
void setFeatures(uint64_t Features_) { Features = Features_; }

private:
unsigned ATReg;
bool Reorder;
bool Macro;
uint64_t Features;
};
}

Expand All @@ -67,7 +81,7 @@ class MipsAsmParser : public MCTargetAsmParser {

MCSubtargetInfo &STI;
MCAsmParser &Parser;
MipsAssemblerOptions Options;
SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions;

#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
Expand Down Expand Up @@ -157,6 +171,8 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetNoReorderDirective();
bool parseSetNoMips16Directive();
bool parseSetFpDirective();
bool parseSetPopDirective();
bool parseSetPushDirective();

bool parseSetAssignment();

Expand Down Expand Up @@ -205,13 +221,15 @@ class MipsAsmParser : public MCTargetAsmParser {
setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
AssemblerOptions.back()->setFeatures(getAvailableFeatures());
}

void clearFeatureBits(uint64_t Feature, StringRef FeatureString) {
if (STI.getFeatureBits() & Feature) {
setAvailableFeatures(
ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
AssemblerOptions.back()->setFeatures(getAvailableFeatures());
}

public:
Expand All @@ -228,6 +246,16 @@ class MipsAsmParser : public MCTargetAsmParser {
: MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));

// Remember the initial assembler options. The user can not modify these.
MipsAssemblerOptions *TmpAOPtr =
new MipsAssemblerOptions(getAvailableFeatures());
AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));

// Create an assembler options environment for the user to modify.
TmpAOPtr = new MipsAssemblerOptions(getAvailableFeatures());
AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));
TmpAOPtr = nullptr;

getTargetStreamer().updateABIInfo(*this);

Expand Down Expand Up @@ -961,7 +989,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
"nop instruction");
}

if (MCID.hasDelaySlot() && Options.isReorder()) {
if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
Instructions.push_back(Inst);
Expand Down Expand Up @@ -1424,7 +1452,8 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
}

void MipsAsmParser::WarnIfAssemblerTemporary(int RegIndex, SMLoc Loc) {
if ((RegIndex != 0) && ((int)Options.getATRegNum() == RegIndex)) {
if ((RegIndex != 0) &&
((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) {
if (RegIndex == 1)
Warning(Loc, "Used $at without \".set noat\"");
else
Expand Down Expand Up @@ -1573,7 +1602,7 @@ bool MipsAssemblerOptions::setATReg(unsigned Reg) {
}

int MipsAsmParser::getATReg(SMLoc Loc) {
int AT = Options.getATRegNum();
int AT = AssemblerOptions.back()->getATRegNum();
if (AT == 0)
reportParseError(Loc,
"Pseudo instruction requires $at, which is not available");
Expand Down Expand Up @@ -2328,7 +2357,7 @@ bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) {
bool MipsAsmParser::parseSetNoAtDirective() {
// Line should look like: ".set noat".
// set at reg to 0.
Options.setATReg(0);
AssemblerOptions.back()->setATReg(0);
// eat noat
Parser.Lex();
// If this is not the end of the statement, report an error.
Expand All @@ -2346,7 +2375,7 @@ bool MipsAsmParser::parseSetAtDirective() {
int AtRegNo;
getParser().Lex();
if (getLexer().is(AsmToken::EndOfStatement)) {
Options.setATReg(1);
AssemblerOptions.back()->setATReg(1);
Parser.Lex(); // Consume the EndOfStatement.
return false;
} else if (getLexer().is(AsmToken::Equal)) {
Expand All @@ -2371,7 +2400,7 @@ bool MipsAsmParser::parseSetAtDirective() {
return false;
}

if (!Options.setATReg(AtRegNo)) {
if (!AssemblerOptions.back()->setATReg(AtRegNo)) {
reportParseError("unexpected token in statement");
return false;
}
Expand All @@ -2396,7 +2425,7 @@ bool MipsAsmParser::parseSetReorderDirective() {
reportParseError("unexpected token in statement");
return false;
}
Options.setReorder();
AssemblerOptions.back()->setReorder();
getTargetStreamer().emitDirectiveSetReorder();
Parser.Lex(); // Consume the EndOfStatement.
return false;
Expand All @@ -2409,7 +2438,7 @@ bool MipsAsmParser::parseSetNoReorderDirective() {
reportParseError("unexpected token in statement");
return false;
}
Options.setNoReorder();
AssemblerOptions.back()->setNoReorder();
getTargetStreamer().emitDirectiveSetNoReorder();
Parser.Lex(); // Consume the EndOfStatement.
return false;
Expand All @@ -2422,7 +2451,7 @@ bool MipsAsmParser::parseSetMacroDirective() {
reportParseError("unexpected token in statement");
return false;
}
Options.setMacro();
AssemblerOptions.back()->setMacro();
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
Expand All @@ -2434,11 +2463,11 @@ bool MipsAsmParser::parseSetNoMacroDirective() {
reportParseError("`noreorder' must be set before `nomacro'");
return false;
}
if (Options.isReorder()) {
if (AssemblerOptions.back()->isReorder()) {
reportParseError("`noreorder' must be set before `nomacro'");
return false;
}
Options.setNoMacro();
AssemblerOptions.back()->setNoMacro();
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
Expand Down Expand Up @@ -2481,6 +2510,39 @@ bool MipsAsmParser::parseSetFpDirective() {
return false;
}

bool MipsAsmParser::parseSetPopDirective() {
SMLoc Loc = getLexer().getLoc();

Parser.Lex();
if (getLexer().isNot(AsmToken::EndOfStatement))
return reportParseError("unexpected token, expected end of statement");

// Always keep an element on the options "stack" to prevent the user
// from changing the initial options. This is how we remember them.
if (AssemblerOptions.size() == 2)
return reportParseError(Loc, ".set pop with no .set push");

AssemblerOptions.pop_back();
setAvailableFeatures(AssemblerOptions.back()->getFeatures());

getTargetStreamer().emitDirectiveSetPop();
return false;
}

bool MipsAsmParser::parseSetPushDirective() {
Parser.Lex();
if (getLexer().isNot(AsmToken::EndOfStatement))
return reportParseError("unexpected token, expected end of statement");

// Create a copy of the current assembler options environment and push it.
MipsAssemblerOptions *TmpAOPtr =
new MipsAssemblerOptions(AssemblerOptions.back().get());
AssemblerOptions.push_back(std::unique_ptr<MipsAssemblerOptions>(TmpAOPtr));

getTargetStreamer().emitDirectiveSetPush();
return false;
}

bool MipsAsmParser::parseSetAssignment() {
StringRef Name;
const MCExpr *Value;
Expand Down Expand Up @@ -2551,7 +2613,7 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
}

bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
if (Options.isReorder())
if (AssemblerOptions.back()->isReorder())
Warning(Loc, ".cpload in reorder section");

// FIXME: Warn if cpload is used in Mips16 mode.
Expand Down Expand Up @@ -2664,6 +2726,10 @@ bool MipsAsmParser::parseDirectiveSet() {
return parseSetAtDirective();
} else if (Tok.getString() == "fp") {
return parseSetFpDirective();
} else if (Tok.getString() == "pop") {
return parseSetPopDirective();
} else if (Tok.getString() == "push") {
return parseSetPushDirective();
} else if (Tok.getString() == "reorder") {
return parseSetReorderDirective();
} else if (Tok.getString() == "noreorder") {
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
Expand Up @@ -55,6 +55,8 @@ void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) {
void MipsTargetStreamer::emitDirectiveSetMips32R2() {}
void MipsTargetStreamer::emitDirectiveSetMips64() {}
void MipsTargetStreamer::emitDirectiveSetMips64R2() {}
void MipsTargetStreamer::emitDirectiveSetPop() {}
void MipsTargetStreamer::emitDirectiveSetPush() {}
void MipsTargetStreamer::emitDirectiveSetDsp() {}
void MipsTargetStreamer::emitDirectiveCpload(unsigned RegNo) {}
void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
Expand Down Expand Up @@ -171,6 +173,11 @@ void MipsTargetAsmStreamer::emitDirectiveSetDsp() {
OS << "\t.set\tdsp\n";
setCanHaveModuleDir(false);
}

void MipsTargetAsmStreamer::emitDirectiveSetPop() { OS << "\t.set\tpop\n"; }

void MipsTargetAsmStreamer::emitDirectiveSetPush() { OS << "\t.set\tpush\n"; }

// Print a 32 bit hex number with all numbers.
static void printHex32(unsigned Value, raw_ostream &OS) {
OS << "0x";
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/Mips/MipsTargetStreamer.h
Expand Up @@ -49,6 +49,8 @@ class MipsTargetStreamer : public MCTargetStreamer {
virtual void emitDirectiveSetMips64();
virtual void emitDirectiveSetMips64R2();
virtual void emitDirectiveSetDsp();
virtual void emitDirectiveSetPop();
virtual void emitDirectiveSetPush();

// PIC support
virtual void emitDirectiveCpload(unsigned RegNo);
Expand Down Expand Up @@ -125,6 +127,8 @@ class MipsTargetAsmStreamer : public MipsTargetStreamer {
void emitDirectiveSetMips64() override;
void emitDirectiveSetMips64R2() override;
void emitDirectiveSetDsp() override;
void emitDirectiveSetPop() override;
void emitDirectiveSetPush() override;

// PIC support
virtual void emitDirectiveCpload(unsigned RegNo);
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/MC/Mips/set-push-pop-directives-bad.s
@@ -0,0 +1,14 @@
# RUN: not llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 2>%t1
# RUN: FileCheck %s < %t1

.text
.set pop
# CHECK: :[[@LINE-1]]:14: error: .set pop with no .set push
.set push
.set pop
.set pop
# CHECK: :[[@LINE-1]]:14: error: .set pop with no .set push
.set push foo
# CHECK: :[[@LINE-1]]:19: error: unexpected token, expected end of statement
.set pop bar
# CHECK: :[[@LINE-1]]:18: error: unexpected token, expected end of statement
47 changes: 47 additions & 0 deletions llvm/test/MC/Mips/set-push-pop-directives.s
@@ -0,0 +1,47 @@
# RUN: llvm-mc %s -triple=mipsel-unknown-linux -mcpu=mips32r2 -mattr=+msa | \
# RUN: FileCheck %s
# .set push creates a copy of the current environment.
# .set pop restores the previous environment.
# FIXME: Also test resetting of .set macro/nomacro option.

.text
# The first environment on the stack (with initial values).
lw $1, 65536($1)
b 1336
addvi.b $w15, $w13, 18

# Create a new environment.
.set push
.set at=$ra # Test the ATReg option.
lw $1, 65536($1)
.set noreorder # Test the Reorder option.
b 1336

# Switch back to the first environment.
.set pop
lw $1, 65536($1)
b 1336
addvi.b $w15, $w13, 18

# CHECK: lui $1, 1
# CHECK: addu $1, $1, $1
# CHECK: lw $1, 0($1)
# CHECK: b 1336
# CHECK: nop
# CHECK: addvi.b $w15, $w13, 18

# CHECK: .set push
# CHECK: lui $ra, 1
# CHECK: addu $ra, $ra, $1
# CHECK: lw $1, 0($ra)
# CHECK: .set noreorder
# CHECK: b 1336
# CHECK-NOT: nop

# CHECK: .set pop
# CHECK: lui $1, 1
# CHECK: addu $1, $1, $1
# CHECK: lw $1, 0($1)
# CHECK: b 1336
# CHECK: nop
# CHECK: addvi.b $w15, $w13, 18

0 comments on commit af61ee8

Please sign in to comment.