diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2010-07-17 04:29:04 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2010-07-17 04:29:04 +0000 |
commit | 21444efae03be297faf5bdb8f16567765307fa9d (patch) | |
tree | 287986462601674a10e189a68021c6759882ab4f /lib/MC/MCParser/ELFAsmParser.cpp | |
parent | 5423856e44a7e4b173af211b0fb0675c44945a58 (diff) |
Work-in-progress parsing for ELF .section directive.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108609 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCParser/ELFAsmParser.cpp')
-rw-r--r-- | lib/MC/MCParser/ELFAsmParser.cpp | 118 |
1 files changed, 113 insertions, 5 deletions
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index f87031860e..340af23cf9 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCParser/MCAsmParserExtension.h" -#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCStreamer.h" using namespace llvm; namespace { @@ -31,8 +32,10 @@ public: &ELFAsmParser::ParseSectionDirectiveData)); Parser.AddDirectiveHandler(this, ".text", MCAsmParser::DirectiveHandler( &ELFAsmParser::ParseSectionDirectiveText)); + Parser.AddDirectiveHandler(this, ".section", MCAsmParser::DirectiveHandler( + &ELFAsmParser::ParseDirectiveSection)); Parser.AddDirectiveHandler(this, ".size", MCAsmParser::DirectiveHandler( - &ELFAsmParser::ParseSizeDirective)); + &ELFAsmParser::ParseDirectiveSize)); } bool ParseSectionDirectiveData(StringRef, SMLoc) { @@ -45,7 +48,8 @@ public: MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, SectionKind::getText()); } - bool ParseSizeDirective(StringRef, SMLoc); + bool ParseDirectiveSection(StringRef, SMLoc); + bool ParseDirectiveSize(StringRef, SMLoc); }; } @@ -62,7 +66,7 @@ bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type, return false; } -bool ELFAsmParser::ParseSizeDirective(StringRef, SMLoc) { +bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) { StringRef Name; if (getParser().ParseIdentifier(Name)) return TokError("expected identifier in directive"); @@ -83,6 +87,110 @@ bool ELFAsmParser::ParseSizeDirective(StringRef, SMLoc) { return false; } +// FIXME: This is a work in progress. +bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { + StringRef SectionName; + // FIXME: This doesn't parse section names like ".note.GNU-stack" correctly. + if (getParser().ParseIdentifier(SectionName)) + return TokError("expected identifier in directive"); + + std::string FlagsStr; + StringRef TypeName; + int64_t Size = 0; + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getLexer().isNot(AsmToken::String)) + return TokError("expected string in directive"); + + FlagsStr = getTok().getStringContents(); + Lex(); + + AsmToken::TokenKind TypeStartToken; + if (getContext().getAsmInfo().getCommentString()[0] == '@') + TypeStartToken = AsmToken::Percent; + else + TypeStartToken = AsmToken::At; + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + if (getLexer().is(TypeStartToken)) { + Lex(); + if (getParser().ParseIdentifier(TypeName)) + return TokError("expected identifier in directive"); + + if (getLexer().is(AsmToken::Comma)) { + Lex(); + + if (getParser().ParseAbsoluteExpression(Size)) + return true; + + if (Size <= 0) + return TokError("section size must be positive"); + } + } + } + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + unsigned Flags = 0; + for (unsigned i = 0; i < FlagsStr.size(); i++) { + switch (FlagsStr[i]) { + case 'a': + Flags |= MCSectionELF::SHF_ALLOC; + break; + case 'x': + Flags |= MCSectionELF::SHF_EXECINSTR; + break; + case 'w': + Flags |= MCSectionELF::SHF_WRITE; + break; + case 'M': + Flags |= MCSectionELF::SHF_MERGE; + break; + case 'S': + Flags |= MCSectionELF::SHF_STRINGS; + break; + case 'T': + Flags |= MCSectionELF::SHF_TLS; + break; + case 'c': + Flags |= MCSectionELF::XCORE_SHF_CP_SECTION; + break; + case 'd': + Flags |= MCSectionELF::XCORE_SHF_DP_SECTION; + break; + default: + return TokError("unknown flag"); + } + } + + unsigned Type = MCSectionELF::SHT_NULL; + if (!TypeName.empty()) { + if (TypeName == "init_array") + Type = MCSectionELF::SHT_INIT_ARRAY; + else if (TypeName == "fini_array") + Type = MCSectionELF::SHT_FINI_ARRAY; + else if (TypeName == "preinit_array") + Type = MCSectionELF::SHT_PREINIT_ARRAY; + else if (TypeName == "nobits") + Type = MCSectionELF::SHT_NOBITS; + else if (TypeName == "progbits") + Type = MCSectionELF::SHT_PROGBITS; + else + return TokError("unknown section type"); + } + + SectionKind Kind = (Flags & MCSectionELF::SHF_EXECINSTR) + ? SectionKind::getText() + : SectionKind::getDataRel(); + getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type, + Flags, Kind, false)); + return false; +} + namespace llvm { MCAsmParserExtension *createELFAsmParser() { |