diff options
Diffstat (limited to 'lib/MC/MCParser')
-rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 5 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 211 |
2 files changed, 82 insertions, 134 deletions
diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 22c8d76..1183312 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -74,6 +74,11 @@ AsmToken AsmLexer::LexIdentifier() { while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' || *CurPtr == '.' || *CurPtr == '@') ++CurPtr; + + // Handle . as a special case. + if (CurPtr == TokStart+1 && TokStart[0] == '.') + return AsmToken(AsmToken::Dot, StringRef(TokStart, 1)); + return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart)); } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 4e62689..a63d2e4 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -30,16 +30,10 @@ using namespace llvm; enum { DEFAULT_ADDRSPACE = 0 }; -// Mach-O section uniquing. -// -// FIXME: Figure out where this should live, it should be shared by -// TargetLoweringObjectFile. -typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; - AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0), - CurBuffer(0), SectionUniquingMap(0) { + CurBuffer(0) { Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); // Debugging directives. @@ -51,39 +45,6 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, AsmParser::~AsmParser() { - // If we have the MachO uniquing map, free it. - delete (MachOUniqueMapTy*)SectionUniquingMap; -} - -const MCSection *AsmParser::getMachOSection(const StringRef &Segment, - const StringRef &Section, - unsigned TypeAndAttributes, - unsigned Reserved2, - SectionKind Kind) const { - // We unique sections by their segment/section pair. The returned section - // may not have the same flags as the requested section, if so this should be - // diagnosed by the client as an error. - - // Create the map if it doesn't already exist. - if (SectionUniquingMap == 0) - SectionUniquingMap = new MachOUniqueMapTy(); - MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap; - - // Form the name to look up. - SmallString<64> Name; - Name += Segment; - Name.push_back(','); - Name += Section; - - // Do the lookup, if we have a hit, return it. - const MCSectionMachO *&Entry = Map[Name.str()]; - - // FIXME: This should validate the type and attributes. - if (Entry) return Entry; - - // Otherwise, return a new section. - return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, - Reserved2, Kind, Ctx); } void AsmParser::Warning(SMLoc L, const Twine &Msg) { @@ -143,7 +104,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // // FIXME: Target hook & command line option for initial section. if (!NoInitialTextSection) - Out.SwitchSection(getMachOSection("__TEXT", "__text", + Out.SwitchSection(Ctx.getMachOSection("__TEXT", "__text", MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 0, SectionKind::getText())); @@ -156,29 +117,6 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { - // Handle conditional assembly here before calling ParseStatement() - if (Lexer.getKind() == AsmToken::Identifier) { - // If we have an identifier, handle it as the key symbol. - AsmToken ID = getTok(); - SMLoc IDLoc = ID.getLoc(); - StringRef IDVal = ID.getString(); - - if (IDVal == ".if" || - IDVal == ".elseif" || - IDVal == ".else" || - IDVal == ".endif") { - if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc)) - continue; - HadError = true; - EatToEndOfStatement(); - continue; - } - } - if (TheCondState.Ignore) { - EatToEndOfStatement(); - continue; - } - if (!ParseStatement()) continue; // We had an error, remember it and recover by skipping to the next line. @@ -198,21 +136,6 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { return HadError; } -/// ParseConditionalAssemblyDirectives - parse the conditional assembly -/// directives -bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive, - SMLoc DirectiveLoc) { - if (Directive == ".if") - return ParseDirectiveIf(DirectiveLoc); - if (Directive == ".elseif") - return ParseDirectiveElseIf(DirectiveLoc); - if (Directive == ".else") - return ParseDirectiveElse(DirectiveLoc); - if (Directive == ".endif") - return ParseDirectiveEndIf(DirectiveLoc); - return true; -} - /// EatToEndOfStatement - Throw away the rest of the line for testing purposes. void AsmParser::EatToEndOfStatement() { while (Lexer.isNot(AsmToken::EndOfStatement) && @@ -248,6 +171,7 @@ MCSymbol *AsmParser::CreateSymbol(StringRef Name) { /// primaryexpr ::= (parenexpr /// primaryexpr ::= symbol /// primaryexpr ::= number +/// primaryexpr ::= '.' /// primaryexpr ::= ~,+,- primaryexpr bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { switch (Lexer.getKind()) { @@ -292,6 +216,17 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { EndLoc = Lexer.getLoc(); Lex(); // Eat token. return false; + case AsmToken::Dot: { + // This is a '.' reference, which references the current PC. Emit a + // temporary label to the streamer and refer to it. + MCSymbol *Sym = Ctx.CreateTempSymbol(); + Out.EmitLabel(Sym); + Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. + return false; + } + case AsmToken::LParen: Lex(); // Eat the '('. return ParseParenExpr(Res, EndLoc); @@ -484,9 +419,30 @@ bool AsmParser::ParseStatement() { AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal; - if (ParseIdentifier(IDVal)) - return TokError("unexpected token at start of statement"); + if (ParseIdentifier(IDVal)) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + IDVal = ""; + } + // Handle conditional assembly here before checking for skipping. We + // have to do this so that .endif isn't skipped in a ".if 0" block for + // example. + if (IDVal == ".if") + return ParseDirectiveIf(IDLoc); + if (IDVal == ".elseif") + return ParseDirectiveElseIf(IDLoc); + if (IDVal == ".else") + return ParseDirectiveElse(IDLoc); + if (IDVal == ".endif") + return ParseDirectiveEndIf(IDLoc); + + // If we are in a ".if 0" block, ignore this statement. + if (TheCondState.Ignore) { + EatToEndOfStatement(); + return false; + } + // FIXME: Recurse on local labels? // See what kind of statement we have. @@ -773,39 +729,38 @@ bool AsmParser::ParseStatement() { return false; } - SmallVector<MCParsedAsmOperand*, 8> ParsedOperands; - if (getTargetParser().ParseInstruction(IDVal, IDLoc, ParsedOperands)) - // FIXME: Leaking ParsedOperands on failure. - return true; - - if (Lexer.isNot(AsmToken::EndOfStatement)) - // FIXME: Leaking ParsedOperands on failure. - return TokError("unexpected token in argument list"); - - // Eat the end of statement marker. - Lex(); - - - MCInst Inst; + bool HadError = getTargetParser().ParseInstruction(IDVal, IDLoc, + ParsedOperands); + if (!HadError && Lexer.isNot(AsmToken::EndOfStatement)) + HadError = TokError("unexpected token in argument list"); + + // If parsing succeeded, match the instruction. + if (!HadError) { + MCInst Inst; + if (!getTargetParser().MatchInstruction(ParsedOperands, Inst)) { + // Emit the instruction on success. + Out.EmitInstruction(Inst); + } else { + // Otherwise emit a diagnostic about the match failure and set the error + // flag. + // + // FIXME: We should give nicer diagnostics about the exact failure. + Error(IDLoc, "unrecognized instruction"); + HadError = true; + } + } - bool MatchFail = getTargetParser().MatchInstruction(ParsedOperands, Inst); + // If there was no error, consume the end-of-statement token. Otherwise this + // will be done by our caller. + if (!HadError) + Lex(); // Free any parsed operands. for (unsigned i = 0, e = ParsedOperands.size(); i != e; ++i) delete ParsedOperands[i]; - if (MatchFail) { - // FIXME: We should give nicer diagnostics about the exact failure. - Error(IDLoc, "unrecognized instruction"); - return true; - } - - // Instruction is good, process it. - Out.EmitInstruction(Inst); - - // Skip to end of line for now. - return false; + return HadError; } bool AsmParser::ParseAssignment(const StringRef &Name) { @@ -919,9 +874,9 @@ bool AsmParser::ParseDirectiveDarwinSection() { // FIXME: Arch specific. bool isText = Segment == "__TEXT"; // FIXME: Hack. - Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, - isText ? SectionKind::getText() - : SectionKind::getDataRel())); + Out.SwitchSection(Ctx.getMachOSection(Segment, Section, TAA, StubSize, + isText ? SectionKind::getText() + : SectionKind::getDataRel())); return false; } @@ -936,9 +891,9 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, // FIXME: Arch specific. bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack. - Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, - isText ? SectionKind::getText() - : SectionKind::getDataRel())); + Out.SwitchSection(Ctx.getMachOSection(Segment, Section, TAA, StubSize, + isText ? SectionKind::getText() + : SectionKind::getDataRel())); // Set the implicit alignment, if any. // @@ -1374,9 +1329,9 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { // '.lcomm' is equivalent to '.zerofill'. // Create the Symbol as a common or local common with Size and Pow2Alignment if (IsLocal) { - Out.EmitZerofill(getMachOSection("__DATA", "__bss", - MCSectionMachO::S_ZEROFILL, 0, - SectionKind::getBSS()), + Out.EmitZerofill(Ctx.getMachOSection("__DATA", "__bss", + MCSectionMachO::S_ZEROFILL, 0, + SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; } @@ -1410,9 +1365,9 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { // the section but with no symbol. if (Lexer.is(AsmToken::EndOfStatement)) { // Create the zerofill section but no symbol - Out.EmitZerofill(getMachOSection(Segment, Section, - MCSectionMachO::S_ZEROFILL, 0, - SectionKind::getBSS())); + Out.EmitZerofill(Ctx.getMachOSection(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind::getBSS())); return false; } @@ -1468,9 +1423,9 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { // Create the zerofill Symbol with Size and Pow2Alignment // // FIXME: Arch specific. - Out.EmitZerofill(getMachOSection(Segment, Section, - MCSectionMachO::S_ZEROFILL, 0, - SectionKind::getBSS()), + Out.EmitZerofill(Ctx.getMachOSection(Segment, Section, + MCSectionMachO::S_ZEROFILL, 0, + SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; @@ -1604,9 +1559,6 @@ bool AsmParser::ParseDirectiveDarwinDumpOrLoad(SMLoc IDLoc, bool IsDump) { /// ParseDirectiveIf /// ::= .if expression bool AsmParser::ParseDirectiveIf(SMLoc DirectiveLoc) { - // Consume the identifier that was the .if directive - Lex(); - TheCondStack.push_back(TheCondState); TheCondState.TheCond = AsmCond::IfCond; if(TheCondState.Ignore) { @@ -1638,9 +1590,6 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { " an .elseif"); TheCondState.TheCond = AsmCond::ElseIfCond; - // Consume the identifier that was the .elseif directive - Lex(); - bool LastIgnoreState = false; if (!TheCondStack.empty()) LastIgnoreState = TheCondStack.back().Ignore; @@ -1667,9 +1616,6 @@ bool AsmParser::ParseDirectiveElseIf(SMLoc DirectiveLoc) { /// ParseDirectiveElse /// ::= .else bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { - // Consume the identifier that was the .else directive - Lex(); - if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.else' directive"); @@ -1694,9 +1640,6 @@ bool AsmParser::ParseDirectiveElse(SMLoc DirectiveLoc) { /// ParseDirectiveEndIf /// ::= .endif bool AsmParser::ParseDirectiveEndIf(SMLoc DirectiveLoc) { - // Consume the identifier that was the .endif directive - Lex(); - if (Lexer.isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in '.endif' directive"); |