ARM: allow .thumb_func to be separated from symbol definition

When assembling, a .thumb_func directive is supposed to be applicable to the
next symbol definition, even if there are intervening directives. We were
racing ahead to try and find it, and this commit should fix the issue.

Patch by Gabor Ballabas

llvm-svn: 193403
This commit is contained in:
Tim Northover 2013-10-25 12:49:50 +00:00
parent 2eac89868c
commit 1744d0ad83
4 changed files with 23 additions and 18 deletions

View File

@ -181,6 +181,8 @@ public:
MCContext &Ctx) { MCContext &Ctx) {
return 0; return 0;
} }
virtual void onLabelParsed(MCSymbol *Symbol) { };
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -1262,6 +1262,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) {
MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(), MCGenDwarfLabelEntry::Make(Sym, &getStreamer(), getSourceManager(),
IDLoc); IDLoc);
getTargetParser().onLabelParsed(Sym);
// Consume any end of statement token, if present, to avoid spurious // Consume any end of statement token, if present, to avoid spurious
// AddBlankLine calls(). // AddBlankLine calls().
if (Lexer.is(AsmToken::EndOfStatement)) { if (Lexer.is(AsmToken::EndOfStatement)) {

View File

@ -74,6 +74,8 @@ class ARMAsmParser : public MCTargetAsmParser {
// Map of register aliases registers via the .req directive. // Map of register aliases registers via the .req directive.
StringMap<unsigned> RegisterReqs; StringMap<unsigned> RegisterReqs;
bool NextSymbolIsThumb;
struct { struct {
ARMCC::CondCodes Cond; // Condition for IT block. ARMCC::CondCodes Cond; // Condition for IT block.
unsigned Mask:4; // Condition mask for instructions. unsigned Mask:4; // Condition mask for instructions.
@ -268,6 +270,8 @@ public:
// Not in an ITBlock to start with. // Not in an ITBlock to start with.
ITState.CurPosition = ~0U; ITState.CurPosition = ~0U;
NextSymbolIsThumb = false;
} }
// Implementation of the MCTargetAsmParser interface: // Implementation of the MCTargetAsmParser interface:
@ -284,6 +288,8 @@ public:
SmallVectorImpl<MCParsedAsmOperand*> &Operands, SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo, MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm); bool MatchingInlineAsm);
void onLabelParsed(MCSymbol *Symbol);
}; };
} // end anonymous namespace } // end anonymous namespace
@ -7837,13 +7843,18 @@ bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
return false; return false;
} }
void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
if (NextSymbolIsThumb) {
getParser().getStreamer().EmitThumbFunc(Symbol);
NextSymbolIsThumb = false;
}
}
/// parseDirectiveThumbFunc /// parseDirectiveThumbFunc
/// ::= .thumbfunc symbol_name /// ::= .thumbfunc symbol_name
bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) { bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo(); const MCAsmInfo *MAI = getParser().getStreamer().getContext().getAsmInfo();
bool isMachO = MAI->hasSubsectionsViaSymbols(); bool isMachO = MAI->hasSubsectionsViaSymbols();
StringRef Name;
bool needFuncName = true;
// Darwin asm has (optionally) function name after .thumb_func direction // Darwin asm has (optionally) function name after .thumb_func direction
// ELF doesn't // ELF doesn't
@ -7852,29 +7863,19 @@ bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
if (Tok.isNot(AsmToken::EndOfStatement)) { if (Tok.isNot(AsmToken::EndOfStatement)) {
if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
return Error(L, "unexpected token in .thumb_func directive"); return Error(L, "unexpected token in .thumb_func directive");
Name = Tok.getIdentifier(); MCSymbol *Func =
getParser().getContext().GetOrCreateSymbol(Tok.getIdentifier());
getParser().getStreamer().EmitThumbFunc(Func);
Parser.Lex(); // Consume the identifier token. Parser.Lex(); // Consume the identifier token.
needFuncName = false; return false;
} }
} }
if (getLexer().isNot(AsmToken::EndOfStatement)) if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(L, "unexpected token in directive"); return Error(L, "unexpected token in directive");
// Eat the end of statement and any blank lines that follow. NextSymbolIsThumb = true;
while (getLexer().is(AsmToken::EndOfStatement))
Parser.Lex();
// FIXME: assuming function name will be the line following .thumb_func
// We really should be checking the next symbol definition even if there's
// stuff in between.
if (needFuncName) {
Name = Parser.getTok().getIdentifier();
}
// Mark symbol as a thumb symbol.
MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
getParser().getStreamer().EmitThumbFunc(Func);
return false; return false;
} }

View File

@ -5,9 +5,9 @@
.text .text
.globl foo .globl foo
.align 2 .align 2
.type foo,%function
.code 16 .code 16
.thumb_func .thumb_func
.type foo,%function
foo: foo:
bx lr bx lr