diff options
author | Jason W Kim <jason.w.kim.2009@gmail.com> | 2011-01-11 23:53:41 +0000 |
---|---|---|
committer | Jason W Kim <jason.w.kim.2009@gmail.com> | 2011-01-11 23:53:41 +0000 |
commit | 9081b4b4cf89a161246e037f4817c69de2fcdf82 (patch) | |
tree | 6bd034b86d24ae18940c927a145bb26c9a88a97e | |
parent | 2df5458535c54c1e214da65191ef86c38b57da39 (diff) | |
download | llvm-9081b4b4cf89a161246e037f4817c69de2fcdf82.tar.gz llvm-9081b4b4cf89a161246e037f4817c69de2fcdf82.tar.bz2 llvm-9081b4b4cf89a161246e037f4817c69de2fcdf82.tar.xz |
Workaround for bug 8721.
.s Test added.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@123292 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 106 | ||||
-rw-r--r-- | test/MC/ARM/elf-movt.s | 14 |
2 files changed, 120 insertions, 0 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 190be65121..b51e351172 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -55,6 +55,10 @@ class ARMAsmParser : public TargetAsmParser { bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &); bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &); + bool ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind); + const MCExpr *ApplyPrefixToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind Variant); + bool ParseMemoryOffsetReg(bool &Negative, bool &OffsetRegShifted, @@ -864,9 +868,111 @@ bool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands){ E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); return false; + case AsmToken::Colon: { + // ":lower16:" and ":upper16:" expression prefixes + MCSymbolRefExpr::VariantKind RefKind; + if (ParsePrefix(RefKind)) + return true; + + const MCExpr *ExprVal; + if (getParser().ParseExpression(ExprVal)) + return true; + + // TODO: Attach the prefix to the entire expression + // instead of just the first symbol. + const MCExpr *ModExprVal = ApplyPrefixToExpr(ExprVal, RefKind); + if (!ModExprVal) { + return TokError("invalid modifier '" + getTok().getIdentifier() + + "' (no symbols present)"); + } + + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(ARMOperand::CreateImm(ModExprVal, S, E)); + return false; + } } } +// FIXME: The next 2 routines are hacks to get ARMAsmParser to understand +// :lower16: and :upper16: +// It still attaches VK_ARM_HI/LO16 to MCSymbolRefExpr, but it really +// should be attached to the entire MCExpr as a whole - perhaps using +// MCTargetExpr? +bool ARMAsmParser::ParsePrefix(MCSymbolRefExpr::VariantKind &RefKind) { + RefKind = MCSymbolRefExpr::VK_None; + + // :lower16: and :upper16: modifiers + if (getLexer().isNot(AsmToken::Colon)) { + Error(Parser.getTok().getLoc(), "expected :"); + return true; + } + Parser.Lex(); // Eat ':' + + if (getLexer().isNot(AsmToken::Identifier)) { + Error(Parser.getTok().getLoc(), "expected prefix identifier in operand"); + return true; + } + + StringRef IDVal = Parser.getTok().getIdentifier(); + if (IDVal == "lower16") { + RefKind = MCSymbolRefExpr::VK_ARM_LO16; + } else if (IDVal == "upper16") { + RefKind = MCSymbolRefExpr::VK_ARM_HI16; + } else { + Error(Parser.getTok().getLoc(), "unexpected prefix in operand"); + return true; + } + Parser.Lex(); + + if (getLexer().isNot(AsmToken::Colon)) { + Error(Parser.getTok().getLoc(), "unexpected token after prefix"); + return true; + } + Parser.Lex(); // Eat the last ':' + return false; +} + +const MCExpr * +ARMAsmParser::ApplyPrefixToExpr(const MCExpr *E, + MCSymbolRefExpr::VariantKind Variant) { + // Recurse over the given expression, rebuilding it to apply the given variant + // to the leftmost symbol. + if (Variant == MCSymbolRefExpr::VK_None) + return E; + + switch (E->getKind()) { + case MCExpr::Target: + llvm_unreachable("Can't handle target expr yet"); + case MCExpr::Constant: + llvm_unreachable("Can't handle lower16/upper16 of constant yet"); + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E); + + if (SRE->getKind() != MCSymbolRefExpr::VK_None) + return 0; + + return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext()); + } + + case MCExpr::Unary: + llvm_unreachable("Can't handle unary expressions yet"); + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(E); + const MCExpr *LHS = ApplyPrefixToExpr(BE->getLHS(), Variant); + const MCExpr *RHS = BE->getRHS(); + if (!LHS) + return 0; + + return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext()); + } + } + + assert(0 && "Invalid expression kind!"); + return 0; +} + /// \brief Given a mnemonic, split out possible predication code and carry /// setting letters to form a canonical mnemonic and flags. // diff --git a/test/MC/ARM/elf-movt.s b/test/MC/ARM/elf-movt.s new file mode 100644 index 0000000000..51c54298de --- /dev/null +++ b/test/MC/ARM/elf-movt.s @@ -0,0 +1,14 @@ +@ RUN: llvm-mc %s -triple=armv7-linux-gnueabi | FileCheck -check-prefix=ASM %s + .syntax unified + .text + .globl barf + .align 2 + .type barf,%function +barf: @ @barf +@ BB#0: @ %entry + movw r0, :lower16:GOT-(.LPC0_2+8) + movt r0, :upper16:GOT-(.LPC0_2+16) +.LPC0_2: +@ ASM: movw r0, :lower16:GOT-(.LPC0_2+8) +@ ASM-NEXT: movt r0, :upper16:GOT-(.LPC0_2+16) + |