AsmMatchers: Use unique_ptr to manage ownership of MCParsedAsmOperand

I saw at least a memory leak or two from inspection (on probably
untested error paths) and r206991, which was the original inspiration
for this change.

I ran this idea by Jim Grosbach a few weeks ago & he was OK with it.
Since it's a basically mechanical patch that seemed sufficient - usual
post-commit review, revert, etc, as needed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210427 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2014-06-08 16:18:35 +00:00
parent e570687bd8
commit c50f986b4d
13 changed files with 982 additions and 1119 deletions

View File

@ -14,6 +14,8 @@
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
#include "llvm/MC/MCTargetOptions.h"
#include <memory>
namespace llvm {
class AsmToken;
class MCInst;
@ -23,6 +25,8 @@ class SMLoc;
class StringRef;
template <typename T> class SmallVectorImpl;
typedef SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>> OperandVector;
enum AsmRewriteKind {
AOK_Delete = 0, // Rewrite should be ignored.
AOK_Align, // Rewrite align as .align.
@ -131,8 +135,7 @@ public:
/// ownership of them to the caller.
/// \return True on failure.
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
SMLoc NameLoc, OperandVector &Operands) = 0;
/// ParseDirective - Parse a target specific assembler directive
///
@ -156,17 +159,16 @@ public:
///
/// On failure, the target parser is responsible for emitting a diagnostic
/// explaining the match failure.
virtual bool
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) = 0;
virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) = 0;
/// Allow a target to add special case operand matching for things that
/// tblgen doesn't/can't handle effectively. For example, literal
/// immediates on ARM. TableGen expects a token operand, but the parser
/// will recognize them as immediates.
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
virtual unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) {
return Match_InvalidOperand;
}
@ -178,7 +180,7 @@ public:
}
virtual void convertToMapAndConstraints(unsigned Kind,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
const OperandVector &Operands) = 0;
virtual const MCExpr *applyModifierToExpr(const MCExpr *E,
MCSymbolRefExpr::VariantKind,

View File

@ -102,7 +102,7 @@ public:
struct ParseStatementInfo {
/// \brief The parsed operands from the last parsed statement.
SmallVector<MCParsedAsmOperand*, 8> ParsedOperands;
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> ParsedOperands;
/// \brief The opcode from the last parsed instruction.
unsigned Opcode;
@ -115,13 +115,6 @@ struct ParseStatementInfo {
ParseStatementInfo() : Opcode(~0U), ParseError(false), AsmRewrites(nullptr) {}
ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
: Opcode(~0), ParseError(false), AsmRewrites(rewrites) {}
~ParseStatementInfo() {
// Free any parsed operands.
for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i)
delete ParsedOperands[i];
ParsedOperands.clear();
}
};
/// \brief The concrete assembly parser instance.
@ -4465,27 +4458,27 @@ bool AsmParser::parseMSInlineAsm(
// Build the list of clobbers, outputs and inputs.
for (unsigned i = 1, e = Info.ParsedOperands.size(); i != e; ++i) {
MCParsedAsmOperand *Operand = Info.ParsedOperands[i];
MCParsedAsmOperand &Operand = *Info.ParsedOperands[i];
// Immediate.
if (Operand->isImm())
if (Operand.isImm())
continue;
// Register operand.
if (Operand->isReg() && !Operand->needAddressOf()) {
if (Operand.isReg() && !Operand.needAddressOf()) {
unsigned NumDefs = Desc.getNumDefs();
// Clobber.
if (NumDefs && Operand->getMCOperandNum() < NumDefs)
ClobberRegs.push_back(Operand->getReg());
if (NumDefs && Operand.getMCOperandNum() < NumDefs)
ClobberRegs.push_back(Operand.getReg());
continue;
}
// Expr/Input or Output.
StringRef SymName = Operand->getSymName();
StringRef SymName = Operand.getSymName();
if (SymName.empty())
continue;
void *OpDecl = Operand->getOpDecl();
void *OpDecl = Operand.getOpDecl();
if (!OpDecl)
continue;
@ -4494,13 +4487,13 @@ bool AsmParser::parseMSInlineAsm(
if (isOutput) {
++InputIdx;
OutputDecls.push_back(OpDecl);
OutputDeclsAddressOf.push_back(Operand->needAddressOf());
OutputConstraints.push_back('=' + Operand->getConstraint().str());
OutputDeclsAddressOf.push_back(Operand.needAddressOf());
OutputConstraints.push_back('=' + Operand.getConstraint().str());
AsmStrRewrites.push_back(AsmRewrite(AOK_Output, Start, SymName.size()));
} else {
InputDecls.push_back(OpDecl);
InputDeclsAddressOf.push_back(Operand->needAddressOf());
InputConstraints.push_back(Operand->getConstraint().str());
InputDeclsAddressOf.push_back(Operand.needAddressOf());
InputConstraints.push_back(Operand.getConstraint().str());
AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size()));
}
}

View File

@ -38,9 +38,6 @@ namespace {
class AArch64Operand;
class AArch64AsmParser : public MCTargetAsmParser {
public:
typedef SmallVectorImpl<MCParsedAsmOperand *> OperandVector;
private:
StringRef Mnemonic; ///< Instruction mnemonic.
MCSubtargetInfo &STI;
@ -117,7 +114,7 @@ public:
SMLoc NameLoc, OperandVector &Operands) override;
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseDirective(AsmToken DirectiveID) override;
unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
static bool classifySymbolRef(const MCExpr *Expr,
@ -240,10 +237,10 @@ private:
// the add<>Operands() calls.
MCContext &Ctx;
public:
AArch64Operand(KindTy K, MCContext &_Ctx)
: MCParsedAsmOperand(), Kind(K), Ctx(_Ctx) {}
public:
AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
Kind = o.Kind;
StartLoc = o.StartLoc;
@ -1523,9 +1520,9 @@ public:
void print(raw_ostream &OS) const override;
static AArch64Operand *CreateToken(StringRef Str, bool IsSuffix, SMLoc S,
MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_Token, Ctx);
static std::unique_ptr<AArch64Operand>
CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->Tok.IsSuffix = IsSuffix;
@ -1534,9 +1531,9 @@ public:
return Op;
}
static AArch64Operand *CreateReg(unsigned RegNum, bool isVector, SMLoc S,
SMLoc E, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_Register, Ctx);
static std::unique_ptr<AArch64Operand>
CreateReg(unsigned RegNum, bool isVector, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Op->Reg.RegNum = RegNum;
Op->Reg.isVector = isVector;
Op->StartLoc = S;
@ -1544,10 +1541,10 @@ public:
return Op;
}
static AArch64Operand *CreateVectorList(unsigned RegNum, unsigned Count,
unsigned NumElements, char ElementKind,
SMLoc S, SMLoc E, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_VectorList, Ctx);
static std::unique_ptr<AArch64Operand>
CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Op->VectorList.RegNum = RegNum;
Op->VectorList.Count = Count;
Op->VectorList.NumElements = NumElements;
@ -1557,28 +1554,29 @@ public:
return Op;
}
static AArch64Operand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_VectorIndex, Ctx);
static std::unique_ptr<AArch64Operand>
CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Op->VectorIndex.Val = Idx;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static AArch64Operand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_Immediate, Ctx);
static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static AArch64Operand *CreateShiftedImm(const MCExpr *Val,
unsigned ShiftAmount, SMLoc S,
SMLoc E, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_ShiftedImm, Ctx);
static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
unsigned ShiftAmount,
SMLoc S, SMLoc E,
MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Op->ShiftedImm .Val = Val;
Op->ShiftedImm.ShiftAmount = ShiftAmount;
Op->StartLoc = S;
@ -1586,34 +1584,36 @@ public:
return Op;
}
static AArch64Operand *CreateCondCode(AArch64CC::CondCode Code, SMLoc S,
SMLoc E, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_CondCode, Ctx);
static std::unique_ptr<AArch64Operand>
CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Op->CondCode.Code = Code;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static AArch64Operand *CreateFPImm(unsigned Val, SMLoc S, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_FPImm, Ctx);
static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Op->FPImm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
static AArch64Operand *CreateBarrier(unsigned Val, SMLoc S, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_Barrier, Ctx);
static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val, SMLoc S,
MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Op->Barrier.Val = Val;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
static AArch64Operand *CreateSysReg(StringRef Str, SMLoc S,
uint64_t FeatureBits, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_SysReg, Ctx);
static std::unique_ptr<AArch64Operand>
CreateSysReg(StringRef Str, SMLoc S, uint64_t FeatureBits, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Op->SysReg.Data = Str.data();
Op->SysReg.Length = Str.size();
Op->SysReg.FeatureBits = FeatureBits;
@ -1622,27 +1622,28 @@ public:
return Op;
}
static AArch64Operand *CreateSysCR(unsigned Val, SMLoc S, SMLoc E,
MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_SysCR, Ctx);
static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Op->SysCRImm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static AArch64Operand *CreatePrefetch(unsigned Val, SMLoc S, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_Prefetch, Ctx);
static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val, SMLoc S,
MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Op->Prefetch.Val = Val;
Op->StartLoc = S;
Op->EndLoc = S;
return Op;
}
static AArch64Operand *CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp,
unsigned Val, bool HasExplicitAmount,
SMLoc S, SMLoc E, MCContext &Ctx) {
AArch64Operand *Op = new AArch64Operand(k_ShiftExtend, Ctx);
static std::unique_ptr<AArch64Operand>
CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Op->ShiftExtend.Type = ShOp;
Op->ShiftExtend.Amount = Val;
Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
@ -3456,23 +3457,23 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
unsigned &ErrorInfo,
bool MatchingInlineAsm) {
assert(!Operands.empty() && "Unexpect empty operand list!");
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[0]);
assert(Op->isToken() && "Leading operand should always be a mnemonic!");
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
assert(Op.isToken() && "Leading operand should always be a mnemonic!");
StringRef Tok = Op->getToken();
StringRef Tok = Op.getToken();
unsigned NumOperands = Operands.size();
if (NumOperands == 4 && Tok == "lsl") {
AArch64Operand *Op2 = static_cast<AArch64Operand *>(Operands[2]);
AArch64Operand *Op3 = static_cast<AArch64Operand *>(Operands[3]);
if (Op2->isReg() && Op3->isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3->getImm());
AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
if (Op2.isReg() && Op3.isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
if (Op3CE) {
uint64_t Op3Val = Op3CE->getValue();
uint64_t NewOp3Val = 0;
uint64_t NewOp4Val = 0;
if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
Op2->getReg())) {
Op2.getReg())) {
NewOp3Val = (32 - Op3Val) & 0x1f;
NewOp4Val = 31 - Op3Val;
} else {
@ -3484,26 +3485,24 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
const MCExpr *NewOp4 = MCConstantExpr::Create(NewOp4Val, getContext());
Operands[0] = AArch64Operand::CreateToken(
"ubfm", false, Op->getStartLoc(), getContext());
Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3->getStartLoc(),
Op3->getEndLoc(), getContext());
"ubfm", false, Op.getStartLoc(), getContext());
Operands.push_back(AArch64Operand::CreateImm(
NewOp4, Op3->getStartLoc(), Op3->getEndLoc(), getContext()));
delete Op3;
delete Op;
NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
Op3.getEndLoc(), getContext());
}
}
} else if (NumOperands == 5) {
// FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
// UBFIZ -> UBFM aliases.
if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
AArch64Operand *Op1 = static_cast<AArch64Operand *>(Operands[1]);
AArch64Operand *Op3 = static_cast<AArch64Operand *>(Operands[3]);
AArch64Operand *Op4 = static_cast<AArch64Operand *>(Operands[4]);
AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
if (Op1->isReg() && Op3->isImm() && Op4->isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3->getImm());
const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4->getImm());
if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
if (Op3CE && Op4CE) {
uint64_t Op3Val = Op3CE->getValue();
@ -3511,21 +3510,21 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
uint64_t RegWidth = 0;
if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
Op1->getReg()))
Op1.getReg()))
RegWidth = 64;
else
RegWidth = 32;
if (Op3Val >= RegWidth)
return Error(Op3->getStartLoc(),
return Error(Op3.getStartLoc(),
"expected integer in range [0, 31]");
if (Op4Val < 1 || Op4Val > RegWidth)
return Error(Op4->getStartLoc(),
return Error(Op4.getStartLoc(),
"expected integer in range [1, 32]");
uint64_t NewOp3Val = 0;
if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
Op1->getReg()))
Op1.getReg()))
NewOp3Val = (32 - Op3Val) & 0x1f;
else
NewOp3Val = (64 - Op3Val) & 0x3f;
@ -3533,7 +3532,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
uint64_t NewOp4Val = Op4Val - 1;
if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
return Error(Op4->getStartLoc(),
return Error(Op4.getStartLoc(),
"requested insert overflows register");
const MCExpr *NewOp3 =
@ -3541,24 +3540,20 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
const MCExpr *NewOp4 =
MCConstantExpr::Create(NewOp4Val, getContext());
Operands[3] = AArch64Operand::CreateImm(
NewOp3, Op3->getStartLoc(), Op3->getEndLoc(), getContext());
NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Operands[4] = AArch64Operand::CreateImm(
NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
if (Tok == "bfi")
Operands[0] = AArch64Operand::CreateToken(
"bfm", false, Op->getStartLoc(), getContext());
"bfm", false, Op.getStartLoc(), getContext());
else if (Tok == "sbfiz")
Operands[0] = AArch64Operand::CreateToken(
"sbfm", false, Op->getStartLoc(), getContext());
"sbfm", false, Op.getStartLoc(), getContext());
else if (Tok == "ubfiz")
Operands[0] = AArch64Operand::CreateToken(
"ubfm", false, Op->getStartLoc(), getContext());
"ubfm", false, Op.getStartLoc(), getContext());
else
llvm_unreachable("No valid mnemonic for alias?");
delete Op;
delete Op3;
delete Op4;
}
}
@ -3566,13 +3561,13 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
// UBFX -> UBFM aliases.
} else if (NumOperands == 5 &&
(Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
AArch64Operand *Op1 = static_cast<AArch64Operand *>(Operands[1]);
AArch64Operand *Op3 = static_cast<AArch64Operand *>(Operands[3]);
AArch64Operand *Op4 = static_cast<AArch64Operand *>(Operands[4]);
AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
if (Op1->isReg() && Op3->isImm() && Op4->isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3->getImm());
const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4->getImm());
if (Op1.isReg() && Op3.isImm() && Op4.isImm()) {
const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
if (Op3CE && Op4CE) {
uint64_t Op3Val = Op3CE->getValue();
@ -3580,42 +3575,39 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
uint64_t RegWidth = 0;
if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
Op1->getReg()))
Op1.getReg()))
RegWidth = 64;
else
RegWidth = 32;
if (Op3Val >= RegWidth)
return Error(Op3->getStartLoc(),
return Error(Op3.getStartLoc(),
"expected integer in range [0, 31]");
if (Op4Val < 1 || Op4Val > RegWidth)
return Error(Op4->getStartLoc(),
return Error(Op4.getStartLoc(),
"expected integer in range [1, 32]");
uint64_t NewOp4Val = Op3Val + Op4Val - 1;
if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
return Error(Op4->getStartLoc(),
return Error(Op4.getStartLoc(),
"requested extract overflows register");
const MCExpr *NewOp4 =
MCConstantExpr::Create(NewOp4Val, getContext());
Operands[4] = AArch64Operand::CreateImm(
NewOp4, Op4->getStartLoc(), Op4->getEndLoc(), getContext());
NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
if (Tok == "bfxil")
Operands[0] = AArch64Operand::CreateToken(
"bfm", false, Op->getStartLoc(), getContext());
"bfm", false, Op.getStartLoc(), getContext());
else if (Tok == "sbfx")
Operands[0] = AArch64Operand::CreateToken(
"sbfm", false, Op->getStartLoc(), getContext());
"sbfm", false, Op.getStartLoc(), getContext());
else if (Tok == "ubfx")
Operands[0] = AArch64Operand::CreateToken(
"ubfm", false, Op->getStartLoc(), getContext());
"ubfm", false, Op.getStartLoc(), getContext());
else
llvm_unreachable("No valid mnemonic for alias?");
delete Op;
delete Op4;
}
}
}
@ -3626,63 +3618,58 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
// The source register can be Wn here, but the matcher expects a
// GPR64. Twiddle it here if necessary.
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[2]);
if (Op->isReg()) {
unsigned Reg = getXRegFromWReg(Op->getReg());
Operands[2] = AArch64Operand::CreateReg(Reg, false, Op->getStartLoc(),
Op->getEndLoc(), getContext());
delete Op;
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
if (Op.isReg()) {
unsigned Reg = getXRegFromWReg(Op.getReg());
Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
Op.getEndLoc(), getContext());
}
}
// FIXME: Likewise for sxt[bh] with a Xd dst operand
else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[1]);
if (Op->isReg() &&
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
if (Op.isReg() &&
AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
Op->getReg())) {
Op.getReg())) {
// The source register can be Wn here, but the matcher expects a
// GPR64. Twiddle it here if necessary.
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[2]);
if (Op->isReg()) {
unsigned Reg = getXRegFromWReg(Op->getReg());
Operands[2] = AArch64Operand::CreateReg(Reg, false, Op->getStartLoc(),
Op->getEndLoc(), getContext());
delete Op;
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
if (Op.isReg()) {
unsigned Reg = getXRegFromWReg(Op.getReg());
Operands[2] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
Op.getEndLoc(), getContext());
}
}
}
// FIXME: Likewise for uxt[bh] with a Xd dst operand
else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[1]);
if (Op->isReg() &&
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
if (Op.isReg() &&
AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
Op->getReg())) {
Op.getReg())) {
// The source register can be Wn here, but the matcher expects a
// GPR32. Twiddle it here if necessary.
AArch64Operand *Op = static_cast<AArch64Operand *>(Operands[1]);
if (Op->isReg()) {
unsigned Reg = getWRegFromXReg(Op->getReg());
Operands[1] = AArch64Operand::CreateReg(Reg, false, Op->getStartLoc(),
Op->getEndLoc(), getContext());
delete Op;
AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
if (Op.isReg()) {
unsigned Reg = getWRegFromXReg(Op.getReg());
Operands[1] = AArch64Operand::CreateReg(Reg, false, Op.getStartLoc(),
Op.getEndLoc(), getContext());
}
}
}
// Yet another horrible hack to handle FMOV Rd, #0.0 using [WX]ZR.
if (NumOperands == 3 && Tok == "fmov") {
AArch64Operand *RegOp = static_cast<AArch64Operand *>(Operands[1]);
AArch64Operand *ImmOp = static_cast<AArch64Operand *>(Operands[2]);
if (RegOp->isReg() && ImmOp->isFPImm() &&
ImmOp->getFPImm() == (unsigned)-1) {
AArch64Operand &RegOp = static_cast<AArch64Operand &>(*Operands[1]);
AArch64Operand &ImmOp = static_cast<AArch64Operand &>(*Operands[2]);
if (RegOp.isReg() && ImmOp.isFPImm() && ImmOp.getFPImm() == (unsigned)-1) {
unsigned zreg =
AArch64MCRegisterClasses[AArch64::FPR32RegClassID].contains(
RegOp->getReg())
RegOp.getReg())
? AArch64::WZR
: AArch64::XZR;
Operands[2] = AArch64Operand::CreateReg(zreg, false, Op->getStartLoc(),
Op->getEndLoc(), getContext());
delete ImmOp;
Operands[2] = AArch64Operand::CreateReg(zreg, false, Op.getStartLoc(),
Op.getEndLoc(), getContext());
}
}
@ -3735,14 +3722,14 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = ((AArch64Operand *)Operands[ErrorInfo])->getStartLoc();
ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
// If the match failed on a suffix token operand, tweak the diagnostic
// accordingly.
if (((AArch64Operand *)Operands[ErrorInfo])->isToken() &&
((AArch64Operand *)Operands[ErrorInfo])->isTokenSuffix())
if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
MatchResult = Match_InvalidSuffix;
return showMatchError(ErrorLoc, MatchResult);
@ -3798,7 +3785,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "too few operands for instruction");
// Any time we get here, there's nothing fancy to do. Just get the
// operand SMLoc and display the diagnostic.
SMLoc ErrorLoc = ((AArch64Operand *)Operands[ErrorInfo])->getStartLoc();
SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
return showMatchError(ErrorLoc, MatchResult);
@ -3988,9 +3975,9 @@ extern "C" void LLVMInitializeAArch64AsmParser() {
// Define this matcher function after the auto-generated include so we
// have the match class enum definitions.
unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
unsigned Kind) {
AArch64Operand *Op = static_cast<AArch64Operand *>(AsmOp);
AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
// If the kind is a token for a literal immediate, check if our asm
// operand matches. This is for InstAliases which have a fixed-value
// immediate in the syntax.
@ -4038,9 +4025,9 @@ unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
ExpectedVal = 8;
break;
}
if (!Op->isImm())
if (!Op.isImm())
return Match_InvalidOperand;
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
if (!CE)
return Match_InvalidOperand;
if (CE->getValue() == ExpectedVal)

File diff suppressed because it is too large Load Diff

View File

@ -73,55 +73,44 @@ class MipsAsmParser : public MCTargetAsmParser {
#include "MipsGenAsmMatcher.inc"
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) override;
/// Parse a register as used in CFI directives
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseParenSuffix(StringRef Name,
SmallVectorImpl<MCParsedAsmOperand *> &Operands);
bool ParseParenSuffix(StringRef Name, OperandVector &Operands);
bool ParseBracketSuffix(StringRef Name,
SmallVectorImpl<MCParsedAsmOperand *> &Operands);
bool ParseBracketSuffix(StringRef Name, OperandVector &Operands);
bool
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand *> &Operands) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
bool ParseDirective(AsmToken DirectiveID) override;
MipsAsmParser::OperandMatchResultTy
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy MatchAnyRegisterNameWithoutDollar(
SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
SMLoc S);
MipsAsmParser::OperandMatchResultTy parseMemOperand(OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
MatchAnyRegisterWithoutDollar(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
SMLoc S);
MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier, SMLoc S);
MipsAsmParser::OperandMatchResultTy
ParseAnyRegister(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S);
MipsAsmParser::OperandMatchResultTy
ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy ParseAnyRegister(OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
ParseJumpTarget(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy ParseImm(OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy ParseJumpTarget(OperandVector &Operands);
MipsAsmParser::OperandMatchResultTy
ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy parseInvNum(OperandVector &Operands);
bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
MipsAsmParser::OperandMatchResultTy ParseLSAImm(OperandVector &Operands);
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &,
StringRef Mnemonic);
bool searchSymbolAlias(OperandVector &Operands);
bool ParseOperand(OperandVector &, StringRef Mnemonic);
bool needsExpansion(MCInst &Inst);
@ -289,9 +278,11 @@ private:
k_Token /// A simple token
} Kind;
public:
MipsOperand(KindTy K, MipsAsmParser &Parser)
: MCParsedAsmOperand(), Kind(K), AsmParser(Parser) {}
private:
/// For diagnostics, and checking the assembler temporary
MipsAsmParser &AsmParser;
@ -330,10 +321,11 @@ private:
SMLoc StartLoc, EndLoc;
/// Internal constructor for register kinds
static MipsOperand *CreateReg(unsigned Index, RegKind RegKind,
const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
MipsOperand *Op = new MipsOperand(k_RegisterIndex, Parser);
static std::unique_ptr<MipsOperand> CreateReg(unsigned Index, RegKind RegKind,
const MCRegisterInfo *RegInfo,
SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_RegisterIndex, Parser);
Op->RegIdx.Index = Index;
Op->RegIdx.RegInfo = RegInfo;
Op->RegIdx.Kind = RegKind;
@ -656,9 +648,9 @@ public:
return Mem.Off;
}
static MipsOperand *CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) {
MipsOperand *Op = new MipsOperand(k_Token, Parser);
static std::unique_ptr<MipsOperand> CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_Token, Parser);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@ -668,74 +660,75 @@ public:
/// Create a numeric register (e.g. $1). The exact register remains
/// unresolved until an instruction successfully matches
static MipsOperand *CreateNumericReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateNumericReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
DEBUG(dbgs() << "CreateNumericReg(" << Index << ", ...)\n");
return CreateReg(Index, RegKind_Numeric, RegInfo, S, E, Parser);
}
/// Create a register that is definitely a GPR.
/// This is typically only used for named registers such as $gp.
static MipsOperand *CreateGPRReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateGPRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_GPR, RegInfo, S, E, Parser);
}
/// Create a register that is definitely a FGR.
/// This is typically only used for named registers such as $f0.
static MipsOperand *CreateFGRReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateFGRReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_FGR, RegInfo, S, E, Parser);
}
/// Create a register that is definitely an FCC.
/// This is typically only used for named registers such as $fcc0.
static MipsOperand *CreateFCCReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateFCCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_FCC, RegInfo, S, E, Parser);
}
/// Create a register that is definitely an ACC.
/// This is typically only used for named registers such as $ac0.
static MipsOperand *CreateACCReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateACCReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_ACC, RegInfo, S, E, Parser);
}
/// Create a register that is definitely an MSA128.
/// This is typically only used for named registers such as $w0.
static MipsOperand *CreateMSA128Reg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateMSA128Reg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_MSA128, RegInfo, S, E, Parser);
}
/// Create a register that is definitely an MSACtrl.
/// This is typically only used for named registers such as $msaaccess.
static MipsOperand *CreateMSACtrlReg(unsigned Index,
const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
static std::unique_ptr<MipsOperand>
CreateMSACtrlReg(unsigned Index, const MCRegisterInfo *RegInfo, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
return CreateReg(Index, RegKind_MSACtrl, RegInfo, S, E, Parser);
}
static MipsOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
MipsOperand *Op = new MipsOperand(k_Immediate, Parser);
static std::unique_ptr<MipsOperand>
CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_Immediate, Parser);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static MipsOperand *CreateMem(MipsOperand *Base, const MCExpr *Off, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
MipsOperand *Op = new MipsOperand(k_Memory, Parser);
Op->Mem.Base = Base;
static std::unique_ptr<MipsOperand>
CreateMem(std::unique_ptr<MipsOperand> Base, const MCExpr *Off, SMLoc S,
SMLoc E, MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_Memory, Parser);
Op->Mem.Base = Base.release();
Op->Mem.Off = Off;
Op->StartLoc = S;
Op->EndLoc = E;
@ -1164,10 +1157,11 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
TempInst.clear();
}
bool MipsAsmParser::MatchAndEmitInstruction(
SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand *> &Operands, MCStreamer &Out,
unsigned &ErrorInfo, bool MatchingInlineAsm) {
bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
SmallVector<MCInst, 8> Instructions;
unsigned MatchResult =
@ -1192,7 +1186,7 @@ bool MipsAsmParser::MatchAndEmitInstruction(
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = ((MipsOperand *)Operands[ErrorInfo])->getStartLoc();
ErrorLoc = ((MipsOperand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
@ -1378,9 +1372,7 @@ int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
return getReg(RegClass, RegNum);
}
bool
MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands,
StringRef Mnemonic) {
bool MipsAsmParser::ParseOperand(OperandVector &Operands, StringRef Mnemonic) {
DEBUG(dbgs() << "ParseOperand\n");
// Check if the current operand has a custom associated parser, if so, try to
@ -1578,11 +1570,11 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
SmallVector<MCParsedAsmOperand *, 1> Operands;
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
OperandMatchResultTy ResTy = ParseAnyRegister(Operands);
if (ResTy == MatchOperand_Success) {
assert(Operands.size() == 1);
MipsOperand &Operand = *static_cast<MipsOperand *>(Operands.front());
MipsOperand &Operand = static_cast<MipsOperand &>(*Operands.front());
StartLoc = Operand.getStartLoc();
EndLoc = Operand.getEndLoc();
@ -1595,8 +1587,6 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
}
delete &Operand;
return (RegNo == (unsigned)-1);
}
@ -1632,8 +1622,8 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
return Result;
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseMemOperand(OperandVector &Operands) {
DEBUG(dbgs() << "parseMemOperand\n");
const MCExpr *IdVal = nullptr;
SMLoc S;
@ -1653,8 +1643,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
const AsmToken &Tok = Parser.getTok(); // Get the next token.
if (Tok.isNot(AsmToken::LParen)) {
MipsOperand *Mnemonic = static_cast<MipsOperand *>(Operands[0]);
if (Mnemonic->getToken() == "la") {
MipsOperand &Mnemonic = static_cast<MipsOperand &>(*Operands[0]);
if (Mnemonic.getToken() == "la") {
SMLoc E =
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
@ -1666,9 +1656,10 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
// Zero register assumed, add a memory operand with ZERO as its base.
// "Base" will be managed by k_Memory.
MipsOperand *Base = MipsOperand::CreateGPRReg(
0, getContext().getRegisterInfo(), S, E, *this);
Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
auto Base = MipsOperand::CreateGPRReg(0, getContext().getRegisterInfo(),
S, E, *this);
Operands.push_back(
MipsOperand::CreateMem(std::move(Base), IdVal, S, E, *this));
return MatchOperand_Success;
}
Error(Parser.getTok().getLoc(), "'(' expected");
@ -1695,7 +1686,8 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
IdVal = MCConstantExpr::Create(0, getContext());
// Replace the register operand with the memory operand.
MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
std::unique_ptr<MipsOperand> op(
static_cast<MipsOperand *>(Operands.back().release()));
// Remove the register from the operands.
// "op" will be managed by k_Memory.
Operands.pop_back();
@ -1709,12 +1701,11 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
getContext());
}
Operands.push_back(MipsOperand::CreateMem(op, IdVal, S, E, *this));
Operands.push_back(MipsOperand::CreateMem(std::move(op), IdVal, S, E, *this));
return MatchOperand_Success;
}
bool MipsAsmParser::searchSymbolAlias(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
if (Sym) {
@ -1740,9 +1731,8 @@ bool MipsAsmParser::searchSymbolAlias(
} else if (Expr->getKind() == MCExpr::Constant) {
Parser.Lex();
const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
MipsOperand *op =
MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this);
Operands.push_back(op);
Operands.push_back(
MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
return true;
}
}
@ -1750,9 +1740,9 @@ bool MipsAsmParser::searchSymbolAlias(
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
SmallVectorImpl<MCParsedAsmOperand *> &Operands, StringRef Identifier,
SMLoc S) {
MipsAsmParser::MatchAnyRegisterNameWithoutDollar(OperandVector &Operands,
StringRef Identifier,
SMLoc S) {
int Index = matchCPURegisterName(Identifier);
if (Index != -1) {
Operands.push_back(MipsOperand::CreateGPRReg(
@ -1799,8 +1789,7 @@ MipsAsmParser::MatchAnyRegisterNameWithoutDollar(
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::MatchAnyRegisterWithoutDollar(
SmallVectorImpl<MCParsedAsmOperand *> &Operands, SMLoc S) {
MipsAsmParser::MatchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) {
auto Token = Parser.getLexer().peekTok(false);
if (Token.is(AsmToken::Identifier)) {
@ -1822,8 +1811,8 @@ MipsAsmParser::MatchAnyRegisterWithoutDollar(
return MatchOperand_NoMatch;
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::ParseAnyRegister(OperandVector &Operands) {
DEBUG(dbgs() << "ParseAnyRegister\n");
auto Token = Parser.getTok();
@ -1850,7 +1839,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseAnyRegister(
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::ParseImm(OperandVector &Operands) {
switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
@ -1872,8 +1861,8 @@ MipsAsmParser::ParseImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
return MatchOperand_Success;
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::ParseJumpTarget(OperandVector &Operands) {
DEBUG(dbgs() << "ParseJumpTarget\n");
SMLoc S = getLexer().getLoc();
@ -1899,7 +1888,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::ParseJumpTarget(
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::parseInvNum(OperandVector &Operands) {
const MCExpr *IdVal;
// If the first token is '$' we may have register operand.
if (Parser.getTok().is(AsmToken::Dollar))
@ -1917,7 +1906,7 @@ MipsAsmParser::parseInvNum(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::ParseLSAImm(SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
MipsAsmParser::ParseLSAImm(OperandVector &Operands) {
switch (getLexer().getKind()) {
default:
return MatchOperand_NoMatch;
@ -1996,8 +1985,7 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
/// ::= '(', register, ')'
/// handle it before we iterate so we don't get tripped up by the lack of
/// a comma.
bool MipsAsmParser::ParseParenSuffix(
StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
bool MipsAsmParser::ParseParenSuffix(StringRef Name, OperandVector &Operands) {
if (getLexer().is(AsmToken::LParen)) {
Operands.push_back(
MipsOperand::CreateToken("(", getLexer().getLoc(), *this));
@ -2025,8 +2013,8 @@ bool MipsAsmParser::ParseParenSuffix(
/// ::= '[', integer, ']'
/// handle it before we iterate so we don't get tripped up by the lack of
/// a comma.
bool MipsAsmParser::ParseBracketSuffix(
StringRef Name, SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
bool MipsAsmParser::ParseBracketSuffix(StringRef Name,
OperandVector &Operands) {
if (getLexer().is(AsmToken::LBrac)) {
Operands.push_back(
MipsOperand::CreateToken("[", getLexer().getLoc(), *this));
@ -2048,9 +2036,8 @@ bool MipsAsmParser::ParseBracketSuffix(
return false;
}
bool MipsAsmParser::ParseInstruction(
ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
DEBUG(dbgs() << "ParseInstruction\n");
// Check if we have valid mnemonic
if (!mnemonicIsValid(Name, 0)) {
@ -2332,21 +2319,20 @@ bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
// FIXME: Warn if cpload is used in Mips16 mode.
SmallVector<MCParsedAsmOperand *, 1> Reg;
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Reg;
OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
reportParseError("expected register containing function address");
return false;
}
MipsOperand *RegOpnd = static_cast<MipsOperand *>(Reg[0]);
if (!RegOpnd->isGPRAsmReg()) {
reportParseError(RegOpnd->getStartLoc(), "invalid register");
MipsOperand &RegOpnd = static_cast<MipsOperand &>(*Reg[0]);
if (!RegOpnd.isGPRAsmReg()) {
reportParseError(RegOpnd.getStartLoc(), "invalid register");
return false;
}
getTargetStreamer().emitDirectiveCpload(RegOpnd->getGPR32Reg());
delete RegOpnd;
getTargetStreamer().emitDirectiveCpload(RegOpnd.getGPR32Reg());
return false;
}

View File

@ -238,7 +238,7 @@ class PPCAsmParser : public MCTargetAsmParser {
bool ParseExpression(const MCExpr *&EVal);
bool ParseDarwinExpression(const MCExpr *&EVal);
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
bool ParseOperand(OperandVector &Operands);
bool ParseDirectiveWord(unsigned Size, SMLoc L);
bool ParseDirectiveTC(unsigned Size, SMLoc L);
@ -246,12 +246,11 @@ class PPCAsmParser : public MCTargetAsmParser {
bool ParseDarwinDirectiveMachine(SMLoc L);
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) override;
void ProcessInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
void ProcessInstruction(MCInst &Inst, const OperandVector &Ops);
/// @name Auto-generated Match Functions
/// {
@ -276,13 +275,12 @@ public:
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
bool ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
bool ParseDirective(AsmToken DirectiveID) override;
unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
const MCExpr *applyModifierToExpr(const MCExpr *E,
@ -548,8 +546,9 @@ public:
void print(raw_ostream &OS) const override;
static PPCOperand *CreateToken(StringRef Str, SMLoc S, bool IsPPC64) {
PPCOperand *Op = new PPCOperand(Token);
static std::unique_ptr<PPCOperand> CreateToken(StringRef Str, SMLoc S,
bool IsPPC64) {
auto Op = make_unique<PPCOperand>(Token);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@ -558,22 +557,27 @@ public:
return Op;
}
static PPCOperand *CreateTokenWithStringCopy(StringRef Str, SMLoc S,
bool IsPPC64) {
static std::unique_ptr<PPCOperand>
CreateTokenWithStringCopy(StringRef Str, SMLoc S, bool IsPPC64) {
// Allocate extra memory for the string and copy it.
// FIXME: This is incorrect, Operands are owned by unique_ptr with a default
// deleter which will destroy them by simply using "delete", not correctly
// calling operator delete on this extra memory after calling the dtor
// explicitly.
void *Mem = ::operator new(sizeof(PPCOperand) + Str.size());
PPCOperand *Op = new (Mem) PPCOperand(Token);
Op->Tok.Data = (const char *)(Op + 1);
std::unique_ptr<PPCOperand> Op(new (Mem) PPCOperand(Token));
Op->Tok.Data = (const char *)(Op.get() + 1);
Op->Tok.Length = Str.size();
std::memcpy((char *)(Op + 1), Str.data(), Str.size());
std::memcpy((void *)Op->Tok.Data, Str.data(), Str.size());
Op->StartLoc = S;
Op->EndLoc = S;
Op->IsPPC64 = IsPPC64;
return Op;
}
static PPCOperand *CreateImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64) {
PPCOperand *Op = new PPCOperand(Immediate);
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
bool IsPPC64) {
auto Op = make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
@ -581,9 +585,9 @@ public:
return Op;
}
static PPCOperand *CreateExpr(const MCExpr *Val,
SMLoc S, SMLoc E, bool IsPPC64) {
PPCOperand *Op = new PPCOperand(Expression);
static std::unique_ptr<PPCOperand> CreateExpr(const MCExpr *Val, SMLoc S,
SMLoc E, bool IsPPC64) {
auto Op = make_unique<PPCOperand>(Expression);
Op->Expr.Val = Val;
Op->Expr.CRVal = EvaluateCRExpr(Val);
Op->StartLoc = S;
@ -592,9 +596,9 @@ public:
return Op;
}
static PPCOperand *CreateTLSReg(const MCSymbolRefExpr *Sym,
SMLoc S, SMLoc E, bool IsPPC64) {
PPCOperand *Op = new PPCOperand(TLSRegister);
static std::unique_ptr<PPCOperand>
CreateTLSReg(const MCSymbolRefExpr *Sym, SMLoc S, SMLoc E, bool IsPPC64) {
auto Op = make_unique<PPCOperand>(TLSRegister);
Op->TLSReg.Sym = Sym;
Op->StartLoc = S;
Op->EndLoc = E;
@ -602,8 +606,8 @@ public:
return Op;
}
static PPCOperand *CreateFromMCExpr(const MCExpr *Val,
SMLoc S, SMLoc E, bool IsPPC64) {
static std::unique_ptr<PPCOperand>
CreateFromMCExpr(const MCExpr *Val, SMLoc S, SMLoc E, bool IsPPC64) {
if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val))
return CreateImm(CE->getValue(), S, E, IsPPC64);
@ -634,10 +638,8 @@ void PPCOperand::print(raw_ostream &OS) const {
}
}
void PPCAsmParser::
ProcessInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
void PPCAsmParser::ProcessInstruction(MCInst &Inst,
const OperandVector &Operands) {
int Opcode = Inst.getOpcode();
switch (Opcode) {
case PPC::LAx: {
@ -917,11 +919,10 @@ ProcessInstruction(MCInst &Inst,
}
}
bool PPCAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
@ -942,7 +943,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = ((PPCOperand*)Operands[ErrorInfo])->getStartLoc();
ErrorLoc = ((PPCOperand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
}
@ -1216,12 +1217,10 @@ ParseDarwinExpression(const MCExpr *&EVal) {
/// ParseOperand
/// This handles registers in the form 'NN', '%rNN' for ELF platforms and
/// rNN for MachO.
bool PPCAsmParser::
ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
bool PPCAsmParser::ParseOperand(OperandVector &Operands) {
SMLoc S = Parser.getTok().getLoc();
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
const MCExpr *EVal;
PPCOperand *Op;
// Attempt to parse the next token as an immediate
switch (getLexer().getKind()) {
@ -1233,8 +1232,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
int64_t IntVal;
if (!MatchRegisterName(Parser.getTok(), RegNo, IntVal)) {
Parser.Lex(); // Eat the identifier token.
Op = PPCOperand::CreateImm(IntVal, S, E, isPPC64());
Operands.push_back(Op);
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
return false;
}
return Error(S, "invalid register name");
@ -1249,8 +1247,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
int64_t IntVal;
if (!MatchRegisterName(Parser.getTok(), RegNo, IntVal)) {
Parser.Lex(); // Eat the identifier token.
Op = PPCOperand::CreateImm(IntVal, S, E, isPPC64());
Operands.push_back(Op);
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
return false;
}
}
@ -1272,8 +1269,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
}
// Push the parsed operand into the list of operands
Op = PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64());
Operands.push_back(Op);
Operands.push_back(PPCOperand::CreateFromMCExpr(EVal, S, E, isPPC64()));
// Check whether this is a TLS call expression
bool TLSCall = false;
@ -1292,8 +1288,7 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
E = Parser.getTok().getLoc();
Parser.Lex(); // Eat the ')'.
Op = PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64());
Operands.push_back(Op);
Operands.push_back(PPCOperand::CreateFromMCExpr(TLSSym, S, E, isPPC64()));
}
// Otherwise, check for D-form memory operands
@ -1340,17 +1335,15 @@ ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
E = Parser.getTok().getLoc();
Parser.Lex(); // Eat the ')'.
Op = PPCOperand::CreateImm(IntVal, S, E, isPPC64());
Operands.push_back(Op);
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
}
return false;
}
/// Parse an instruction mnemonic followed by its operands.
bool PPCAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
// The first operand is the token for the instruction name.
// If the next character is a '+' or '-', we need to add it to the
// instruction name, to match what TableGen is doing.
@ -1554,7 +1547,7 @@ extern "C" void LLVMInitializePowerPCAsmParser() {
// Define this matcher function after the auto-generated include so we
// have the match class enum definitions.
unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
unsigned Kind) {
// If the kind is a token for a literal immediate, check if our asm
// operand matches. This is for InstAliases which have a fixed-value
@ -1568,8 +1561,8 @@ unsigned PPCAsmParser::validateTargetOperandClass(MCParsedAsmOperand *AsmOp,
default: return Match_InvalidOperand;
}
PPCOperand *Op = static_cast<PPCOperand*>(AsmOp);
if (Op->isImm() && Op->getImm() == ImmVal)
PPCOperand &Op = static_cast<PPCOperand &>(AsmOp);
if (Op.isImm() && Op.getImm() == ImmVal)
return Match_Success;
return Match_InvalidOperand;

View File

@ -47,31 +47,27 @@ class SparcAsmParser : public MCTargetAsmParser {
// public interface of the MCTargetAsmParser.
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) override;
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) override;
SMLoc NameLoc, OperandVector &Operands) override;
bool ParseDirective(AsmToken DirectiveID) override;
unsigned validateTargetOperandClass(MCParsedAsmOperand *Op,
unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
unsigned Kind) override;
// Custom parse functions for Sparc specific operands.
OperandMatchResultTy
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy parseMEMOperand(OperandVector &Operands);
OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Name);
OperandMatchResultTy
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Name);
parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Operand,
bool isCall = false);
OperandMatchResultTy
parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false);
OperandMatchResultTy
parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy parseBranchModifiers(OperandVector &Operands);
// returns true if Tok is matched to a register and returns register in RegNo.
bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
@ -153,8 +149,6 @@ private:
SMLoc StartLoc, EndLoc;
SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
struct Token {
const char *Data;
unsigned Length;
@ -182,6 +176,8 @@ private:
struct MemOp Mem;
};
public:
SparcOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
bool isToken() const override { return Kind == k_Token; }
bool isReg() const override { return Kind == k_Register; }
bool isImm() const override { return Kind == k_Immediate; }
@ -291,8 +287,8 @@ public:
addExpr(Inst, Expr);
}
static SparcOperand *CreateToken(StringRef Str, SMLoc S) {
SparcOperand *Op = new SparcOperand(k_Token);
static std::unique_ptr<SparcOperand> CreateToken(StringRef Str, SMLoc S) {
auto Op = make_unique<SparcOperand>(k_Token);
Op->Tok.Data = Str.data();
Op->Tok.Length = Str.size();
Op->StartLoc = S;
@ -300,10 +296,9 @@ public:
return Op;
}
static SparcOperand *CreateReg(unsigned RegNum,
unsigned Kind,
SMLoc S, SMLoc E) {
SparcOperand *Op = new SparcOperand(k_Register);
static std::unique_ptr<SparcOperand> CreateReg(unsigned RegNum, unsigned Kind,
SMLoc S, SMLoc E) {
auto Op = make_unique<SparcOperand>(k_Register);
Op->Reg.RegNum = RegNum;
Op->Reg.Kind = (SparcOperand::RegisterKind)Kind;
Op->StartLoc = S;
@ -311,49 +306,51 @@ public:
return Op;
}
static SparcOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
SparcOperand *Op = new SparcOperand(k_Immediate);
static std::unique_ptr<SparcOperand> CreateImm(const MCExpr *Val, SMLoc S,
SMLoc E) {
auto Op = make_unique<SparcOperand>(k_Immediate);
Op->Imm.Val = Val;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static SparcOperand *MorphToDoubleReg(SparcOperand *Op) {
unsigned Reg = Op->getReg();
assert(Op->Reg.Kind == rk_FloatReg);
static bool MorphToDoubleReg(SparcOperand &Op) {
unsigned Reg = Op.getReg();
assert(Op.Reg.Kind == rk_FloatReg);
unsigned regIdx = Reg - Sparc::F0;
if (regIdx % 2 || regIdx > 31)
return nullptr;
Op->Reg.RegNum = DoubleRegs[regIdx / 2];
Op->Reg.Kind = rk_DoubleReg;
return Op;
return false;
Op.Reg.RegNum = DoubleRegs[regIdx / 2];
Op.Reg.Kind = rk_DoubleReg;
return true;
}
static SparcOperand *MorphToQuadReg(SparcOperand *Op) {
unsigned Reg = Op->getReg();
static bool MorphToQuadReg(SparcOperand &Op) {
unsigned Reg = Op.getReg();
unsigned regIdx = 0;
switch (Op->Reg.Kind) {
switch (Op.Reg.Kind) {
default: assert(0 && "Unexpected register kind!");
case rk_FloatReg:
regIdx = Reg - Sparc::F0;
if (regIdx % 4 || regIdx > 31)
return nullptr;
return false;
Reg = QuadFPRegs[regIdx / 4];
break;
case rk_DoubleReg:
regIdx = Reg - Sparc::D0;
if (regIdx % 2 || regIdx > 31)
return nullptr;
return false;
Reg = QuadFPRegs[regIdx / 2];
break;
}
Op->Reg.RegNum = Reg;
Op->Reg.Kind = rk_QuadReg;
return Op;
Op.Reg.RegNum = Reg;
Op.Reg.Kind = rk_QuadReg;
return true;
}
static SparcOperand *MorphToMEMrr(unsigned Base, SparcOperand *Op) {
static std::unique_ptr<SparcOperand>
MorphToMEMrr(unsigned Base, std::unique_ptr<SparcOperand> Op) {
unsigned offsetReg = Op->getReg();
Op->Kind = k_MemoryReg;
Op->Mem.Base = Base;
@ -362,10 +359,9 @@ public:
return Op;
}
static SparcOperand *CreateMEMri(unsigned Base,
const MCExpr *Off,
SMLoc S, SMLoc E) {
SparcOperand *Op = new SparcOperand(k_MemoryImm);
static std::unique_ptr<SparcOperand>
CreateMEMri(unsigned Base, const MCExpr *Off, SMLoc S, SMLoc E) {
auto Op = make_unique<SparcOperand>(k_MemoryImm);
Op->Mem.Base = Base;
Op->Mem.OffsetReg = 0;
Op->Mem.Off = Off;
@ -374,7 +370,8 @@ public:
return Op;
}
static SparcOperand *MorphToMEMri(unsigned Base, SparcOperand *Op) {
static std::unique_ptr<SparcOperand>
MorphToMEMri(unsigned Base, std::unique_ptr<SparcOperand> Op) {
const MCExpr *Imm = Op->getImm();
Op->Kind = k_MemoryImm;
Op->Mem.Base = Base;
@ -386,11 +383,11 @@ public:
} // end namespace
bool SparcAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
bool SparcAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
SmallVector<MCInst, 8> Instructions;
unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
@ -415,7 +412,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = ((SparcOperand*) Operands[ErrorInfo])->getStartLoc();
ErrorLoc = ((SparcOperand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
@ -450,11 +447,9 @@ ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc)
static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features,
unsigned VariantID);
bool SparcAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands)
{
bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
// First operand in MCInst is instruction mnemonic.
Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
@ -548,9 +543,8 @@ bool SparcAsmParser:: parseDirectiveWord(unsigned Size, SMLoc L) {
return false;
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
{
SparcAsmParser::OperandMatchResultTy
SparcAsmParser::parseMEMOperand(OperandVector &Operands) {
SMLoc S, E;
unsigned BaseReg = 0;
@ -575,23 +569,20 @@ parseMEMOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands)
break;
}
SparcOperand *Offset = nullptr;
std::unique_ptr<SparcOperand> Offset;
OperandMatchResultTy ResTy = parseSparcAsmOperand(Offset);
if (ResTy != MatchOperand_Success || !Offset)
return MatchOperand_NoMatch;
Offset = (Offset->isImm()
? SparcOperand::MorphToMEMri(BaseReg, Offset)
: SparcOperand::MorphToMEMrr(BaseReg, Offset));
Operands.push_back(
Offset->isImm() ? SparcOperand::MorphToMEMri(BaseReg, std::move(Offset))
: SparcOperand::MorphToMEMrr(BaseReg, std::move(Offset)));
Operands.push_back(Offset);
return MatchOperand_Success;
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic)
{
SparcAsmParser::OperandMatchResultTy
SparcAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
@ -637,21 +628,21 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
return MatchOperand_Success;
}
SparcOperand *Op = nullptr;
std::unique_ptr<SparcOperand> Op;
ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call"));
if (ResTy != MatchOperand_Success || !Op)
return MatchOperand_ParseFail;
// Push the parsed operand into the list of operands
Operands.push_back(Op);
Operands.push_back(std::move(Op));
return MatchOperand_Success;
}
SparcAsmParser::OperandMatchResultTy
SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall)
{
SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op,
bool isCall) {
SMLoc S = Parser.getTok().getLoc();
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
@ -718,8 +709,8 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall)
return (Op) ? MatchOperand_Success : MatchOperand_ParseFail;
}
SparcAsmParser::OperandMatchResultTy SparcAsmParser::
parseBranchModifiers(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SparcAsmParser::OperandMatchResultTy
SparcAsmParser::parseBranchModifiers(OperandVector &Operands) {
// parse (,a|,pn|,pt)+
@ -928,18 +919,14 @@ extern "C" void LLVMInitializeSparcAsmParser() {
#define GET_MATCHER_IMPLEMENTATION
#include "SparcGenAsmMatcher.inc"
unsigned SparcAsmParser::
validateTargetOperandClass(MCParsedAsmOperand *GOp,
unsigned Kind)
{
SparcOperand *Op = (SparcOperand*)GOp;
if (Op->isFloatOrDoubleReg()) {
unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
unsigned Kind) {
SparcOperand &Op = (SparcOperand &)GOp;
if (Op.isFloatOrDoubleReg()) {
switch (Kind) {
default: break;
case MCK_DFPRegs:
if (!Op->isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
if (!Op.isFloatReg() || SparcOperand::MorphToDoubleReg(Op))
return MCTargetAsmParser::Match_Success;
break;
case MCK_QFPRegs:

View File

@ -104,10 +104,6 @@ private:
MemOp Mem;
};
SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc)
: Kind(kind), StartLoc(startLoc), EndLoc(endLoc)
{}
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
if (!Expr)
@ -119,40 +115,44 @@ private:
}
public:
SystemZOperand(OperandKind kind, SMLoc startLoc, SMLoc endLoc)
: Kind(kind), StartLoc(startLoc), EndLoc(endLoc) {}
// Create particular kinds of operand.
static SystemZOperand *createInvalid(SMLoc StartLoc, SMLoc EndLoc) {
return new SystemZOperand(KindInvalid, StartLoc, EndLoc);
static std::unique_ptr<SystemZOperand> createInvalid(SMLoc StartLoc,
SMLoc EndLoc) {
return make_unique<SystemZOperand>(KindInvalid, StartLoc, EndLoc);
}
static SystemZOperand *createToken(StringRef Str, SMLoc Loc) {
SystemZOperand *Op = new SystemZOperand(KindToken, Loc, Loc);
static std::unique_ptr<SystemZOperand> createToken(StringRef Str, SMLoc Loc) {
auto Op = make_unique<SystemZOperand>(KindToken, Loc, Loc);
Op->Token.Data = Str.data();
Op->Token.Length = Str.size();
return Op;
}
static SystemZOperand *createReg(RegisterKind Kind, unsigned Num,
SMLoc StartLoc, SMLoc EndLoc) {
SystemZOperand *Op = new SystemZOperand(KindReg, StartLoc, EndLoc);
static std::unique_ptr<SystemZOperand>
createReg(RegisterKind Kind, unsigned Num, SMLoc StartLoc, SMLoc EndLoc) {
auto Op = make_unique<SystemZOperand>(KindReg, StartLoc, EndLoc);
Op->Reg.Kind = Kind;
Op->Reg.Num = Num;
return Op;
}
static SystemZOperand *createAccessReg(unsigned Num, SMLoc StartLoc,
SMLoc EndLoc) {
SystemZOperand *Op = new SystemZOperand(KindAccessReg, StartLoc, EndLoc);
static std::unique_ptr<SystemZOperand>
createAccessReg(unsigned Num, SMLoc StartLoc, SMLoc EndLoc) {
auto Op = make_unique<SystemZOperand>(KindAccessReg, StartLoc, EndLoc);
Op->AccessReg = Num;
return Op;
}
static SystemZOperand *createImm(const MCExpr *Expr, SMLoc StartLoc,
SMLoc EndLoc) {
SystemZOperand *Op = new SystemZOperand(KindImm, StartLoc, EndLoc);
static std::unique_ptr<SystemZOperand>
createImm(const MCExpr *Expr, SMLoc StartLoc, SMLoc EndLoc) {
auto Op = make_unique<SystemZOperand>(KindImm, StartLoc, EndLoc);
Op->Imm = Expr;
return Op;
}
static SystemZOperand *createMem(RegisterKind RegKind, unsigned Base,
const MCExpr *Disp, unsigned Index,
const MCExpr *Length, SMLoc StartLoc,
SMLoc EndLoc) {
SystemZOperand *Op = new SystemZOperand(KindMem, StartLoc, EndLoc);
static std::unique_ptr<SystemZOperand>
createMem(RegisterKind RegKind, unsigned Base, const MCExpr *Disp,
unsigned Index, const MCExpr *Length, SMLoc StartLoc,
SMLoc EndLoc) {
auto Op = make_unique<SystemZOperand>(KindMem, StartLoc, EndLoc);
Op->Mem.RegKind = RegKind;
Op->Mem.Base = Base;
Op->Mem.Index = Index;
@ -313,21 +313,19 @@ private:
bool parseRegister(Register &Reg, RegisterGroup Group, const unsigned *Regs,
bool IsAddress = false);
OperandMatchResultTy
parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
RegisterGroup Group, const unsigned *Regs, RegisterKind Kind);
OperandMatchResultTy parseRegister(OperandVector &Operands,
RegisterGroup Group, const unsigned *Regs,
RegisterKind Kind);
bool parseAddress(unsigned &Base, const MCExpr *&Disp,
unsigned &Index, const MCExpr *&Length,
const unsigned *Regs, RegisterKind RegKind);
OperandMatchResultTy
parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
const unsigned *Regs, RegisterKind RegKind,
MemoryKind MemKind);
OperandMatchResultTy parseAddress(OperandVector &Operands,
const unsigned *Regs, RegisterKind RegKind,
MemoryKind MemKind);
bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic);
bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
public:
SystemZAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
@ -343,87 +341,66 @@ public:
// Override MCTargetAsmParser.
bool ParseDirective(AsmToken DirectiveID) override;
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands)
override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) override;
// Used by the TableGen code to parse particular operand types.
OperandMatchResultTy
parseGR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseGR32(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, GR32Reg);
}
OperandMatchResultTy
parseGRH32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseGRH32(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GRH32Regs, GRH32Reg);
}
OperandMatchResultTy
parseGRX32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseGRX32(OperandVector &Operands) {
llvm_unreachable("GRX32 should only be used for pseudo instructions");
}
OperandMatchResultTy
parseGR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseGR64(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, GR64Reg);
}
OperandMatchResultTy
parseGR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseGR128(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GR128Regs, GR128Reg);
}
OperandMatchResultTy
parseADDR32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseADDR32(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GR32Regs, ADDR32Reg);
}
OperandMatchResultTy
parseADDR64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseADDR64(OperandVector &Operands) {
return parseRegister(Operands, RegGR, SystemZMC::GR64Regs, ADDR64Reg);
}
OperandMatchResultTy
parseADDR128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseADDR128(OperandVector &Operands) {
llvm_unreachable("Shouldn't be used as an operand");
}
OperandMatchResultTy
parseFP32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseFP32(OperandVector &Operands) {
return parseRegister(Operands, RegFP, SystemZMC::FP32Regs, FP32Reg);
}
OperandMatchResultTy
parseFP64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseFP64(OperandVector &Operands) {
return parseRegister(Operands, RegFP, SystemZMC::FP64Regs, FP64Reg);
}
OperandMatchResultTy
parseFP128(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseFP128(OperandVector &Operands) {
return parseRegister(Operands, RegFP, SystemZMC::FP128Regs, FP128Reg);
}
OperandMatchResultTy
parseBDAddr32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseBDAddr32(OperandVector &Operands) {
return parseAddress(Operands, SystemZMC::GR32Regs, ADDR32Reg, BDMem);
}
OperandMatchResultTy
parseBDAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseBDAddr64(OperandVector &Operands) {
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDMem);
}
OperandMatchResultTy
parseBDXAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseBDXAddr64(OperandVector &Operands) {
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDXMem);
}
OperandMatchResultTy
parseBDLAddr64(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseBDLAddr64(OperandVector &Operands) {
return parseAddress(Operands, SystemZMC::GR64Regs, ADDR64Reg, BDLMem);
}
OperandMatchResultTy
parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
OperandMatchResultTy
parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int64_t MinVal, int64_t MaxVal);
OperandMatchResultTy
parsePCRel16(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parseAccessReg(OperandVector &Operands);
OperandMatchResultTy parsePCRel(OperandVector &Operands, int64_t MinVal,
int64_t MaxVal);
OperandMatchResultTy parsePCRel16(OperandVector &Operands) {
return parsePCRel(Operands, -(1LL << 16), (1LL << 16) - 1);
}
OperandMatchResultTy
parsePCRel32(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OperandMatchResultTy parsePCRel32(OperandVector &Operands) {
return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1);
}
};
@ -497,9 +474,8 @@ bool SystemZAsmParser::parseRegister(Register &Reg, RegisterGroup Group,
// Parse a register and add it to Operands. The other arguments are as above.
SystemZAsmParser::OperandMatchResultTy
SystemZAsmParser::parseRegister(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
RegisterGroup Group, const unsigned *Regs,
RegisterKind Kind) {
SystemZAsmParser::parseRegister(OperandVector &Operands, RegisterGroup Group,
const unsigned *Regs, RegisterKind Kind) {
if (Parser.getTok().isNot(AsmToken::Percent))
return MatchOperand_NoMatch;
@ -566,9 +542,8 @@ bool SystemZAsmParser::parseAddress(unsigned &Base, const MCExpr *&Disp,
// Parse a memory operand and add it to Operands. The other arguments
// are as above.
SystemZAsmParser::OperandMatchResultTy
SystemZAsmParser::parseAddress(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
const unsigned *Regs, RegisterKind RegKind,
MemoryKind MemKind) {
SystemZAsmParser::parseAddress(OperandVector &Operands, const unsigned *Regs,
RegisterKind RegKind, MemoryKind MemKind) {
SMLoc StartLoc = Parser.getTok().getLoc();
unsigned Base, Index;
const MCExpr *Disp;
@ -622,9 +597,9 @@ bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
return false;
}
bool SystemZAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
Operands.push_back(SystemZOperand::createToken(Name, NameLoc));
// Read the remaining operands.
@ -655,9 +630,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
return false;
}
bool SystemZAsmParser::
parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
StringRef Mnemonic) {
bool SystemZAsmParser::parseOperand(OperandVector &Operands,
StringRef Mnemonic) {
// Check if the current operand has a custom associated parser, if so, try to
// custom parse the operand, or fallback to the general approach.
OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
@ -700,11 +674,11 @@ parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
return false;
}
bool SystemZAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
bool SystemZAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
unsigned MatchResult;
@ -739,7 +713,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
ErrorLoc = ((SystemZOperand*)Operands[ErrorInfo])->getStartLoc();
ErrorLoc = ((SystemZOperand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc())
ErrorLoc = IDLoc;
}
@ -753,8 +727,8 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
llvm_unreachable("Unexpected match type");
}
SystemZAsmParser::OperandMatchResultTy SystemZAsmParser::
parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
SystemZAsmParser::OperandMatchResultTy
SystemZAsmParser::parseAccessReg(OperandVector &Operands) {
if (Parser.getTok().isNot(AsmToken::Percent))
return MatchOperand_NoMatch;
@ -768,9 +742,9 @@ parseAccessReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_Success;
}
SystemZAsmParser::OperandMatchResultTy SystemZAsmParser::
parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
int64_t MinVal, int64_t MaxVal) {
SystemZAsmParser::OperandMatchResultTy
SystemZAsmParser::parsePCRel(OperandVector &Operands, int64_t MinVal,
int64_t MaxVal) {
MCContext &Ctx = getContext();
MCStreamer &Out = getStreamer();
const MCExpr *Expr;

View File

@ -20,6 +20,7 @@
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/CommandLine.h"
@ -46,21 +47,21 @@ public:
virtual ~X86AddressSanitizer() {}
// X86AsmInstrumentation implementation:
virtual void InstrumentInstruction(
const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) override {
virtual void InstrumentInstruction(const MCInst &Inst,
OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) override {
InstrumentMOV(Inst, Operands, Ctx, MII, Out);
}
// Should be implemented differently in x86_32 and x86_64 subclasses.
virtual void InstrumentMemOperandImpl(X86Operand *Op, unsigned AccessSize,
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) = 0;
void InstrumentMemOperand(MCParsedAsmOperand *Op, unsigned AccessSize,
void InstrumentMemOperand(MCParsedAsmOperand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx, MCStreamer &Out);
void InstrumentMOV(const MCInst &Inst,
SmallVectorImpl<MCParsedAsmOperand *> &Operands,
void InstrumentMOV(const MCInst &Inst, OperandVector &Operands,
MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
void EmitInstruction(MCStreamer &Out, const MCInst &Inst) {
Out.EmitInstruction(Inst, STI);
@ -70,24 +71,26 @@ protected:
const MCSubtargetInfo &STI;
};
void X86AddressSanitizer::InstrumentMemOperand(
MCParsedAsmOperand *Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
assert(Op && Op->isMem() && "Op should be a memory operand.");
void X86AddressSanitizer::InstrumentMemOperand(MCParsedAsmOperand &Op,
unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
assert(Op.isMem() && "Op should be a memory operand.");
assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 &&
"AccessSize should be a power of two, less or equal than 16.");
X86Operand *MemOp = static_cast<X86Operand *>(Op);
X86Operand &MemOp = static_cast<X86Operand &>(Op);
// FIXME: get rid of this limitation.
if (IsStackReg(MemOp->getMemBaseReg()) || IsStackReg(MemOp->getMemIndexReg()))
if (IsStackReg(MemOp.getMemBaseReg()) || IsStackReg(MemOp.getMemIndexReg()))
return;
InstrumentMemOperandImpl(MemOp, AccessSize, IsWrite, Ctx, Out);
}
void X86AddressSanitizer::InstrumentMOV(
const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) {
void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst,
OperandVector &Operands, MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) {
// Access size in bytes.
unsigned AccessSize = 0;
@ -124,8 +127,9 @@ void X86AddressSanitizer::InstrumentMOV(
const bool IsWrite = MII.get(Inst.getOpcode()).mayStore();
for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) {
MCParsedAsmOperand *Op = Operands[Ix];
if (Op && Op->isMem())
assert(Operands[Ix]);
MCParsedAsmOperand &Op = *Operands[Ix];
if (Op.isMem())
InstrumentMemOperand(Op, AccessSize, IsWrite, Ctx, Out);
}
}
@ -136,21 +140,23 @@ public:
: X86AddressSanitizer(STI) {}
virtual ~X86AddressSanitizer32() {}
virtual void InstrumentMemOperandImpl(X86Operand *Op, unsigned AccessSize,
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
};
void X86AddressSanitizer32::InstrumentMemOperandImpl(
X86Operand *Op, unsigned AccessSize, bool IsWrite, MCContext &Ctx,
MCStreamer &Out) {
void X86AddressSanitizer32::InstrumentMemOperandImpl(X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
MCContext &Ctx,
MCStreamer &Out) {
// FIXME: emit .cfi directives for correct stack unwinding.
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
{
MCInst Inst;
Inst.setOpcode(X86::LEA32r);
Inst.addOperand(MCOperand::CreateReg(X86::EAX));
Op->addMemOperands(Inst, 5);
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(X86::EAX));
@ -171,12 +177,12 @@ public:
: X86AddressSanitizer(STI) {}
virtual ~X86AddressSanitizer64() {}
virtual void InstrumentMemOperandImpl(X86Operand *Op, unsigned AccessSize,
virtual void InstrumentMemOperandImpl(X86Operand &Op, unsigned AccessSize,
bool IsWrite, MCContext &Ctx,
MCStreamer &Out) override;
};
void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand *Op,
void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand &Op,
unsigned AccessSize,
bool IsWrite,
MCContext &Ctx,
@ -201,7 +207,7 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand *Op,
MCInst Inst;
Inst.setOpcode(X86::LEA64r);
Inst.addOperand(MCOperand::CreateReg(X86::RDI));
Op->addMemOperands(Inst, 5);
Op.addMemOperands(Inst, 5);
EmitInstruction(Out, Inst);
}
{
@ -232,9 +238,11 @@ void X86AddressSanitizer64::InstrumentMemOperandImpl(X86Operand *Op,
X86AsmInstrumentation::X86AsmInstrumentation() {}
X86AsmInstrumentation::~X86AsmInstrumentation() {}
void X86AsmInstrumentation::InstrumentInstruction(
const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out) {}
void X86AsmInstrumentation::InstrumentInstruction(const MCInst &Inst,
OperandVector &Operands,
MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out) {}
X86AsmInstrumentation *
CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions,

View File

@ -12,6 +12,8 @@
#include "llvm/ADT/SmallVector.h"
#include <memory>
namespace llvm {
class MCContext;
@ -35,10 +37,9 @@ public:
// Instruments Inst. Should be called just before the original
// instruction is sent to Out.
virtual void InstrumentInstruction(
const MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCContext &Ctx,
const MCInstrInfo &MII,
MCStreamer &Out);
const MCInst &Inst,
SmallVectorImpl<std::unique_ptr<MCParsedAsmOperand>> &Operands,
MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out);
protected:
friend X86AsmInstrumentation *

View File

@ -618,52 +618,52 @@ private:
return Error(L, Msg, Ranges, MatchingInlineAsm);
}
X86Operand *ErrorOperand(SMLoc Loc, StringRef Msg) {
std::nullptr_t ErrorOperand(SMLoc Loc, StringRef Msg) {
Error(Loc, Msg);
return nullptr;
}
X86Operand *DefaultMemSIOperand(SMLoc Loc);
X86Operand *DefaultMemDIOperand(SMLoc Loc);
X86Operand *ParseOperand();
X86Operand *ParseATTOperand();
X86Operand *ParseIntelOperand();
X86Operand *ParseIntelOffsetOfOperator();
std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
std::unique_ptr<X86Operand> ParseOperand();
std::unique_ptr<X86Operand> ParseATTOperand();
std::unique_ptr<X86Operand> ParseIntelOperand();
std::unique_ptr<X86Operand> ParseIntelOffsetOfOperator();
bool ParseIntelDotOperator(const MCExpr *Disp, const MCExpr *&NewDisp);
X86Operand *ParseIntelOperator(unsigned OpKind);
X86Operand *ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size);
X86Operand *ParseIntelMemOperand(int64_t ImmDisp, SMLoc StartLoc,
unsigned Size);
std::unique_ptr<X86Operand> ParseIntelOperator(unsigned OpKind);
std::unique_ptr<X86Operand>
ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start, unsigned Size);
std::unique_ptr<X86Operand>
ParseIntelMemOperand(int64_t ImmDisp, SMLoc StartLoc, unsigned Size);
bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
X86Operand *ParseIntelBracExpression(unsigned SegReg, SMLoc Start,
int64_t ImmDisp, unsigned Size);
std::unique_ptr<X86Operand> ParseIntelBracExpression(unsigned SegReg,
SMLoc Start,
int64_t ImmDisp,
unsigned Size);
bool ParseIntelIdentifier(const MCExpr *&Val, StringRef &Identifier,
InlineAsmIdentifierInfo &Info,
bool IsUnevaluatedOperand, SMLoc &End);
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
std::unique_ptr<X86Operand> ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
X86Operand *CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End,
unsigned Size, StringRef Identifier,
InlineAsmIdentifierInfo &Info);
std::unique_ptr<X86Operand>
CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg,
unsigned IndexReg, unsigned Scale, SMLoc Start,
SMLoc End, unsigned Size, StringRef Identifier,
InlineAsmIdentifierInfo &Info);
bool ParseDirectiveWord(unsigned Size, SMLoc L);
bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
bool processInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
bool processInstruction(MCInst &Inst, const OperandVector &Ops);
/// Wrapper around MCStreamer::EmitInstruction(). Possibly adds
/// instrumentation around Inst.
void EmitInstruction(MCInst &Inst,
SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCStreamer &Out);
void EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
OperandVector &Operands, MCStreamer &Out,
unsigned &ErrorInfo,
bool MatchingInlineAsm) override;
/// doSrcDstMatch - Returns true if operands are matching in their
@ -674,8 +674,8 @@ private:
/// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
/// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
/// \return \c true if no parsing errors occurred, \c false otherwise.
bool HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
const MCParsedAsmOperand &Op);
bool HandleAVX512Operand(OperandVector &Operands,
const MCParsedAsmOperand &Op);
bool is64BitMode() const {
// FIXME: Can tablegen auto-generate this?
@ -725,9 +725,8 @@ public:
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) override;
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) override;
bool ParseDirective(AsmToken DirectiveID) override;
};
@ -908,7 +907,7 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo,
return false;
}
X86Operand *X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
unsigned basereg =
is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);
const MCExpr *Disp = MCConstantExpr::Create(0, getContext());
@ -916,7 +915,7 @@ X86Operand *X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
/*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);
}
X86Operand *X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
unsigned basereg =
is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI);
const MCExpr *Disp = MCConstantExpr::Create(0, getContext());
@ -924,7 +923,7 @@ X86Operand *X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
/*IndexReg=*/0, /*Scale=*/1, Loc, Loc, 0);
}
X86Operand *X86AsmParser::ParseOperand() {
std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() {
if (isParsingIntelSyntax())
return ParseIntelOperand();
return ParseATTOperand();
@ -946,12 +945,10 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) {
return Size;
}
X86Operand *
X86AsmParser::CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End,
unsigned Size, StringRef Identifier,
InlineAsmIdentifierInfo &Info){
std::unique_ptr<X86Operand> X86AsmParser::CreateMemForInlineAsm(
unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
InlineAsmIdentifierInfo &Info) {
// If this is not a VarDecl then assume it is a FuncDecl or some other label
// reference. We need an 'r' constraint here, so we need to create register
// operand to ensure proper matching. Just pick a GPR based on the size of
@ -1164,9 +1161,9 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
return false;
}
X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start,
int64_t ImmDisp,
unsigned Size) {
std::unique_ptr<X86Operand>
X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start,
int64_t ImmDisp, unsigned Size) {
const AsmToken &Tok = Parser.getTok();
SMLoc BracLoc = Tok.getLoc(), End = Tok.getEndLoc();
if (getLexer().isNot(AsmToken::LBrac))
@ -1270,9 +1267,9 @@ bool X86AsmParser::ParseIntelIdentifier(const MCExpr *&Val,
}
/// \brief Parse intel style segment override.
X86Operand *X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg,
SMLoc Start,
unsigned Size) {
std::unique_ptr<X86Operand>
X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg, SMLoc Start,
unsigned Size) {
assert(SegReg != 0 && "Tried to parse a segment override without a segment!");
const AsmToken &Tok = Parser.getTok(); // Eat colon.
if (Tok.isNot(AsmToken::Colon))
@ -1321,8 +1318,9 @@ X86Operand *X86AsmParser::ParseIntelSegmentOverride(unsigned SegReg,
}
/// ParseIntelMemOperand - Parse intel style memory operand.
X86Operand *X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp, SMLoc Start,
unsigned Size) {
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelMemOperand(int64_t ImmDisp,
SMLoc Start,
unsigned Size) {
const AsmToken &Tok = Parser.getTok();
SMLoc End;
@ -1425,7 +1423,7 @@ bool X86AsmParser::ParseIntelDotOperator(const MCExpr *Disp,
/// Parse the 'offset' operator. This operator is used to specify the
/// location rather then the content of a variable.
X86Operand *X86AsmParser::ParseIntelOffsetOfOperator() {
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() {
const AsmToken &Tok = Parser.getTok();
SMLoc OffsetOfLoc = Tok.getLoc();
Parser.Lex(); // Eat offset.
@ -1462,7 +1460,7 @@ enum IntelOperatorKind {
/// variable. A variable's size is the product of its LENGTH and TYPE. The
/// TYPE operator returns the size of a C or C++ type or variable. If the
/// variable is an array, TYPE returns the size of a single element.
X86Operand *X86AsmParser::ParseIntelOperator(unsigned OpKind) {
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperator(unsigned OpKind) {
const AsmToken &Tok = Parser.getTok();
SMLoc TypeLoc = Tok.getLoc();
Parser.Lex(); // Eat operator.
@ -1495,7 +1493,7 @@ X86Operand *X86AsmParser::ParseIntelOperator(unsigned OpKind) {
return X86Operand::CreateImm(Imm, Start, End);
}
X86Operand *X86AsmParser::ParseIntelOperand() {
std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
const AsmToken &Tok = Parser.getTok();
SMLoc Start, End;
@ -1577,7 +1575,7 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
return ParseIntelMemOperand(/*Disp=*/0, Start, Size);
}
X86Operand *X86AsmParser::ParseATTOperand() {
std::unique_ptr<X86Operand> X86AsmParser::ParseATTOperand() {
switch (getLexer().getKind()) {
default:
// Parse a memory operand with no segment register.
@ -1613,9 +1611,8 @@ X86Operand *X86AsmParser::ParseATTOperand() {
}
}
bool
X86AsmParser::HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
const MCParsedAsmOperand &Op) {
bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
const MCParsedAsmOperand &Op) {
if(STI.getFeatureBits() & X86::FeatureAVX512) {
if (getLexer().is(AsmToken::LCurly)) {
// Eat "{" and mark the current place.
@ -1653,8 +1650,8 @@ X86AsmParser::HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands
} else {
// Parse mask register {%k1}
Operands.push_back(X86Operand::CreateToken("{", consumedToken));
if (X86Operand *Op = ParseOperand()) {
Operands.push_back(Op);
if (std::unique_ptr<X86Operand> Op = ParseOperand()) {
Operands.push_back(std::move(Op));
if (!getLexer().is(AsmToken::RCurly))
return !ErrorAndEatStatement(getLexer().getLoc(),
"Expected } at this point");
@ -1682,7 +1679,8 @@ X86AsmParser::HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands
/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
/// has already been parsed if present.
X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
std::unique_ptr<X86Operand> X86AsmParser::ParseMemOperand(unsigned SegReg,
SMLoc MemStart) {
// We have to disambiguate a parenthesized expression "(4+5)" from the start
// of a memory operand with a missing displacement "(%ebx)" or "(,%eax)". The
@ -1845,9 +1843,8 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
MemStart, MemEnd);
}
bool X86AsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
InstInfo = &Info;
StringRef PatchedName = Name;
@ -1940,9 +1937,9 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
// Read the operands.
while(1) {
if (X86Operand *Op = ParseOperand()) {
Operands.push_back(Op);
if (!HandleAVX512Operand(Operands, *Op))
if (std::unique_ptr<X86Operand> Op = ParseOperand()) {
Operands.push_back(std::move(Op));
if (!HandleAVX512Operand(Operands, *Operands.back()))
return true;
} else {
Parser.eatToEndOfStatement();
@ -1973,27 +1970,25 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
// documented form in various unofficial manuals, so a lot of code uses it.
if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
Operands.size() == 3) {
X86Operand &Op = *(X86Operand*)Operands.back();
X86Operand &Op = (X86Operand &)*Operands.back();
if (Op.isMem() && Op.Mem.SegReg == 0 &&
isa<MCConstantExpr>(Op.Mem.Disp) &&
cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
SMLoc Loc = Op.getEndLoc();
Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
delete &Op;
}
}
// Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al".
if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") &&
Operands.size() == 3) {
X86Operand &Op = *(X86Operand*)Operands.begin()[1];
X86Operand &Op = (X86Operand &)*Operands[1];
if (Op.isMem() && Op.Mem.SegReg == 0 &&
isa<MCConstantExpr>(Op.Mem.Disp) &&
cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
SMLoc Loc = Op.getEndLoc();
Operands.begin()[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
delete &Op;
Operands[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
}
}
@ -2060,8 +2055,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Operands.push_back(DefaultMemSIOperand(NameLoc));
}
} else if (Operands.size() == 3) {
X86Operand &Op = *(X86Operand*)Operands.begin()[1];
X86Operand &Op2 = *(X86Operand*)Operands.begin()[2];
X86Operand &Op = (X86Operand &)*Operands[1];
X86Operand &Op2 = (X86Operand &)*Operands[2];
if (!doSrcDstMatch(Op, Op2))
return Error(Op.getStartLoc(),
"mismatching source and destination index registers");
@ -2076,10 +2071,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
(Name == "smov" || Name == "smovb" || Name == "smovw" ||
Name == "smovl" || Name == "smovd" || Name == "smovq"))) {
if (Operands.size() == 1) {
if (Name == "movsd") {
delete Operands.back();
if (Name == "movsd")
Operands.back() = X86Operand::CreateToken("movsl", NameLoc);
}
if (isParsingIntelSyntax()) {
Operands.push_back(DefaultMemDIOperand(NameLoc));
Operands.push_back(DefaultMemSIOperand(NameLoc));
@ -2088,8 +2081,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Operands.push_back(DefaultMemDIOperand(NameLoc));
}
} else if (Operands.size() == 3) {
X86Operand &Op = *(X86Operand*)Operands.begin()[1];
X86Operand &Op2 = *(X86Operand*)Operands.begin()[2];
X86Operand &Op = (X86Operand &)*Operands[1];
X86Operand &Op2 = (X86Operand &)*Operands[2];
if (!doSrcDstMatch(Op, Op2))
return Error(Op.getStartLoc(),
"mismatching source and destination index registers");
@ -2105,31 +2098,26 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Operands.size() == 3) {
if (isParsingIntelSyntax()) {
// Intel syntax
X86Operand *Op1 = static_cast<X86Operand*>(Operands[2]);
if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) {
delete Operands[2];
X86Operand &Op1 = static_cast<X86Operand &>(*Operands[2]);
if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
cast<MCConstantExpr>(Op1.getImm())->getValue() == 1)
Operands.pop_back();
}
} else {
X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) {
delete Operands[1];
X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
cast<MCConstantExpr>(Op1.getImm())->getValue() == 1)
Operands.erase(Operands.begin() + 1);
}
}
}
// Transforms "int $3" into "int3" as a size optimization. We can't write an
// instalias with an immediate operand yet.
if (Name == "int" && Operands.size() == 2) {
X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
cast<MCConstantExpr>(Op1->getImm())->getValue() == 3) {
delete Operands[1];
X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
if (Op1.isImm() && isa<MCConstantExpr>(Op1.getImm()) &&
cast<MCConstantExpr>(Op1.getImm())->getValue() == 3) {
Operands.erase(Operands.begin() + 1);
static_cast<X86Operand*>(Operands[0])->setTokenValue("int3");
static_cast<X86Operand &>(*Operands[0]).setTokenValue("int3");
}
}
@ -2175,9 +2163,7 @@ static bool convert64i32to64ri8(MCInst &Inst, unsigned Opcode,
return convertToSExti8(Inst, Opcode, X86::RAX, isCmp);
}
bool X86AsmParser::
processInstruction(MCInst &Inst,
const SmallVectorImpl<MCParsedAsmOperand*> &Ops) {
bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {
switch (Inst.getOpcode()) {
default: return false;
case X86::AND16i16: return convert16i16to16ri8(Inst, X86::AND16ri8);
@ -2258,51 +2244,47 @@ processInstruction(MCInst &Inst,
static const char *getSubtargetFeatureName(unsigned Val);
void X86AsmParser::EmitInstruction(
MCInst &Inst, SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCStreamer &Out) {
void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands,
MCStreamer &Out) {
Instrumentation->InstrumentInstruction(Inst, Operands, getContext(), MII,
Out);
Out.EmitInstruction(Inst, STI);
}
bool X86AsmParser::
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
assert(!Operands.empty() && "Unexpect empty operand list!");
X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
assert(Op->isToken() && "Leading operand should always be a mnemonic!");
X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
assert(Op.isToken() && "Leading operand should always be a mnemonic!");
ArrayRef<SMRange> EmptyRanges = None;
// First, handle aliases that expand to multiple instructions.
// FIXME: This should be replaced with a real .td file alias mechanism.
// Also, MatchInstructionImpl should actually *do* the EmitInstruction
// call.
if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
Op->getToken() == "finit" || Op->getToken() == "fsave" ||
Op->getToken() == "fstenv" || Op->getToken() == "fclex") {
if (Op.getToken() == "fstsw" || Op.getToken() == "fstcw" ||
Op.getToken() == "fstsww" || Op.getToken() == "fstcww" ||
Op.getToken() == "finit" || Op.getToken() == "fsave" ||
Op.getToken() == "fstenv" || Op.getToken() == "fclex") {
MCInst Inst;
Inst.setOpcode(X86::WAIT);
Inst.setLoc(IDLoc);
if (!MatchingInlineAsm)
EmitInstruction(Inst, Operands, Out);
const char *Repl =
StringSwitch<const char*>(Op->getToken())
.Case("finit", "fninit")
.Case("fsave", "fnsave")
.Case("fstcw", "fnstcw")
.Case("fstcww", "fnstcw")
.Case("fstenv", "fnstenv")
.Case("fstsw", "fnstsw")
.Case("fstsww", "fnstsw")
.Case("fclex", "fnclex")
.Default(nullptr);
const char *Repl = StringSwitch<const char *>(Op.getToken())
.Case("finit", "fninit")
.Case("fsave", "fnsave")
.Case("fstcw", "fnstcw")
.Case("fstcww", "fnstcw")
.Case("fstenv", "fnstenv")
.Case("fstsw", "fnstsw")
.Case("fstsww", "fnstsw")
.Case("fclex", "fnclex")
.Default(nullptr);
assert(Repl && "Unknown wait-prefixed instruction");
delete Operands[0];
Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
}
@ -2355,11 +2337,11 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
// following hack.
// Change the operand to point to a temporary token.
StringRef Base = Op->getToken();
StringRef Base = Op.getToken();
SmallString<16> Tmp;
Tmp += Base;
Tmp += ' ';
Op->setTokenValue(Tmp.str());
Op.setTokenValue(Tmp.str());
// If this instruction starts with an 'f', then it is a floating point stack
// instruction. These come in up to three forms for 32-bit, 64-bit, and
@ -2400,7 +2382,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
ErrorInfoMissingFeature = ErrorInfoIgnore;
// Restore the old token.
Op->setTokenValue(Base);
Op.setTokenValue(Base);
// If exactly one matched, then we treat that as a successful match (and the
// instruction will already have been filled in correctly, since the failing
@ -2450,8 +2432,8 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if ((Match1 == Match_MnemonicFail) && (Match2 == Match_MnemonicFail) &&
(Match3 == Match_MnemonicFail) && (Match4 == Match_MnemonicFail)) {
if (!WasOriginallyInvalidOperand) {
ArrayRef<SMRange> Ranges = MatchingInlineAsm ? EmptyRanges :
Op->getLocRange();
ArrayRef<SMRange> Ranges =
MatchingInlineAsm ? EmptyRanges : Op.getLocRange();
return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",
Ranges, MatchingInlineAsm);
}
@ -2462,10 +2444,10 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "too few operands for instruction",
EmptyRanges, MatchingInlineAsm);
X86Operand *Operand = (X86Operand*)Operands[ErrorInfo];
if (Operand->getStartLoc().isValid()) {
SMRange OperandRange = Operand->getLocRange();
return Error(Operand->getStartLoc(), "invalid operand for instruction",
X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];
if (Operand.getStartLoc().isValid()) {
SMRange OperandRange = Operand.getLocRange();
return Error(Operand.getStartLoc(), "invalid operand for instruction",
OperandRange, MatchingInlineAsm);
}
}

View File

@ -13,6 +13,7 @@
#include "X86AsmParserCommon.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/ADT/STLExtras.h"
namespace llvm {
@ -410,20 +411,19 @@ struct X86Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
}
static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
X86Operand *Res = new X86Operand(Token, Loc, EndLoc);
auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
Res->Tok.Data = Str.data();
Res->Tok.Length = Str.size();
return Res;
}
static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
bool AddressOf = false,
SMLoc OffsetOfLoc = SMLoc(),
StringRef SymName = StringRef(),
void *OpDecl = nullptr) {
X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
static std::unique_ptr<X86Operand>
CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
StringRef SymName = StringRef(), void *OpDecl = nullptr) {
auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
Res->Reg.RegNo = RegNo;
Res->AddressOf = AddressOf;
Res->OffsetOfLoc = OffsetOfLoc;
@ -432,17 +432,18 @@ struct X86Operand : public MCParsedAsmOperand {
return Res;
}
static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
SMLoc StartLoc, SMLoc EndLoc) {
auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
Res->Imm.Val = Val;
return Res;
}
/// Create an absolute memory operand.
static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
unsigned Size = 0, StringRef SymName = StringRef(),
void *OpDecl = nullptr) {
X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
static std::unique_ptr<X86Operand>
CreateMem(const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, unsigned Size = 0,
StringRef SymName = StringRef(), void *OpDecl = nullptr) {
auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
Res->Mem.SegReg = 0;
Res->Mem.Disp = Disp;
Res->Mem.BaseReg = 0;
@ -456,12 +457,11 @@ struct X86Operand : public MCParsedAsmOperand {
}
/// Create a generalized memory operand.
static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
unsigned Size = 0,
StringRef SymName = StringRef(),
void *OpDecl = nullptr) {
static std::unique_ptr<X86Operand>
CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg,
unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
unsigned Size = 0, StringRef SymName = StringRef(),
void *OpDecl = nullptr) {
// We should never just have a displacement, that should be parsed as an
// absolute memory operand.
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
@ -469,7 +469,7 @@ struct X86Operand : public MCParsedAsmOperand {
// The scale should always be one of {1,2,4,8}.
assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
"Invalid scale!");
X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
Res->Mem.SegReg = SegReg;
Res->Mem.Disp = Disp;
Res->Mem.BaseReg = BaseReg;

View File

@ -1722,8 +1722,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
CvtOS << "void " << Target.getName() << ClassName << "::\n"
<< "convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*"
<< "> &Operands) {\n"
<< " const OperandVector"
<< " &Operands) {\n"
<< " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
<< " const uint8_t *Converter = ConversionTable[Kind];\n"
<< " Inst.setOpcode(Opcode);\n"
@ -1732,7 +1732,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
<< " default: llvm_unreachable(\"invalid conversion entry!\");\n"
<< " case CVT_Reg:\n"
<< " static_cast<" << TargetOperandClass
<< "*>(Operands[*(p + 1)])->addRegOperands(Inst, 1);\n"
<< "&>(*Operands[*(p + 1)]).addRegOperands(Inst, 1);\n"
<< " break;\n"
<< " case CVT_Tied:\n"
<< " Inst.addOperand(Inst.getOperand(*(p + 1)));\n"
@ -1744,7 +1744,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
OpOS << "void " << Target.getName() << ClassName << "::\n"
<< "convertToMapAndConstraints(unsigned Kind,\n";
OpOS.indent(27);
OpOS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {\n"
OpOS << "const OperandVector &Operands) {\n"
<< " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
<< " unsigned NumMCOperands = 0;\n"
<< " const uint8_t *Converter = ConversionTable[Kind];\n"
@ -1849,9 +1849,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// converter driver.
CvtOS << " case " << Name << ":\n"
<< " static_cast<" << TargetOperandClass
<< "*>(Operands[*(p + 1)])->"
<< Op.Class->RenderMethod << "(Inst, " << OpInfo.MINumOperands
<< ");\n"
<< "&>(*Operands[*(p + 1)])." << Op.Class->RenderMethod
<< "(Inst, " << OpInfo.MINumOperands << ");\n"
<< " break;\n";
// Add a handler for the operand number lookup.
@ -2036,10 +2035,10 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target,
/// emitValidateOperandClass - Emit the function to validate an operand class.
static void emitValidateOperandClass(AsmMatcherInfo &Info,
raw_ostream &OS) {
OS << "static unsigned validateOperandClass(MCParsedAsmOperand *GOp, "
OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, "
<< "MatchClassKind Kind) {\n";
OS << " " << Info.Target.getName() << "Operand &Operand = *("
<< Info.Target.getName() << "Operand*)GOp;\n";
OS << " " << Info.Target.getName() << "Operand &Operand = ("
<< Info.Target.getName() << "Operand&)GOp;\n";
// The InvalidMatchClass is not to match any operand.
OS << " if (Kind == InvalidMatchClass)\n";
@ -2561,7 +2560,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// the found operand class.
OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< Target.getName() << ClassName << "::\n"
<< "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
<< "tryCustomParseOperand(OperandVector"
<< " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n";
@ -2585,7 +2584,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// a better error handling.
OS << Target.getName() << ClassName << "::OperandMatchResultTy "
<< Target.getName() << ClassName << "::\n"
<< "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>"
<< "MatchOperandParserImpl(OperandVector"
<< " &Operands,\n StringRef Mnemonic) {\n";
// Emit code to get the available features.
@ -2695,14 +2694,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*> "
<< " const OperandVector "
<< "&Operands);\n";
OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands) override;\n";
OS << " const OperandVector &Operands) override;\n";
OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n";
OS << " unsigned MatchInstructionImpl(\n";
OS.indent(27);
OS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"
OS << "const OperandVector &Operands,\n"
<< " MCInst &Inst,\n"
<< " unsigned &ErrorInfo,"
<< " bool matchingInlineAsm,\n"
@ -2715,11 +2714,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " MatchOperand_ParseFail // operand matched but had errors\n";
OS << " };\n";
OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " OperandVector &Operands,\n";
OS << " StringRef Mnemonic);\n";
OS << " OperandMatchResultTy tryCustomParseOperand(\n";
OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
OS << " OperandVector &Operands,\n";
OS << " unsigned MCK);\n\n";
}
@ -2909,9 +2908,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "}\n\n";
// Finally, build the match function.
OS << "unsigned "
<< Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
OS << "unsigned " << Target.getName() << ClassName << "::\n"
<< "MatchInstructionImpl(const OperandVector"
<< " &Operands,\n";
OS << " MCInst &Inst,\n"
<< "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n";
@ -2928,7 +2926,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // Get the instruction mnemonic, which is the first token.\n";
OS << " StringRef Mnemonic = ((" << Target.getName()
<< "Operand*)Operands[0])->getToken();\n\n";
<< "Operand&)*Operands[0]).getToken();\n\n";
if (HasMnemonicAliases) {
OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
@ -2980,7 +2978,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if (!OperandsValid) ErrorInfo = i + 1;\n";
OS << " break;\n";
OS << " }\n";
OS << " unsigned Diag = validateOperandClass(Operands[i+1],\n";
OS << " unsigned Diag = validateOperandClass(*Operands[i+1],\n";
OS.indent(43);
OS << "(MatchClassKind)it->Classes[i]);\n";
OS << " if (Diag == Match_Success)\n";
@ -2988,7 +2986,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // If the generic handler indicates an invalid operand\n";
OS << " // failure, check for a special case.\n";
OS << " if (Diag == Match_InvalidOperand) {\n";
OS << " Diag = validateTargetOperandClass(Operands[i+1],\n";
OS << " Diag = validateTargetOperandClass(*Operands[i+1],\n";
OS.indent(43);
OS << "(MatchClassKind)it->Classes[i]);\n";
OS << " if (Diag == Match_Success)\n";
@ -3055,7 +3053,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasDeprecation) {
OS << " std::string Info;\n";
OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName() << "Operand*)Operands[0])->getStartLoc();\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
OS << " Parser.Warning(Loc, Info, None);\n";
OS << " }\n";
}