diff options
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 1592 |
1 files changed, 802 insertions, 790 deletions
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 66d3bc745a..ce5ce1dc3f 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -50,7 +50,6 @@ MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { - /// \brief Helper class for storing information about an active macro /// instantiation. struct MacroInstantiation { @@ -111,7 +110,6 @@ private: SourceMgr &SrcMgr; SourceMgr::DiagHandlerTy SavedDiagHandler; void *SavedDiagContext; - MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; /// This is the current buffer index we're lexing from as managed by the @@ -121,11 +119,12 @@ private: AsmCond TheCondState; std::vector<AsmCond> TheCondStack; - /// DirectiveMap - This is a table handlers for directives. Each handler is - /// invoked after the directive identifier is read and is responsible for - /// parsing and validating the rest of the directive. The handler is passed - /// in the directive name and the location of the directive keyword. - StringMap<std::pair<MCAsmParserExtension*, DirectiveHandler> > DirectiveMap; + /// ExtensionDirectiveMap - maps directive names to handler methods in parser + /// extensions. Extensions register themselves in this map by calling + /// AddDirectiveHandler. + typedef std::pair<MCAsmParserExtension*, DirectiveHandler> + ExtensionDirectiveHandler; + StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap; /// MacroMap - Map of currently defined macros. StringMap<MCAsmMacro*> MacroMap; @@ -164,7 +163,7 @@ public: virtual void AddDirectiveHandler(MCAsmParserExtension *Object, StringRef Directive, DirectiveHandler Handler) { - DirectiveMap[Directive] = std::make_pair(Object, Handler); + ExtensionDirectiveMap[Directive] = std::make_pair(Object, Handler); } public: @@ -282,8 +281,9 @@ private: bool ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc); bool ParseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc); - // Directive Parsing. + bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); + // Generic (target and platform independent) directive parsing. enum DirectiveKind { DK_NO_DIRECTIVE, // Placeholder DK_SET, DK_EQU, DK_EQUIV, DK_ASCII, DK_ASCIZ, DK_STRING, DK_BYTE, DK_SHORT, @@ -297,10 +297,21 @@ private: DK_WEAK_DEF_CAN_BE_HIDDEN, DK_COMM, DK_COMMON, DK_LCOMM, DK_ABORT, DK_INCLUDE, DK_INCBIN, DK_CODE16, DK_CODE16GCC, DK_REPT, DK_IRP, DK_IRPC, DK_IF, DK_IFB, DK_IFNB, DK_IFC, DK_IFNC, DK_IFDEF, DK_IFNDEF, DK_IFNOTDEF, - DK_ELSEIF, DK_ELSE, DK_ENDIF + DK_ELSEIF, DK_ELSE, DK_ENDIF, + DK_SPACE, DK_SKIP, DK_FILE, DK_LINE, DK_LOC, DK_STABS, + DK_CFI_SECTIONS, DK_CFI_STARTPROC, DK_CFI_ENDPROC, DK_CFI_DEF_CFA, + DK_CFI_DEF_CFA_OFFSET, DK_CFI_ADJUST_CFA_OFFSET, DK_CFI_DEF_CFA_REGISTER, + DK_CFI_OFFSET, DK_CFI_REL_OFFSET, DK_CFI_PERSONALITY, DK_CFI_LSDA, + DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, + DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, + DK_CFI_REGISTER, + DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, + DK_SLEB128, DK_ULEB128 }; - StringMap<DirectiveKind> DirectiveKindMapping; + /// DirectiveKindMap - Maps directive name --> DirectiveKind enum, for + /// directives parsed by this class. + StringMap<DirectiveKind> DirectiveKindMap; // ".ascii", ".asciz", ".string" bool ParseDirectiveAscii(StringRef IDVal, bool ZeroTerminated); @@ -314,6 +325,38 @@ private: // ".align{,32}", ".p2align{,w,l}" bool ParseDirectiveAlign(bool IsPow2, unsigned ValueSize); + // ".file", ".line", ".loc", ".stabs" + bool ParseDirectiveFile(SMLoc DirectiveLoc); + bool ParseDirectiveLine(); + bool ParseDirectiveLoc(); + bool ParseDirectiveStabs(); + + // .cfi directives + bool ParseDirectiveCFIRegister(SMLoc DirectiveLoc); + bool ParseDirectiveCFISections(); + bool ParseDirectiveCFIStartProc(); + bool ParseDirectiveCFIEndProc(); + bool ParseDirectiveCFIDefCfaOffset(); + bool ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc); + bool ParseDirectiveCFIAdjustCfaOffset(); + bool ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc); + bool ParseDirectiveCFIOffset(SMLoc DirectiveLoc); + bool ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc); + bool ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality); + bool ParseDirectiveCFIRememberState(); + bool ParseDirectiveCFIRestoreState(); + bool ParseDirectiveCFISameValue(SMLoc DirectiveLoc); + bool ParseDirectiveCFIRestore(SMLoc DirectiveLoc); + bool ParseDirectiveCFIEscape(); + bool ParseDirectiveCFISignalFrame(); + bool ParseDirectiveCFIUndefined(SMLoc DirectiveLoc); + + // macro directives + bool ParseDirectivePurgeMacro(SMLoc DirectiveLoc); + bool ParseDirectiveEndMacro(StringRef Directive); + bool ParseDirectiveMacro(SMLoc DirectiveLoc); + bool ParseDirectiveMacrosOnOff(StringRef Directive); + // ".bundle_align_mode" bool ParseDirectiveBundleAlignMode(); // ".bundle_lock" @@ -321,6 +364,12 @@ private: // ".bundle_unlock" bool ParseDirectiveBundleUnlock(); + // ".space", ".skip" + bool ParseDirectiveSpace(StringRef IDVal); + + // .sleb128 (Signed=true) and .uleb128 (Signed=false) + bool ParseDirectiveLEB128(bool Signed); + /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which /// accepts a single symbol (which should be a label or an external). bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); @@ -361,121 +410,8 @@ private: // "_emit" bool ParseDirectiveEmit(SMLoc DirectiveLoc, ParseStatementInfo &Info); - void initializeDirectiveKindMapping(); -}; - -/// \brief Generic implementation of directive handling, etc. which is shared -/// (or the default, at least) for all assembler parsers. -class GenericAsmParser : public MCAsmParserExtension { - template<bool (GenericAsmParser::*Handler)(StringRef, SMLoc)> - void AddDirectiveHandler(StringRef Directive) { - getParser().AddDirectiveHandler(this, Directive, - HandleDirective<GenericAsmParser, Handler>); - } -public: - GenericAsmParser() {} - - virtual void Initialize(MCAsmParser &Parser) { - // Call the base implementation. - this->MCAsmParserExtension::Initialize(Parser); - - // Debugging directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveFile>(".file"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLine>(".line"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLoc>(".loc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveStabs>(".stabs"); - - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveSpace>(".space"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveSpace>(".skip"); - - // CFI directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFISections>( - ".cfi_sections"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIStartProc>( - ".cfi_startproc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIEndProc>( - ".cfi_endproc"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfa>( - ".cfi_def_cfa"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( - ".cfi_def_cfa_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>( - ".cfi_adjust_cfa_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( - ".cfi_def_cfa_register"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( - ".cfi_offset"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>( - ".cfi_rel_offset"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_lsda"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRestore>(".cfi_restore"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIEscape>(".cfi_escape"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFISignalFrame>(".cfi_signal_frame"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIUndefined>(".cfi_undefined"); - AddDirectiveHandler< - &GenericAsmParser::ParseDirectiveCFIRegister>(".cfi_register"); - - // Macro directives. - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( - ".macros_on"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( - ".macros_off"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacro>(".macro"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endm"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveEndMacro>(".endmacro"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectivePurgeMacro>(".purgem"); - - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".sleb128"); - AddDirectiveHandler<&GenericAsmParser::ParseDirectiveLEB128>(".uleb128"); - } - - bool ParseRegisterOrRegisterNumber(int64_t &Register, SMLoc DirectiveLoc); - - bool ParseDirectiveFile(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveLine(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveStabs(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveSpace(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISections(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRestore(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIEscape(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFISignalFrame(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIUndefined(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveCFIRegister(StringRef, SMLoc DirectiveLoc); - - bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); - bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc); - bool ParseDirectivePurgeMacro(StringRef, SMLoc DirectiveLoc); - - bool ParseDirectiveLEB128(StringRef, SMLoc); + void initializeDirectiveKindMap(); }; - } namespace llvm { @@ -491,7 +427,7 @@ enum { DEFAULT_ADDRSPACE = 0 }; AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), MAI(_MAI), SrcMgr(_SM), - GenericParser(new GenericAsmParser), PlatformParser(0), + PlatformParser(0), CurBuffer(0), MacrosEnabledFlag(true), CppHashLineNumber(0), AssemblerDialect(~0U), IsDarwin(false), ParsingInlineAsm(false) { // Save the old handler. @@ -501,9 +437,6 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, SrcMgr.setDiagHandler(DiagHandler, this); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - // Initialize the generic parser. - GenericParser->Initialize(*this); - // Initialize the platform / file format parser. // // FIXME: This is a hack, we need to (majorly) cleanup how these objects are @@ -520,7 +453,7 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, PlatformParser->Initialize(*this); } - initializeDirectiveKindMapping(); + initializeDirectiveKindMap(); } AsmParser::~AsmParser() { @@ -532,7 +465,6 @@ AsmParser::~AsmParser() { delete it->getValue(); delete PlatformParser; - delete GenericParser; } void AsmParser::PrintMacroInstantiations() { @@ -1169,10 +1101,10 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { // have to do this so that .endif isn't skipped in a ".if 0" block for // example. StringMap<DirectiveKind>::const_iterator DirKindIt = - DirectiveKindMapping.find(IDVal); + DirectiveKindMap.find(IDVal); DirectiveKind DirKind = - (DirKindIt == DirectiveKindMapping.end()) ? DK_NO_DIRECTIVE : - DirKindIt->getValue(); + (DirKindIt == DirectiveKindMap.end()) ? DK_NO_DIRECTIVE : + DirKindIt->getValue(); switch (DirKind) { default: break; @@ -1270,12 +1202,34 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { } // Otherwise, we have a normal instruction or directive. + + // Directives start with "." if (IDVal[0] == '.' && IDVal != ".") { - - // Target hook for parsing target specific directives. + // There are several entities interested in parsing directives: + // + // 1. The target-specific assembly parser. Some directives are target + // specific or may potentially behave differently on certain targets. + // 2. Asm parser extensions. For example, platform-specific parsers + // (like the ELF parser) register themselves as extensions. + // 3. The generic directive parser implemented by this class. These are + // all the directives that behave in a target and platform independent + // manner, or at least have a default behavior that's shared between + // all targets and platforms. + + // First query the target-specific parser. It will return 'true' if it + // isn't interested in this directive. if (!getTargetParser().ParseDirective(ID)) return false; + // Next, check the extention directive map to see if any extension has + // registered itself to parse this directive. + std::pair<MCAsmParserExtension*, DirectiveHandler> Handler = + ExtensionDirectiveMap.lookup(IDVal); + if (Handler.first) + return (*Handler.second)(Handler.first, IDVal, IDLoc); + + // Finally, if no one else is interested in this directive, it must be + // generic and familiar to this class. switch (DirKind) { default: break; @@ -1385,14 +1339,71 @@ bool AsmParser::ParseStatement(ParseStatementInfo &Info) { return ParseDirectiveBundleLock(); case DK_BUNDLE_UNLOCK: return ParseDirectiveBundleUnlock(); + case DK_SLEB128: + return ParseDirectiveLEB128(true); + case DK_ULEB128: + return ParseDirectiveLEB128(false); + case DK_SPACE: + case DK_SKIP: + return ParseDirectiveSpace(IDVal); + case DK_FILE: + return ParseDirectiveFile(IDLoc); + case DK_LINE: + return ParseDirectiveLine(); + case DK_LOC: + return ParseDirectiveLoc(); + case DK_STABS: + return ParseDirectiveStabs(); + case DK_CFI_SECTIONS: + return ParseDirectiveCFISections(); + case DK_CFI_STARTPROC: + return ParseDirectiveCFIStartProc(); + case DK_CFI_ENDPROC: + return ParseDirectiveCFIEndProc(); + case DK_CFI_DEF_CFA: + return ParseDirectiveCFIDefCfa(IDLoc); + case DK_CFI_DEF_CFA_OFFSET: + return ParseDirectiveCFIDefCfaOffset(); + case DK_CFI_ADJUST_CFA_OFFSET: + return ParseDirectiveCFIAdjustCfaOffset(); + case DK_CFI_DEF_CFA_REGISTER: + return ParseDirectiveCFIDefCfaRegister(IDLoc); + case DK_CFI_OFFSET: + return ParseDirectiveCFIOffset(IDLoc); + case DK_CFI_REL_OFFSET: + return ParseDirectiveCFIRelOffset(IDLoc); + case DK_CFI_PERSONALITY: + return ParseDirectiveCFIPersonalityOrLsda(true); + case DK_CFI_LSDA: + return ParseDirectiveCFIPersonalityOrLsda(false); + case DK_CFI_REMEMBER_STATE: + return ParseDirectiveCFIRememberState(); + case DK_CFI_RESTORE_STATE: + return ParseDirectiveCFIRestoreState(); + case DK_CFI_SAME_VALUE: + return ParseDirectiveCFISameValue(IDLoc); + case DK_CFI_RESTORE: + return ParseDirectiveCFIRestore(IDLoc); + case DK_CFI_ESCAPE: + return ParseDirectiveCFIEscape(); + case DK_CFI_SIGNAL_FRAME: + return ParseDirectiveCFISignalFrame(); + case DK_CFI_UNDEFINED: + return ParseDirectiveCFIUndefined(IDLoc); + case DK_CFI_REGISTER: + return ParseDirectiveCFIRegister(IDLoc); + case DK_MACROS_ON: + case DK_MACROS_OFF: + return ParseDirectiveMacrosOnOff(IDVal); + case DK_MACRO: + return ParseDirectiveMacro(IDLoc); + case DK_ENDM: + case DK_ENDMACRO: + return ParseDirectiveEndMacro(IDVal); + case DK_PURGEM: + return ParseDirectivePurgeMacro(IDLoc); } - // Look up the handler in the extension handler table. - std::pair<MCAsmParserExtension*, DirectiveHandler> Handler = - DirectiveMap.lookup(IDVal); - if (Handler.first) - return (*Handler.second)(Handler.first, IDVal, IDLoc); - return Error(IDLoc, "unknown directive"); } @@ -2429,507 +2440,10 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { return false; } - -/// ParseDirectiveBundleAlignMode -/// ::= {.bundle_align_mode} expression -bool AsmParser::ParseDirectiveBundleAlignMode() { - CheckForValidSection(); - - // Expect a single argument: an expression that evaluates to a constant - // in the inclusive range 0-30. - SMLoc ExprLoc = getLexer().getLoc(); - int64_t AlignSizePow2; - if (ParseAbsoluteExpression(AlignSizePow2)) - return true; - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token after expression in" - " '.bundle_align_mode' directive"); - else if (AlignSizePow2 < 0 || AlignSizePow2 > 30) - return Error(ExprLoc, - "invalid bundle alignment size (expected between 0 and 30)"); - - Lex(); - - // Because of AlignSizePow2's verified range we can safely truncate it to - // unsigned. - getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2)); - return false; -} - -/// ParseDirectiveBundleLock -/// ::= {.bundle_lock} [align_to_end] -bool AsmParser::ParseDirectiveBundleLock() { - CheckForValidSection(); - bool AlignToEnd = false; - - if (getLexer().isNot(AsmToken::EndOfStatement)) { - StringRef Option; - SMLoc Loc = getTok().getLoc(); - const char *kInvalidOptionError = - "invalid option for '.bundle_lock' directive"; - - if (ParseIdentifier(Option)) - return Error(Loc, kInvalidOptionError); - - if (Option != "align_to_end") - return Error(Loc, kInvalidOptionError); - else if (getLexer().isNot(AsmToken::EndOfStatement)) - return Error(Loc, - "unexpected token after '.bundle_lock' directive option"); - AlignToEnd = true; - } - - Lex(); - - getStreamer().EmitBundleLock(AlignToEnd); - return false; -} - -/// ParseDirectiveBundleLock -/// ::= {.bundle_lock} -bool AsmParser::ParseDirectiveBundleUnlock() { - CheckForValidSection(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.bundle_unlock' directive"); - Lex(); - - getStreamer().EmitBundleUnlock(); - return false; -} - -/// ParseDirectiveSymbolAttribute -/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] -bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { - if (getLexer().isNot(AsmToken::EndOfStatement)) { - for (;;) { - StringRef Name; - SMLoc Loc = getTok().getLoc(); - - if (ParseIdentifier(Name)) - return Error(Loc, "expected identifier in directive"); - - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - - // Assembler local symbols don't make any sense here. Complain loudly. - if (Sym->isTemporary()) - return Error(Loc, "non-local symbol required in directive"); - - getStreamer().EmitSymbolAttribute(Sym, Attr); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - } - } - - Lex(); - return false; -} - -/// ParseDirectiveComm -/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] -bool AsmParser::ParseDirectiveComm(bool IsLocal) { - CheckForValidSection(); - - SMLoc IDLoc = getLexer().getLoc(); - StringRef Name; - if (ParseIdentifier(Name)) - return TokError("expected identifier in directive"); - - // Handle the identifier as the key symbol. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Size; - SMLoc SizeLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Size)) - return true; - - int64_t Pow2Alignment = 0; - SMLoc Pow2AlignmentLoc; - if (getLexer().is(AsmToken::Comma)) { - Lex(); - Pow2AlignmentLoc = getLexer().getLoc(); - if (ParseAbsoluteExpression(Pow2Alignment)) - return true; - - LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); - if (IsLocal && LCOMM == LCOMM::NoAlignment) - return Error(Pow2AlignmentLoc, "alignment not supported on this target"); - - // If this target takes alignments in bytes (not log) validate and convert. - if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || - (IsLocal && LCOMM == LCOMM::ByteAlignment)) { - if (!isPowerOf2_64(Pow2Alignment)) - return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); - Pow2Alignment = Log2_64(Pow2Alignment); - } - } - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.comm' or '.lcomm' directive"); - - Lex(); - - // NOTE: a size of zero for a .comm should create a undefined symbol - // but a size of .lcomm creates a bss symbol of size zero. - if (Size < 0) - return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " - "be less than zero"); - - // NOTE: The alignment in the directive is a power of 2 value, the assembler - // may internally end up wanting an alignment in bytes. - // FIXME: Diagnose overflow. - if (Pow2Alignment < 0) - return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " - "alignment, can't be less than zero"); - - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - // Create the Symbol as a common or local common with Size and Pow2Alignment - if (IsLocal) { - getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; - } - - getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); - return false; -} - -/// ParseDirectiveAbort -/// ::= .abort [... message ...] -bool AsmParser::ParseDirectiveAbort() { - // FIXME: Use loc from directive. - SMLoc Loc = getLexer().getLoc(); - - StringRef Str = ParseStringToEndOfStatement(); - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.abort' directive"); - - Lex(); - - if (Str.empty()) - Error(Loc, ".abort detected. Assembly stopping."); - else - Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); - // FIXME: Actually abort assembly here. - - return false; -} - -/// ParseDirectiveInclude -/// ::= .include "filename" -bool AsmParser::ParseDirectiveInclude() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.include' directive"); - - std::string Filename = getTok().getString(); - SMLoc IncludeLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.include' directive"); - - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - - // Attempt to switch the lexer to the included file before consuming the end - // of statement to avoid losing it when we switch. - if (EnterIncludeFile(Filename)) { - Error(IncludeLoc, "Could not find include file '" + Filename + "'"); - return true; - } - - return false; -} - -/// ParseDirectiveIncbin -/// ::= .incbin "filename" -bool AsmParser::ParseDirectiveIncbin() { - if (getLexer().isNot(AsmToken::String)) - return TokError("expected string in '.incbin' directive"); - - std::string Filename = getTok().getString(); - SMLoc IncbinLoc = getLexer().getLoc(); - Lex(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.incbin' directive"); - - // Strip the quotes. - Filename = Filename.substr(1, Filename.size()-2); - - // Attempt to process the included file. - if (ProcessIncbinFile(Filename)) { - Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); - return true; - } - - return false; -} - -/// ParseDirectiveIf -/// ::= .if expression -bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.if' directive"); - - Lex(); - - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfb -/// ::= .ifb string -bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - StringRef Str = ParseStringToEndOfStatement(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifb' directive"); - - Lex(); - - TheCondState.CondMet = ExpectBlank == Str.empty(); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfc -/// ::= .ifc string1, string2 -bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - StringRef Str1 = ParseStringToComma(); - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); - - StringRef Str2 = ParseStringToEndOfStatement(); - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.ifc' directive"); - - Lex(); - - TheCondState.CondMet = ExpectEqual == (Str1 == Str2); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveIfdef -/// ::= .ifdef symbol -bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { - StringRef Name; - TheCondStack.push_back(TheCondState); - TheCondState.TheCond = AsmCond::IfCond; - - if (TheCondState.Ignore) { - EatToEndOfStatement(); - } else { - if (ParseIdentifier(Name)) - return TokError("expected identifier after '.ifdef'"); - - Lex(); - - MCSymbol *Sym = getContext().LookupSymbol(Name); - - if (expect_defined) - TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); - else - TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveElseIf -/// ::= .elseif expression -bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " - " an .elseif"); - TheCondState.TheCond = AsmCond::ElseIfCond; - - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) { - TheCondState.Ignore = true; - EatToEndOfStatement(); - } - else { - int64_t ExprValue; - if (ParseAbsoluteExpression(ExprValue)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.elseif' directive"); - - Lex(); - TheCondState.CondMet = ExprValue; - TheCondState.Ignore = !TheCondState.CondMet; - } - - return false; -} - -/// ParseDirectiveElse -/// ::= .else -bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.else' directive"); - - Lex(); - - if (TheCondState.TheCond != AsmCond::IfCond && - TheCondState.TheCond != AsmCond::ElseIfCond) - Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " - ".elseif"); - TheCondState.TheCond = AsmCond::ElseCond; - bool LastIgnoreState = false; - if (!TheCondStack.empty()) - LastIgnoreState = TheCondStack.back().Ignore; - if (LastIgnoreState || TheCondState.CondMet) - TheCondState.Ignore = true; - else - TheCondState.Ignore = false; - - return false; -} - -/// ParseDirectiveEndIf -/// ::= .endif -bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.endif' directive"); - - Lex(); - - if ((TheCondState.TheCond == AsmCond::NoCond) || - TheCondStack.empty()) - Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " - ".else"); - if (!TheCondStack.empty()) { - TheCondState = TheCondStack.back(); - TheCondStack.pop_back(); - } - - return false; -} - -void AsmParser::initializeDirectiveKindMapping() { - DirectiveKindMapping[".set"] = DK_SET; - DirectiveKindMapping[".equ"] = DK_EQU; - DirectiveKindMapping[".equiv"] = DK_EQUIV; - DirectiveKindMapping[".ascii"] = DK_ASCII; - DirectiveKindMapping[".asciz"] = DK_ASCIZ; - DirectiveKindMapping[".string"] = DK_STRING; - DirectiveKindMapping[".byte"] = DK_BYTE; - DirectiveKindMapping[".short"] = DK_SHORT; - DirectiveKindMapping[".value"] = DK_VALUE; - DirectiveKindMapping[".2byte"] = DK_2BYTE; - DirectiveKindMapping[".long"] = DK_LONG; - DirectiveKindMapping[".int"] = DK_INT; - DirectiveKindMapping[".4byte"] = DK_4BYTE; - DirectiveKindMapping[".quad"] = DK_QUAD; - DirectiveKindMapping[".8byte"] = DK_8BYTE; - DirectiveKindMapping[".single"] = DK_SINGLE; - DirectiveKindMapping[".float"] = DK_FLOAT; - DirectiveKindMapping[".double"] = DK_DOUBLE; - DirectiveKindMapping[".align"] = DK_ALIGN; - DirectiveKindMapping[".align32"] = DK_ALIGN32; - DirectiveKindMapping[".balign"] = DK_BALIGN; - DirectiveKindMapping[".balignw"] = DK_BALIGNW; - DirectiveKindMapping[".balignl"] = DK_BALIGNL; - DirectiveKindMapping[".p2align"] = DK_P2ALIGN; - DirectiveKindMapping[".p2alignw"] = DK_P2ALIGNW; - DirectiveKindMapping[".p2alignl"] = DK_P2ALIGNL; - DirectiveKindMapping[".org"] = DK_ORG; - DirectiveKindMapping[".fill"] = DK_FILL; - DirectiveKindMapping[".zero"] = DK_ZERO; - DirectiveKindMapping[".extern"] = DK_EXTERN; - DirectiveKindMapping[".globl"] = DK_GLOBL; - DirectiveKindMapping[".global"] = DK_GLOBAL; - DirectiveKindMapping[".indirect_symbol"] = DK_INDIRECT_SYMBOL; - DirectiveKindMapping[".lazy_reference"] = DK_LAZY_REFERENCE; - DirectiveKindMapping[".no_dead_strip"] = DK_NO_DEAD_STRIP; - DirectiveKindMapping[".symbol_resolver"] = DK_SYMBOL_RESOLVER; - DirectiveKindMapping[".private_extern"] = DK_PRIVATE_EXTERN; - DirectiveKindMapping[".reference"] = DK_REFERENCE; - DirectiveKindMapping[".weak_definition"] = DK_WEAK_DEFINITION; - DirectiveKindMapping[".weak_reference"] = DK_WEAK_REFERENCE; - DirectiveKindMapping[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; - DirectiveKindMapping[".comm"] = DK_COMM; - DirectiveKindMapping[".common"] = DK_COMMON; - DirectiveKindMapping[".lcomm"] = DK_LCOMM; - DirectiveKindMapping[".abort"] = DK_ABORT; - DirectiveKindMapping[".include"] = DK_INCLUDE; - DirectiveKindMapping[".incbin"] = DK_INCBIN; - DirectiveKindMapping[".code16"] = DK_CODE16; - DirectiveKindMapping[".code16gcc"] = DK_CODE16GCC; - DirectiveKindMapping[".rept"] = DK_REPT; - DirectiveKindMapping[".irp"] = DK_IRP; - DirectiveKindMapping[".irpc"] = DK_IRPC; - DirectiveKindMapping[".endr"] = DK_ENDR; - DirectiveKindMapping[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; - DirectiveKindMapping[".bundle_lock"] = DK_BUNDLE_LOCK; - DirectiveKindMapping[".bundle_unlock"] = DK_BUNDLE_UNLOCK; - DirectiveKindMapping[".if"] = DK_IF; - DirectiveKindMapping[".ifb"] = DK_IFB; - DirectiveKindMapping[".ifnb"] = DK_IFNB; - DirectiveKindMapping[".ifc"] = DK_IFC; - DirectiveKindMapping[".ifnc"] = DK_IFNC; - DirectiveKindMapping[".ifdef"] = DK_IFDEF; - DirectiveKindMapping[".ifndef"] = DK_IFNDEF; - DirectiveKindMapping[".ifnotdef"] = DK_IFNOTDEF; - DirectiveKindMapping[".elseif"] = DK_ELSEIF; - DirectiveKindMapping[".else"] = DK_ELSE; - DirectiveKindMapping[".endif"] = DK_ENDIF; -} - /// ParseDirectiveFile /// ::= .file [number] filename /// ::= .file number directory filename -bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveFile(SMLoc DirectiveLoc) { // FIXME: I'm not sure what this is. int64_t FileNumber = -1; SMLoc FileNumberLoc = getLexer().getLoc(); @@ -2981,7 +2495,7 @@ bool GenericAsmParser::ParseDirectiveFile(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveLine /// ::= .line [number] -bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveLine() { if (getLexer().isNot(AsmToken::EndOfStatement)) { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.line' directive"); @@ -2999,7 +2513,6 @@ bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { return false; } - /// ParseDirectiveLoc /// ::= .loc FileNumber [LineNumber] [ColumnPos] [basic_block] [prologue_end] /// [epilogue_begin] [is_stmt VALUE] [isa VALUE] @@ -3007,8 +2520,7 @@ bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) { /// a .file directive, the second number is the line number and optionally the /// third number is a column position (zero if not specified). The remaining /// optional items are .loc sub-directives. -bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { - +bool AsmParser::ParseDirectiveLoc() { if (getLexer().isNot(AsmToken::Integer)) return TokError("unexpected token in '.loc' directive"); int64_t FileNumber = getTok().getIntVal(); @@ -3044,7 +2556,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { StringRef Name; SMLoc Loc = getTok().getLoc(); - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("unexpected token in '.loc' directive"); if (Name == "basic_block") @@ -3056,7 +2568,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { else if (Name == "is_stmt") { Loc = getTok().getLoc(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; // The expression must be the constant 0 or 1. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -3075,7 +2587,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { else if (Name == "isa") { Loc = getTok().getLoc(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; // The expression must be a constant greater or equal to 0. if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) { @@ -3089,7 +2601,7 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { } } else if (Name == "discriminator") { - if (getParser().ParseAbsoluteExpression(Discriminator)) + if (ParseAbsoluteExpression(Discriminator)) return true; } else { @@ -3109,53 +2621,18 @@ bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveStabs /// ::= .stabs string, number, number, number -bool GenericAsmParser::ParseDirectiveStabs(StringRef Directive, - SMLoc DirectiveLoc) { - return TokError("unsupported directive '" + Directive + "'"); -} - -/// ParseDirectiveSpace -/// ::= .space expression [ , expression ] -bool GenericAsmParser::ParseDirectiveSpace(StringRef, SMLoc DirectiveLoc) { - getParser().CheckForValidSection(); - - int64_t NumBytes; - if (getParser().ParseAbsoluteExpression(NumBytes)) - return true; - - int64_t FillExpr = 0; - if (getLexer().isNot(AsmToken::EndOfStatement)) { - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in '.space' directive"); - Lex(); - - if (getParser().ParseAbsoluteExpression(FillExpr)) - return true; - - if (getLexer().isNot(AsmToken::EndOfStatement)) - return TokError("unexpected token in '.space' directive"); - } - - Lex(); - - if (NumBytes <= 0) - return TokError("invalid number of bytes in '.space' directive"); - - // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. - getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); - - return false; +bool AsmParser::ParseDirectiveStabs() { + return TokError("unsupported directive '.stabs'"); } /// ParseDirectiveCFISections /// ::= .cfi_sections section [, section] -bool GenericAsmParser::ParseDirectiveCFISections(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISections() { StringRef Name; bool EH = false; bool Debug = false; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -3166,7 +2643,7 @@ bool GenericAsmParser::ParseDirectiveCFISections(StringRef, if (getLexer().is(AsmToken::Comma)) { Lex(); - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("Expected an identifier"); if (Name == ".eh_frame") @@ -3176,45 +2653,41 @@ bool GenericAsmParser::ParseDirectiveCFISections(StringRef, } getStreamer().EmitCFISections(EH, Debug); - return false; } /// ParseDirectiveCFIStartProc /// ::= .cfi_startproc -bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIStartProc() { getStreamer().EmitCFIStartProc(); return false; } /// ParseDirectiveCFIEndProc /// ::= .cfi_endproc -bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIEndProc() { getStreamer().EmitCFIEndProc(); return false; } /// ParseRegisterOrRegisterNumber - parse register name or number. -bool GenericAsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, - SMLoc DirectiveLoc) { +bool AsmParser::ParseRegisterOrRegisterNumber(int64_t &Register, + SMLoc DirectiveLoc) { unsigned RegNo; if (getLexer().isNot(AsmToken::Integer)) { - if (getParser().getTargetParser().ParseRegister(RegNo, DirectiveLoc, - DirectiveLoc)) + if (getTargetParser().ParseRegister(RegNo, DirectiveLoc, DirectiveLoc)) return true; Register = getContext().getRegisterInfo().getDwarfRegNum(RegNo, true); } else - return getParser().ParseAbsoluteExpression(Register); + return ParseAbsoluteExpression(Register); return false; } /// ParseDirectiveCFIDefCfa /// ::= .cfi_def_cfa register, offset -bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfa(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; @@ -3224,7 +2697,7 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, Lex(); int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfa(Register, Offset); @@ -3233,22 +2706,39 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfa(StringRef, /// ParseDirectiveCFIDefCfaOffset /// ::= .cfi_def_cfa_offset offset -bool GenericAsmParser::ParseDirectiveCFIDefCfaOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfaOffset() { int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIDefCfaOffset(Offset); return false; } +/// ParseDirectiveCFIRegister +/// ::= .cfi_register register, register +bool AsmParser::ParseDirectiveCFIRegister(SMLoc DirectiveLoc) { + int64_t Register1 = 0; + if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Register2 = 0; + if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc)) + return true; + + getStreamer().EmitCFIRegister(Register1, Register2); + return false; +} + /// ParseDirectiveCFIAdjustCfaOffset /// ::= .cfi_adjust_cfa_offset adjustment -bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIAdjustCfaOffset() { int64_t Adjustment = 0; - if (getParser().ParseAbsoluteExpression(Adjustment)) + if (ParseAbsoluteExpression(Adjustment)) return true; getStreamer().EmitCFIAdjustCfaOffset(Adjustment); @@ -3257,8 +2747,7 @@ bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, /// ParseDirectiveCFIDefCfaRegister /// ::= .cfi_def_cfa_register register -bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; @@ -3269,7 +2758,7 @@ bool GenericAsmParser::ParseDirectiveCFIDefCfaRegister(StringRef, /// ParseDirectiveCFIOffset /// ::= .cfi_offset register, offset -bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIOffset(SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; @@ -3280,7 +2769,7 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { return TokError("unexpected token in directive"); Lex(); - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIOffset(Register, Offset); @@ -3289,8 +2778,7 @@ bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { /// ParseDirectiveCFIRelOffset /// ::= .cfi_rel_offset register, offset -bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRelOffset(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) @@ -3301,7 +2789,7 @@ bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, Lex(); int64_t Offset = 0; - if (getParser().ParseAbsoluteExpression(Offset)) + if (ParseAbsoluteExpression(Offset)) return true; getStreamer().EmitCFIRelOffset(Register, Offset); @@ -3331,12 +2819,12 @@ static bool isValidEncoding(int64_t Encoding) { } /// ParseDirectiveCFIPersonalityOrLsda +/// IsPersonality true for cfi_personality, false for cfi_lsda /// ::= .cfi_personality encoding, [symbol_name] /// ::= .cfi_lsda encoding, [symbol_name] -bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIPersonalityOrLsda(bool IsPersonality) { int64_t Encoding = 0; - if (getParser().ParseAbsoluteExpression(Encoding)) + if (ParseAbsoluteExpression(Encoding)) return true; if (Encoding == dwarf::DW_EH_PE_omit) return false; @@ -3349,70 +2837,61 @@ bool GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda(StringRef IDVal, Lex(); StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in directive"); MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); - if (IDVal == ".cfi_personality") + if (IsPersonality) getStreamer().EmitCFIPersonality(Sym, Encoding); - else { - assert(IDVal == ".cfi_lsda"); + else getStreamer().EmitCFILsda(Sym, Encoding); - } return false; } /// ParseDirectiveCFIRememberState /// ::= .cfi_remember_state -bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRememberState() { getStreamer().EmitCFIRememberState(); return false; } /// ParseDirectiveCFIRestoreState /// ::= .cfi_remember_state -bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRestoreState() { getStreamer().EmitCFIRestoreState(); return false; } /// ParseDirectiveCFISameValue /// ::= .cfi_same_value register -bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISameValue(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFISameValue(Register); - return false; } /// ParseDirectiveCFIRestore /// ::= .cfi_restore register -bool GenericAsmParser::ParseDirectiveCFIRestore(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIRestore(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIRestore(Register); - return false; } /// ParseDirectiveCFIEscape /// ::= .cfi_escape expression[,...] -bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIEscape() { std::string Values; int64_t CurrValue; - if (getParser().ParseAbsoluteExpression(CurrValue)) + if (ParseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -3420,7 +2899,7 @@ bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, while (getLexer().is(AsmToken::Comma)) { Lex(); - if (getParser().ParseAbsoluteExpression(CurrValue)) + if (ParseAbsoluteExpression(CurrValue)) return true; Values.push_back((uint8_t)CurrValue); @@ -3432,74 +2911,44 @@ bool GenericAsmParser::ParseDirectiveCFIEscape(StringRef IDVal, /// ParseDirectiveCFISignalFrame /// ::= .cfi_signal_frame -bool GenericAsmParser::ParseDirectiveCFISignalFrame(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFISignalFrame() { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), - "unexpected token in '" + Directive + "' directive"); + "unexpected token in '.cfi_signal_frame'"); getStreamer().EmitCFISignalFrame(); - return false; } /// ParseDirectiveCFIUndefined /// ::= .cfi_undefined register -bool GenericAsmParser::ParseDirectiveCFIUndefined(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveCFIUndefined(SMLoc DirectiveLoc) { int64_t Register = 0; if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; getStreamer().EmitCFIUndefined(Register); - - return false; -} - -/// ParseDirectiveCFIRegister -/// ::= .cfi_register register, register -bool GenericAsmParser::ParseDirectiveCFIRegister(StringRef Directive, - SMLoc DirectiveLoc) { - int64_t Register1 = 0; - - if (ParseRegisterOrRegisterNumber(Register1, DirectiveLoc)) - return true; - - if (getLexer().isNot(AsmToken::Comma)) - return TokError("unexpected token in directive"); - Lex(); - - int64_t Register2 = 0; - - if (ParseRegisterOrRegisterNumber(Register2, DirectiveLoc)) - return true; - - getStreamer().EmitCFIRegister(Register1, Register2); - return false; } /// ParseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off -bool GenericAsmParser::ParseDirectiveMacrosOnOff(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveMacrosOnOff(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return Error(getLexer().getLoc(), "unexpected token in '" + Directive + "' directive"); - getParser().SetMacrosEnabled(Directive == ".macros_on"); - + SetMacrosEnabled(Directive == ".macros_on"); return false; } /// ParseDirectiveMacro /// ::= .macro name [parameters] -bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveMacro(SMLoc DirectiveLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in '.macro' directive"); MCAsmMacroParameters Parameters; @@ -3509,12 +2958,12 @@ bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, if (getLexer().isNot(AsmToken::EndOfStatement)) { for (;;) { MCAsmMacroParameter Parameter; - if (getParser().ParseIdentifier(Parameter.first)) + if (ParseIdentifier(Parameter.first)) return TokError("expected identifier in '.macro' directive"); if (getLexer().is(AsmToken::Equal)) { Lex(); - if (getParser().ParseMacroArgument(Parameter.second, ArgumentDelimiter)) + if (ParseMacroArgument(Parameter.second, ArgumentDelimiter)) return true; } @@ -3551,32 +3000,31 @@ bool GenericAsmParser::ParseDirectiveMacro(StringRef Directive, } // Otherwise, scan til the end of the statement. - getParser().EatToEndOfStatement(); + EatToEndOfStatement(); } - if (getParser().LookupMacro(Name)) { + if (LookupMacro(Name)) { return Error(DirectiveLoc, "macro '" + Name + "' is already defined"); } const char *BodyStart = StartToken.getLoc().getPointer(); const char *BodyEnd = EndToken.getLoc().getPointer(); StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); - getParser().DefineMacro(Name, MCAsmMacro(Name, Body, Parameters)); + DefineMacro(Name, MCAsmMacro(Name, Body, Parameters)); return false; } /// ParseDirectiveEndMacro /// ::= .endm /// ::= .endmacro -bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectiveEndMacro(StringRef Directive) { if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '" + Directive + "' directive"); // If we are inside a macro instantiation, terminate the current // instantiation. - if (getParser().InsideMacroInstantiation()) { - getParser().HandleMacroExit(); + if (InsideMacroInstantiation()) { + HandleMacroExit(); return false; } @@ -3588,34 +3036,136 @@ bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive, /// ParseDirectivePurgeMacro /// ::= .purgem -bool GenericAsmParser::ParseDirectivePurgeMacro(StringRef Directive, - SMLoc DirectiveLoc) { +bool AsmParser::ParseDirectivePurgeMacro(SMLoc DirectiveLoc) { StringRef Name; - if (getParser().ParseIdentifier(Name)) + if (ParseIdentifier(Name)) return TokError("expected identifier in '.purgem' directive"); if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.purgem' directive"); - if (!getParser().LookupMacro(Name)) + if (!LookupMacro(Name)) return Error(DirectiveLoc, "macro '" + Name + "' is not defined"); - getParser().UndefineMacro(Name); + UndefineMacro(Name); return false; } -bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { - getParser().CheckForValidSection(); +/// ParseDirectiveBundleAlignMode +/// ::= {.bundle_align_mode} expression +bool AsmParser::ParseDirectiveBundleAlignMode() { + CheckForValidSection(); + + // Expect a single argument: an expression that evaluates to a constant + // in the inclusive range 0-30. + SMLoc ExprLoc = getLexer().getLoc(); + int64_t AlignSizePow2; + if (ParseAbsoluteExpression(AlignSizePow2)) + return true; + else if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token after expression in" + " '.bundle_align_mode' directive"); + else if (AlignSizePow2 < 0 || AlignSizePow2 > 30) + return Error(ExprLoc, + "invalid bundle alignment size (expected between 0 and 30)"); + + Lex(); + + // Because of AlignSizePow2's verified range we can safely truncate it to + // unsigned. + getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2)); + return false; +} + +/// ParseDirectiveBundleLock +/// ::= {.bundle_lock} [align_to_end] +bool AsmParser::ParseDirectiveBundleLock() { + CheckForValidSection(); + bool AlignToEnd = false; + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + StringRef Option; + SMLoc Loc = getTok().getLoc(); + const char *kInvalidOptionError = + "invalid option for '.bundle_lock' directive"; + + if (ParseIdentifier(Option)) + return Error(Loc, kInvalidOptionError); + + if (Option != "align_to_end") + return Error(Loc, kInvalidOptionError); + else if (getLexer().isNot(AsmToken::EndOfStatement)) + return Error(Loc, + "unexpected token after '.bundle_lock' directive option"); + AlignToEnd = true; + } + + Lex(); + + getStreamer().EmitBundleLock(AlignToEnd); + return false; +} + +/// ParseDirectiveBundleLock +/// ::= {.bundle_lock} +bool AsmParser::ParseDirectiveBundleUnlock() { + CheckForValidSection(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.bundle_unlock' directive"); + Lex(); + + getStreamer().EmitBundleUnlock(); + return false; +} + +/// ParseDirectiveSpace +/// ::= (.skip | .space) expression [ , expression ] +bool AsmParser::ParseDirectiveSpace(StringRef IDVal) { + CheckForValidSection(); + + int64_t NumBytes; + if (ParseAbsoluteExpression(NumBytes)) + return true; + + int64_t FillExpr = 0; + if (getLexer().isNot(AsmToken::EndOfStatement)) { + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + Lex(); + + if (ParseAbsoluteExpression(FillExpr)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Twine(IDVal) + "' directive"); + } + Lex(); + + if (NumBytes <= 0) + return TokError("invalid number of bytes in '" + + Twine(IDVal) + "' directive"); + + // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0. + getStreamer().EmitFill(NumBytes, FillExpr, DEFAULT_ADDRSPACE); + + return false; +} + +/// ParseDirectiveLEB128 +/// ::= (.sleb128 | .uleb128) expression +bool AsmParser::ParseDirectiveLEB128(bool Signed) { + CheckForValidSection(); const MCExpr *Value; - if (getParser().ParseExpression(Value)) + if (ParseExpression(Value)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - if (DirName[1] == 's') + if (Signed) getStreamer().EmitSLEB128Value(Value); else getStreamer().EmitULEB128Value(Value); @@ -3623,6 +3173,468 @@ bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) { return false; } +/// ParseDirectiveSymbolAttribute +/// ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ] +bool AsmParser::ParseDirectiveSymbolAttribute(MCSymbolAttr Attr) { + if (getLexer().isNot(AsmToken::EndOfStatement)) { + for (;;) { + StringRef Name; + SMLoc Loc = getTok().getLoc(); + + if (ParseIdentifier(Name)) + return Error(Loc, "expected identifier in directive"); + + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + // Assembler local symbols don't make any sense here. Complain loudly. + if (Sym->isTemporary()) + return Error(Loc, "non-local symbol required in directive"); + + getStreamer().EmitSymbolAttribute(Sym, Attr); + + if (getLexer().is(AsmToken::EndOfStatement)) + break; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + } + } + + Lex(); + return false; +} + +/// ParseDirectiveComm +/// ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ] +bool AsmParser::ParseDirectiveComm(bool IsLocal) { + CheckForValidSection(); + + SMLoc IDLoc = getLexer().getLoc(); + StringRef Name; + if (ParseIdentifier(Name)) + return TokError("expected identifier in directive"); + + // Handle the identifier as the key symbol. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Size; + SMLoc SizeLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + Pow2AlignmentLoc = getLexer().getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + + LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType(); + if (IsLocal && LCOMM == LCOMM::NoAlignment) + return Error(Pow2AlignmentLoc, "alignment not supported on this target"); + + // If this target takes alignments in bytes (not log) validate and convert. + if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) || + (IsLocal && LCOMM == LCOMM::ByteAlignment)) { + if (!isPowerOf2_64(Pow2Alignment)) + return Error(Pow2AlignmentLoc, "alignment must be a power of 2"); + Pow2Alignment = Log2_64(Pow2Alignment); + } + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.comm' or '.lcomm' directive"); + + Lex(); + + // NOTE: a size of zero for a .comm should create a undefined symbol + // but a size of .lcomm creates a bss symbol of size zero. + if (Size < 0) + return Error(SizeLoc, "invalid '.comm' or '.lcomm' directive size, can't " + "be less than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assembler + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive " + "alignment, can't be less than zero"); + + if (!Sym->isUndefined()) + return Error(IDLoc, "invalid symbol redefinition"); + + // Create the Symbol as a common or local common with Size and Pow2Alignment + if (IsLocal) { + getStreamer().EmitLocalCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; + } + + getStreamer().EmitCommonSymbol(Sym, Size, 1 << Pow2Alignment); + return false; +} + +/// ParseDirectiveAbort +/// ::= .abort [... message ...] +bool AsmParser::ParseDirectiveAbort() { + // FIXME: Use loc from directive. + SMLoc Loc = getLexer().getLoc(); + + StringRef Str = ParseStringToEndOfStatement(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.abort' directive"); + + Lex(); + + if (Str.empty()) + Error(Loc, ".abort detected. Assembly stopping."); + else + Error(Loc, ".abort '" + Str + "' detected. Assembly stopping."); + // FIXME: Actually abort assembly here. + + return false; +} + +/// ParseDirectiveInclude +/// ::= .include "filename" +bool AsmParser::ParseDirectiveInclude() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.include' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncludeLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.include' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to switch the lexer to the included file before consuming the end + // of statement to avoid losing it when we switch. + if (EnterIncludeFile(Filename)) { + Error(IncludeLoc, "Could not find include file '" + Filename + "'"); + return true; + } + + return false; +} + +/// ParseDirectiveIncbin +/// ::= .incbin "filename" +bool AsmParser::ParseDirectiveIncbin() { + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in '.incbin' directive"); + + std::string Filename = getTok().getString(); + SMLoc IncbinLoc = getLexer().getLoc(); + Lex(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.incbin' directive"); + + // Strip the quotes. + Filename = Filename.substr(1, Filename.size()-2); + + // Attempt to process the included file. + if (ProcessIncbinFile(Filename)) { + Error(IncbinLoc, "Could not find incbin file '" + Filename + "'"); + return true; + } + + return false; +} + +/// ParseDirectiveIf +/// ::= .if expression +bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.if' directive"); + + Lex(); + + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfb +/// ::= .ifb string +bool AsmParser::ParseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + StringRef Str = ParseStringToEndOfStatement(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ifb' directive"); + + Lex(); + + TheCondState.CondMet = ExpectBlank == Str.empty(); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfc +/// ::= .ifc string1, string2 +bool AsmParser::ParseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) { + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + StringRef Str1 = ParseStringToComma(); + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in '.ifc' directive"); + + Lex(); + + StringRef Str2 = ParseStringToEndOfStatement(); + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.ifc' directive"); + + Lex(); + + TheCondState.CondMet = ExpectEqual == (Str1 == Str2); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveIfdef +/// ::= .ifdef symbol +bool AsmParser::ParseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) { + StringRef Name; + TheCondStack.push_back(TheCondState); + TheCondState.TheCond = AsmCond::IfCond; + + if (TheCondState.Ignore) { + EatToEndOfStatement(); + } else { + if (ParseIdentifier(Name)) + return TokError("expected identifier after '.ifdef'"); + + Lex(); + + MCSymbol *Sym = getContext().LookupSymbol(Name); + + if (expect_defined) + TheCondState.CondMet = (Sym != NULL && !Sym->isUndefined()); + else + TheCondState.CondMet = (Sym == NULL || Sym->isUndefined()); + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElseIf +/// ::= .elseif expression +bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .elseif that doesn't follow a .if or " + " an .elseif"); + TheCondState.TheCond = AsmCond::ElseIfCond; + + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) { + TheCondState.Ignore = true; + EatToEndOfStatement(); + } + else { + int64_t ExprValue; + if (ParseAbsoluteExpression(ExprValue)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.elseif' directive"); + + Lex(); + TheCondState.CondMet = ExprValue; + TheCondState.Ignore = !TheCondState.CondMet; + } + + return false; +} + +/// ParseDirectiveElse +/// ::= .else +bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.else' directive"); + + Lex(); + + if (TheCondState.TheCond != AsmCond::IfCond && + TheCondState.TheCond != AsmCond::ElseIfCond) + Error(DirectiveLoc, "Encountered a .else that doesn't follow a .if or an " + ".elseif"); + TheCondState.TheCond = AsmCond::ElseCond; + bool LastIgnoreState = false; + if (!TheCondStack.empty()) + LastIgnoreState = TheCondStack.back().Ignore; + if (LastIgnoreState || TheCondState.CondMet) + TheCondState.Ignore = true; + else + TheCondState.Ignore = false; + + return false; +} + +/// ParseDirectiveEndIf +/// ::= .endif +bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '.endif' directive"); + + Lex(); + + if ((TheCondState.TheCond == AsmCond::NoCond) || + TheCondStack.empty()) + Error(DirectiveLoc, "Encountered a .endif that doesn't follow a .if or " + ".else"); + if (!TheCondStack.empty()) { + TheCondState = TheCondStack.back(); + TheCondStack.pop_back(); + } + + return false; +} + +void AsmParser::initializeDirectiveKindMap() { + DirectiveKindMap[".set"] = DK_SET; + DirectiveKindMap[".equ"] = DK_EQU; + DirectiveKindMap[".equiv"] = DK_EQUIV; + DirectiveKindMap[".ascii"] = DK_ASCII; + DirectiveKindMap[".asciz"] = DK_ASCIZ; + DirectiveKindMap[".string"] = DK_STRING; + DirectiveKindMap[".byte"] = DK_BYTE; + DirectiveKindMap[".short"] = DK_SHORT; + DirectiveKindMap[".value"] = DK_VALUE; + DirectiveKindMap[".2byte"] = DK_2BYTE; + DirectiveKindMap[".long"] = DK_LONG; + DirectiveKindMap[".int"] = DK_INT; + DirectiveKindMap[".4byte"] = DK_4BYTE; + DirectiveKindMap[".quad"] = DK_QUAD; + DirectiveKindMap[".8byte"] = DK_8BYTE; + DirectiveKindMap[".single"] = DK_SINGLE; + DirectiveKindMap[".float"] = DK_FLOAT; + DirectiveKindMap[".double"] = DK_DOUBLE; + DirectiveKindMap[".align"] = DK_ALIGN; + DirectiveKindMap[".align32"] = DK_ALIGN32; + DirectiveKindMap[".balign"] = DK_BALIGN; + DirectiveKindMap[".balignw"] = DK_BALIGNW; + DirectiveKindMap[".balignl"] = DK_BALIGNL; + DirectiveKindMap[".p2align"] = DK_P2ALIGN; + DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW; + DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL; + DirectiveKindMap[".org"] = DK_ORG; + DirectiveKindMap[".fill"] = DK_FILL; + DirectiveKindMap[".zero"] = DK_ZERO; + DirectiveKindMap[".extern"] = DK_EXTERN; + DirectiveKindMap[".globl"] = DK_GLOBL; + DirectiveKindMap[".global"] = DK_GLOBAL; + DirectiveKindMap[".indirect_symbol"] = DK_INDIRECT_SYMBOL; + DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE; + DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP; + DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER; + DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN; + DirectiveKindMap[".reference"] = DK_REFERENCE; + DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION; + DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE; + DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN; + DirectiveKindMap[".comm"] = DK_COMM; + DirectiveKindMap[".common"] = DK_COMMON; + DirectiveKindMap[".lcomm"] = DK_LCOMM; + DirectiveKindMap[".abort"] = DK_ABORT; + DirectiveKindMap[".include"] = DK_INCLUDE; + DirectiveKindMap[".incbin"] = DK_INCBIN; + DirectiveKindMap[".code16"] = DK_CODE16; + DirectiveKindMap[".code16gcc"] = DK_CODE16GCC; + DirectiveKindMap[".rept"] = DK_REPT; + DirectiveKindMap[".irp"] = DK_IRP; + DirectiveKindMap[".irpc"] = DK_IRPC; + DirectiveKindMap[".endr"] = DK_ENDR; + DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE; + DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK; + DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK; + DirectiveKindMap[".if"] = DK_IF; + DirectiveKindMap[".ifb"] = DK_IFB; + DirectiveKindMap[".ifnb"] = DK_IFNB; + DirectiveKindMap[".ifc"] = DK_IFC; + DirectiveKindMap[".ifnc"] = DK_IFNC; + DirectiveKindMap[".ifdef"] = DK_IFDEF; + DirectiveKindMap[".ifndef"] = DK_IFNDEF; + DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF; + DirectiveKindMap[".elseif"] = DK_ELSEIF; + DirectiveKindMap[".else"] = DK_ELSE; + DirectiveKindMap[".endif"] = DK_ENDIF; + DirectiveKindMap[".skip"] = DK_SKIP; + DirectiveKindMap[".space"] = DK_SPACE; + DirectiveKindMap[".file"] = DK_FILE; + DirectiveKindMap[".line"] = DK_LINE; + DirectiveKindMap[".loc"] = DK_LOC; + DirectiveKindMap[".stabs"] = DK_STABS; + DirectiveKindMap[".sleb128"] = DK_SLEB128; + DirectiveKindMap[".uleb128"] = DK_ULEB128; + DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS; + DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC; + DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC; + DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA; + DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET; + DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET; + DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER; + DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET; + DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET; + DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY; + DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA; + DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE; + DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE; + DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE; + DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE; + DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE; + DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME; + DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED; + DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER; + DirectiveKindMap[".macros_on"] = DK_MACROS_ON; + DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; + DirectiveKindMap[".macro"] = DK_MACRO; + DirectiveKindMap[".endm"] = DK_ENDM; + DirectiveKindMap[".endmacro"] = DK_ENDMACRO; + DirectiveKindMap[".purgem"] = DK_PURGEM; +} + + MCAsmMacro *AsmParser::ParseMacroLikeBody(SMLoc DirectiveLoc) { AsmToken EndToken, StartToken = getTok(); |