blob: 340af23cf9b90ceb8ec7138a68fd5b2cace9d79a [file] [log] [blame]
Daniel Dunbar5146a092010-07-12 21:23:32 +00001//===- ELFAsmParser.cpp - ELF Assembly Parser -----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000011#include "llvm/MC/MCAsmInfo.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000012#include "llvm/MC/MCContext.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
Eli Friedman21444ef2010-07-17 04:29:04 +000014#include "llvm/MC/MCSectionELF.h"
15#include "llvm/MC/MCStreamer.h"
Daniel Dunbar5146a092010-07-12 21:23:32 +000016using namespace llvm;
17
18namespace {
19
20class ELFAsmParser : public MCAsmParserExtension {
21 bool ParseSectionSwitch(StringRef Section, unsigned Type,
22 unsigned Flags, SectionKind Kind);
23
24public:
25 ELFAsmParser() {}
26
27 virtual void Initialize(MCAsmParser &Parser) {
28 // Call the base implementation.
29 this->MCAsmParserExtension::Initialize(Parser);
30
31 Parser.AddDirectiveHandler(this, ".data", MCAsmParser::DirectiveHandler(
32 &ELFAsmParser::ParseSectionDirectiveData));
33 Parser.AddDirectiveHandler(this, ".text", MCAsmParser::DirectiveHandler(
34 &ELFAsmParser::ParseSectionDirectiveText));
Eli Friedman21444ef2010-07-17 04:29:04 +000035 Parser.AddDirectiveHandler(this, ".section", MCAsmParser::DirectiveHandler(
36 &ELFAsmParser::ParseDirectiveSection));
Eli Friedmanf82ccf52010-07-17 03:09:18 +000037 Parser.AddDirectiveHandler(this, ".size", MCAsmParser::DirectiveHandler(
Eli Friedman21444ef2010-07-17 04:29:04 +000038 &ELFAsmParser::ParseDirectiveSize));
Daniel Dunbar5146a092010-07-12 21:23:32 +000039 }
40
41 bool ParseSectionDirectiveData(StringRef, SMLoc) {
42 return ParseSectionSwitch(".data", MCSectionELF::SHT_PROGBITS,
43 MCSectionELF::SHF_WRITE |MCSectionELF::SHF_ALLOC,
44 SectionKind::getDataRel());
45 }
46 bool ParseSectionDirectiveText(StringRef, SMLoc) {
47 return ParseSectionSwitch(".text", MCSectionELF::SHT_PROGBITS,
48 MCSectionELF::SHF_EXECINSTR |
49 MCSectionELF::SHF_ALLOC, SectionKind::getText());
50 }
Eli Friedman21444ef2010-07-17 04:29:04 +000051 bool ParseDirectiveSection(StringRef, SMLoc);
52 bool ParseDirectiveSize(StringRef, SMLoc);
Daniel Dunbar5146a092010-07-12 21:23:32 +000053};
54
55}
56
57bool ELFAsmParser::ParseSectionSwitch(StringRef Section, unsigned Type,
58 unsigned Flags, SectionKind Kind) {
59 if (getLexer().isNot(AsmToken::EndOfStatement))
60 return TokError("unexpected token in section switching directive");
61 Lex();
62
63 getStreamer().SwitchSection(getContext().getELFSection(
64 Section, Type, Flags, Kind));
65
66 return false;
67}
68
Eli Friedman21444ef2010-07-17 04:29:04 +000069bool ELFAsmParser::ParseDirectiveSize(StringRef, SMLoc) {
Eli Friedmanf82ccf52010-07-17 03:09:18 +000070 StringRef Name;
71 if (getParser().ParseIdentifier(Name))
72 return TokError("expected identifier in directive");
73 MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);;
74
75 if (getLexer().isNot(AsmToken::Comma))
76 return TokError("unexpected token in directive");
77 Lex();
78
79 const MCExpr *Expr;
80 if (getParser().ParseExpression(Expr))
81 return true;
82
83 if (getLexer().isNot(AsmToken::EndOfStatement))
84 return TokError("unexpected token in directive");
85
86 getStreamer().EmitELFSize(Sym, Expr);
87 return false;
88}
89
Eli Friedman21444ef2010-07-17 04:29:04 +000090// FIXME: This is a work in progress.
91bool ELFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
92 StringRef SectionName;
93 // FIXME: This doesn't parse section names like ".note.GNU-stack" correctly.
94 if (getParser().ParseIdentifier(SectionName))
95 return TokError("expected identifier in directive");
96
97 std::string FlagsStr;
98 StringRef TypeName;
99 int64_t Size = 0;
100 if (getLexer().is(AsmToken::Comma)) {
101 Lex();
102
103 if (getLexer().isNot(AsmToken::String))
104 return TokError("expected string in directive");
105
106 FlagsStr = getTok().getStringContents();
107 Lex();
108
109 AsmToken::TokenKind TypeStartToken;
110 if (getContext().getAsmInfo().getCommentString()[0] == '@')
111 TypeStartToken = AsmToken::Percent;
112 else
113 TypeStartToken = AsmToken::At;
114
115 if (getLexer().is(AsmToken::Comma)) {
116 Lex();
117 if (getLexer().is(TypeStartToken)) {
118 Lex();
119 if (getParser().ParseIdentifier(TypeName))
120 return TokError("expected identifier in directive");
121
122 if (getLexer().is(AsmToken::Comma)) {
123 Lex();
124
125 if (getParser().ParseAbsoluteExpression(Size))
126 return true;
127
128 if (Size <= 0)
129 return TokError("section size must be positive");
130 }
131 }
132 }
133 }
134
135 if (getLexer().isNot(AsmToken::EndOfStatement))
136 return TokError("unexpected token in directive");
137
138 unsigned Flags = 0;
139 for (unsigned i = 0; i < FlagsStr.size(); i++) {
140 switch (FlagsStr[i]) {
141 case 'a':
142 Flags |= MCSectionELF::SHF_ALLOC;
143 break;
144 case 'x':
145 Flags |= MCSectionELF::SHF_EXECINSTR;
146 break;
147 case 'w':
148 Flags |= MCSectionELF::SHF_WRITE;
149 break;
150 case 'M':
151 Flags |= MCSectionELF::SHF_MERGE;
152 break;
153 case 'S':
154 Flags |= MCSectionELF::SHF_STRINGS;
155 break;
156 case 'T':
157 Flags |= MCSectionELF::SHF_TLS;
158 break;
159 case 'c':
160 Flags |= MCSectionELF::XCORE_SHF_CP_SECTION;
161 break;
162 case 'd':
163 Flags |= MCSectionELF::XCORE_SHF_DP_SECTION;
164 break;
165 default:
166 return TokError("unknown flag");
167 }
168 }
169
170 unsigned Type = MCSectionELF::SHT_NULL;
171 if (!TypeName.empty()) {
172 if (TypeName == "init_array")
173 Type = MCSectionELF::SHT_INIT_ARRAY;
174 else if (TypeName == "fini_array")
175 Type = MCSectionELF::SHT_FINI_ARRAY;
176 else if (TypeName == "preinit_array")
177 Type = MCSectionELF::SHT_PREINIT_ARRAY;
178 else if (TypeName == "nobits")
179 Type = MCSectionELF::SHT_NOBITS;
180 else if (TypeName == "progbits")
181 Type = MCSectionELF::SHT_PROGBITS;
182 else
183 return TokError("unknown section type");
184 }
185
186 SectionKind Kind = (Flags & MCSectionELF::SHF_EXECINSTR)
187 ? SectionKind::getText()
188 : SectionKind::getDataRel();
189 getStreamer().SwitchSection(getContext().getELFSection(SectionName, Type,
190 Flags, Kind, false));
191 return false;
192}
193
Daniel Dunbar5146a092010-07-12 21:23:32 +0000194namespace llvm {
195
196MCAsmParserExtension *createELFAsmParser() {
197 return new ELFAsmParser;
198}
199
200}