Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
//===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===// | //===-- PPCAsmParser.cpp - Parse PowerPC asm to MCInst instructions -------===// | ||||
Lint: Lint: clang-format suggested style edits found: | |||||
// | // | ||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
// See https://llvm.org/LICENSE.txt for license information. | // See https://llvm.org/LICENSE.txt for license information. | ||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
// | // | ||||
//===----------------------------------------------------------------------===// | //===----------------------------------------------------------------------===// | ||||
#include "MCTargetDesc/PPCMCExpr.h" | #include "MCTargetDesc/PPCMCExpr.h" | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
namespace { | namespace { | ||||
struct PPCOperand; | struct PPCOperand; | ||||
class PPCAsmParser : public MCTargetAsmParser { | class PPCAsmParser : public MCTargetAsmParser { | ||||
bool IsPPC64; | bool IsPPC64; | ||||
bool IsDarwin; | |||||
void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); } | void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); } | ||||
bool isPPC64() const { return IsPPC64; } | bool isPPC64() const { return IsPPC64; } | ||||
bool isDarwin() const { return IsDarwin; } | |||||
bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal); | bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal); | ||||
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; | bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; | ||||
OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, | OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, | ||||
SMLoc &EndLoc) override; | SMLoc &EndLoc) override; | ||||
const MCExpr *ExtractModifierFromExpr(const MCExpr *E, | const MCExpr *ExtractModifierFromExpr(const MCExpr *E, | ||||
PPCMCExpr::VariantKind &Variant); | PPCMCExpr::VariantKind &Variant); | ||||
const MCExpr *FixupVariantKind(const MCExpr *E); | const MCExpr *FixupVariantKind(const MCExpr *E); | ||||
bool ParseExpression(const MCExpr *&EVal); | bool ParseExpression(const MCExpr *&EVal); | ||||
bool ParseDarwinExpression(const MCExpr *&EVal); | |||||
bool ParseOperand(OperandVector &Operands); | bool ParseOperand(OperandVector &Operands); | ||||
bool ParseDirectiveWord(unsigned Size, AsmToken ID); | bool ParseDirectiveWord(unsigned Size, AsmToken ID); | ||||
bool ParseDirectiveTC(unsigned Size, AsmToken ID); | bool ParseDirectiveTC(unsigned Size, AsmToken ID); | ||||
bool ParseDirectiveMachine(SMLoc L); | bool ParseDirectiveMachine(SMLoc L); | ||||
bool ParseDarwinDirectiveMachine(SMLoc L); | |||||
bool ParseDirectiveAbiVersion(SMLoc L); | bool ParseDirectiveAbiVersion(SMLoc L); | ||||
bool ParseDirectiveLocalEntry(SMLoc L); | bool ParseDirectiveLocalEntry(SMLoc L); | ||||
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, | ||||
OperandVector &Operands, MCStreamer &Out, | OperandVector &Operands, MCStreamer &Out, | ||||
uint64_t &ErrorInfo, | uint64_t &ErrorInfo, | ||||
bool MatchingInlineAsm) override; | bool MatchingInlineAsm) override; | ||||
Show All 10 Lines | |||||
public: | public: | ||||
PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &, | PPCAsmParser(const MCSubtargetInfo &STI, MCAsmParser &, | ||||
const MCInstrInfo &MII, const MCTargetOptions &Options) | const MCInstrInfo &MII, const MCTargetOptions &Options) | ||||
: MCTargetAsmParser(Options, STI, MII) { | : MCTargetAsmParser(Options, STI, MII) { | ||||
// Check for 64-bit vs. 32-bit pointer mode. | // Check for 64-bit vs. 32-bit pointer mode. | ||||
const Triple &TheTriple = STI.getTargetTriple(); | const Triple &TheTriple = STI.getTargetTriple(); | ||||
IsPPC64 = TheTriple.isPPC64(); | IsPPC64 = TheTriple.isPPC64(); | ||||
IsDarwin = TheTriple.isMacOSX(); | |||||
// Initialize the set of available features. | // Initialize the set of available features. | ||||
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); | setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); | ||||
} | } | ||||
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | ||||
SMLoc NameLoc, OperandVector &Operands) override; | SMLoc NameLoc, OperandVector &Operands) override; | ||||
bool ParseDirective(AsmToken DirectiveID) override; | bool ParseDirective(AsmToken DirectiveID) override; | ||||
▲ Show 20 Lines • Show All 1,234 Lines • ▼ Show 20 Lines | FixupVariantKind(const MCExpr *E) { | ||||
llvm_unreachable("Invalid expression kind!"); | llvm_unreachable("Invalid expression kind!"); | ||||
} | } | ||||
/// ParseExpression. This differs from the default "parseExpression" in that | /// ParseExpression. This differs from the default "parseExpression" in that | ||||
/// it handles modifiers. | /// it handles modifiers. | ||||
bool PPCAsmParser:: | bool PPCAsmParser:: | ||||
ParseExpression(const MCExpr *&EVal) { | ParseExpression(const MCExpr *&EVal) { | ||||
if (isDarwin()) | |||||
return ParseDarwinExpression(EVal); | |||||
// (ELF Platforms) | // (ELF Platforms) | ||||
// Handle \code @l/@ha \endcode | // Handle \code @l/@ha \endcode | ||||
if (getParser().parseExpression(EVal)) | if (getParser().parseExpression(EVal)) | ||||
return true; | return true; | ||||
EVal = FixupVariantKind(EVal); | EVal = FixupVariantKind(EVal); | ||||
PPCMCExpr::VariantKind Variant; | PPCMCExpr::VariantKind Variant; | ||||
const MCExpr *E = ExtractModifierFromExpr(EVal, Variant); | const MCExpr *E = ExtractModifierFromExpr(EVal, Variant); | ||||
if (E) | if (E) | ||||
EVal = PPCMCExpr::create(Variant, E, getParser().getContext()); | EVal = PPCMCExpr::create(Variant, E, getParser().getContext()); | ||||
return false; | return false; | ||||
} | } | ||||
/// ParseDarwinExpression. (MachO Platforms) | |||||
/// This differs from the default "parseExpression" in that it handles detection | |||||
/// of the \code hi16(), ha16() and lo16() \endcode modifiers. At present, | |||||
/// parseExpression() doesn't recognise the modifiers when in the Darwin/MachO | |||||
/// syntax form so it is done here. TODO: Determine if there is merit in | |||||
/// arranging for this to be done at a higher level. | |||||
bool PPCAsmParser:: | |||||
ParseDarwinExpression(const MCExpr *&EVal) { | |||||
MCAsmParser &Parser = getParser(); | |||||
PPCMCExpr::VariantKind Variant = PPCMCExpr::VK_PPC_None; | |||||
switch (getLexer().getKind()) { | |||||
default: | |||||
break; | |||||
case AsmToken::Identifier: | |||||
// Compiler-generated Darwin identifiers begin with L,l,_ or "; thus | |||||
// something starting with any other char should be part of the | |||||
// asm syntax. If handwritten asm includes an identifier like lo16, | |||||
// then all bets are off - but no-one would do that, right? | |||||
StringRef poss = Parser.getTok().getString(); | |||||
if (poss.equals_lower("lo16")) { | |||||
Variant = PPCMCExpr::VK_PPC_LO; | |||||
} else if (poss.equals_lower("hi16")) { | |||||
Variant = PPCMCExpr::VK_PPC_HI; | |||||
} else if (poss.equals_lower("ha16")) { | |||||
Variant = PPCMCExpr::VK_PPC_HA; | |||||
} | |||||
if (Variant != PPCMCExpr::VK_PPC_None) { | |||||
Parser.Lex(); // Eat the xx16 | |||||
if (getLexer().isNot(AsmToken::LParen)) | |||||
return Error(Parser.getTok().getLoc(), "expected '('"); | |||||
Parser.Lex(); // Eat the '(' | |||||
} | |||||
break; | |||||
} | |||||
if (getParser().parseExpression(EVal)) | |||||
return true; | |||||
if (Variant != PPCMCExpr::VK_PPC_None) { | |||||
if (getLexer().isNot(AsmToken::RParen)) | |||||
return Error(Parser.getTok().getLoc(), "expected ')'"); | |||||
Parser.Lex(); // Eat the ')' | |||||
EVal = PPCMCExpr::create(Variant, EVal, getParser().getContext()); | |||||
} | |||||
return false; | |||||
} | |||||
/// ParseOperand | /// ParseOperand | ||||
/// This handles registers in the form 'NN', '%rNN' for ELF platforms and | /// This handles registers in the form 'NN', '%rNN' for ELF platforms and | ||||
/// rNN for MachO. | /// rNN for MachO. | ||||
bool PPCAsmParser::ParseOperand(OperandVector &Operands) { | bool PPCAsmParser::ParseOperand(OperandVector &Operands) { | ||||
MCAsmParser &Parser = getParser(); | MCAsmParser &Parser = getParser(); | ||||
SMLoc S = Parser.getTok().getLoc(); | SMLoc S = Parser.getTok().getLoc(); | ||||
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); | ||||
const MCExpr *EVal; | const MCExpr *EVal; | ||||
Show All 16 Lines | bool PPCAsmParser::ParseOperand(OperandVector &Operands) { | ||||
case AsmToken::LParen: | case AsmToken::LParen: | ||||
case AsmToken::Plus: | case AsmToken::Plus: | ||||
case AsmToken::Minus: | case AsmToken::Minus: | ||||
case AsmToken::Integer: | case AsmToken::Integer: | ||||
case AsmToken::Dot: | case AsmToken::Dot: | ||||
case AsmToken::Dollar: | case AsmToken::Dollar: | ||||
case AsmToken::Exclaim: | case AsmToken::Exclaim: | ||||
case AsmToken::Tilde: | case AsmToken::Tilde: | ||||
// Note that non-register-name identifiers from the compiler will begin | |||||
// with '_', 'L'/'l' or '"'. Of course, handwritten asm could include | |||||
// identifiers like r31foo - so we fall through in the event that parsing | |||||
// a register name fails. | |||||
if (isDarwin()) { | |||||
unsigned RegNo; | |||||
int64_t IntVal; | |||||
if (!MatchRegisterName(RegNo, IntVal)) { | |||||
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | |||||
return false; | |||||
} | |||||
} | |||||
// All other expressions | |||||
if (!ParseExpression(EVal)) | if (!ParseExpression(EVal)) | ||||
break; | break; | ||||
// Fall-through | // Fall-through | ||||
LLVM_FALLTHROUGH; | LLVM_FALLTHROUGH; | ||||
default: | default: | ||||
return Error(S, "unknown operand"); | return Error(S, "unknown operand"); | ||||
} | } | ||||
Show All 30 Lines | if (!TLSCall && getLexer().is(AsmToken::LParen)) { | ||||
case AsmToken::Percent: | case AsmToken::Percent: | ||||
Parser.Lex(); // Eat the '%'. | Parser.Lex(); // Eat the '%'. | ||||
unsigned RegNo; | unsigned RegNo; | ||||
if (MatchRegisterName(RegNo, IntVal)) | if (MatchRegisterName(RegNo, IntVal)) | ||||
return Error(S, "invalid register name"); | return Error(S, "invalid register name"); | ||||
break; | break; | ||||
case AsmToken::Integer: | case AsmToken::Integer: | ||||
if (isDarwin()) | if (getParser().parseAbsoluteExpression(IntVal) || IntVal < 0 || | ||||
return Error(S, "unexpected integer value"); | |||||
else if (getParser().parseAbsoluteExpression(IntVal) || IntVal < 0 || | |||||
IntVal > 31) | IntVal > 31) | ||||
Lint: Pre-merge checks clang-format: please reformat the code - IntVal > 31) + IntVal > 31) Lint: Pre-merge checks: clang-format: please reformat the code
```
- IntVal > 31)
+ IntVal > 31)… | |||||
return Error(S, "invalid register number"); | return Error(S, "invalid register number"); | ||||
break; | break; | ||||
case AsmToken::Identifier: | case AsmToken::Identifier: | ||||
if (isDarwin()) { | |||||
unsigned RegNo; | |||||
if (!MatchRegisterName(RegNo, IntVal)) { | |||||
break; | |||||
} | |||||
} | |||||
LLVM_FALLTHROUGH; | |||||
default: | default: | ||||
return Error(S, "invalid memory operand"); | return Error(S, "invalid memory operand"); | ||||
} | } | ||||
E = Parser.getTok().getLoc(); | E = Parser.getTok().getLoc(); | ||||
if (parseToken(AsmToken::RParen, "missing ')'")) | if (parseToken(AsmToken::RParen, "missing ')'")) | ||||
return true; | return true; | ||||
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64())); | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | bool PPCAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
/// ParseDirective parses the PPC specific directives | /// ParseDirective parses the PPC specific directives | ||||
bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) { | bool PPCAsmParser::ParseDirective(AsmToken DirectiveID) { | ||||
StringRef IDVal = DirectiveID.getIdentifier(); | StringRef IDVal = DirectiveID.getIdentifier(); | ||||
if (isDarwin()) { | if (IDVal == ".word") | ||||
if (IDVal == ".machine") | |||||
ParseDarwinDirectiveMachine(DirectiveID.getLoc()); | |||||
else | |||||
return true; | |||||
} else if (IDVal == ".word") | |||||
ParseDirectiveWord(2, DirectiveID); | ParseDirectiveWord(2, DirectiveID); | ||||
else if (IDVal == ".llong") | else if (IDVal == ".llong") | ||||
ParseDirectiveWord(8, DirectiveID); | ParseDirectiveWord(8, DirectiveID); | ||||
else if (IDVal == ".tc") | else if (IDVal == ".tc") | ||||
ParseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID); | ParseDirectiveTC(isPPC64() ? 8 : 4, DirectiveID); | ||||
else if (IDVal == ".machine") | else if (IDVal == ".machine") | ||||
ParseDirectiveMachine(DirectiveID.getLoc()); | ParseDirectiveMachine(DirectiveID.getLoc()); | ||||
else if (IDVal == ".abiversion") | else if (IDVal == ".abiversion") | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | bool PPCAsmParser::ParseDirectiveMachine(SMLoc L) { | ||||
PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>( | PPCTargetStreamer *TStreamer = static_cast<PPCTargetStreamer *>( | ||||
getParser().getStreamer().getTargetStreamer()); | getParser().getStreamer().getTargetStreamer()); | ||||
if (TStreamer != nullptr) | if (TStreamer != nullptr) | ||||
TStreamer->emitMachine(CPU); | TStreamer->emitMachine(CPU); | ||||
return false; | return false; | ||||
} | } | ||||
/// ParseDarwinDirectiveMachine (Mach-o platforms) | |||||
/// ::= .machine cpu-identifier | |||||
bool PPCAsmParser::ParseDarwinDirectiveMachine(SMLoc L) { | |||||
MCAsmParser &Parser = getParser(); | |||||
if (Parser.getTok().isNot(AsmToken::Identifier) && | |||||
Parser.getTok().isNot(AsmToken::String)) | |||||
return Error(L, "unexpected token in directive"); | |||||
StringRef CPU = Parser.getTok().getIdentifier(); | |||||
Parser.Lex(); | |||||
// FIXME: this is only the 'default' set of cpu variants. | |||||
// However we don't act on this information at present, this is simply | |||||
// allowing parsing to proceed with minimal sanity checking. | |||||
if (check(CPU != "ppc7400" && CPU != "ppc" && CPU != "ppc64", L, | |||||
"unrecognized cpu type") || | |||||
check(isPPC64() && (CPU == "ppc7400" || CPU == "ppc"), L, | |||||
"wrong cpu type specified for 64bit") || | |||||
check(!isPPC64() && CPU == "ppc64", L, | |||||
"wrong cpu type specified for 32bit") || | |||||
parseToken(AsmToken::EndOfStatement)) | |||||
return addErrorSuffix(" in '.machine' directive"); | |||||
return false; | |||||
} | |||||
/// ParseDirectiveAbiVersion | /// ParseDirectiveAbiVersion | ||||
/// ::= .abiversion constant-expression | /// ::= .abiversion constant-expression | ||||
bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) { | bool PPCAsmParser::ParseDirectiveAbiVersion(SMLoc L) { | ||||
int64_t AbiVersion; | int64_t AbiVersion; | ||||
if (check(getParser().parseAbsoluteExpression(AbiVersion), L, | if (check(getParser().parseAbsoluteExpression(AbiVersion), L, | ||||
"expected constant expression") || | "expected constant expression") || | ||||
parseToken(AsmToken::EndOfStatement)) | parseToken(AsmToken::EndOfStatement)) | ||||
return addErrorSuffix(" in '.abiversion' directive"); | return addErrorSuffix(" in '.abiversion' directive"); | ||||
▲ Show 20 Lines • Show All 100 Lines • Show Last 20 Lines |
clang-format suggested style edits found: