Add support for emitting ARM file attributes.
[oota-llvm.git] / lib / MC / MCParser / COFFAsmParser.cpp
1 //===- COFFAsmParser.cpp - COFF 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"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/MC/MCAsmInfo.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCParser/MCAsmLexer.h"
15 #include "llvm/MC/MCSectionCOFF.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/Support/COFF.h"
18 using namespace llvm;
19
20 namespace {
21
22 class COFFAsmParser : public MCAsmParserExtension {
23   template<bool (COFFAsmParser::*Handler)(StringRef, SMLoc)>
24   void AddDirectiveHandler(StringRef Directive) {
25     getParser().AddDirectiveHandler(this, Directive,
26                                     HandleDirective<COFFAsmParser, Handler>);
27   }
28
29   bool ParseSectionSwitch(StringRef Section,
30                           unsigned Characteristics,
31                           SectionKind Kind);
32
33   virtual void Initialize(MCAsmParser &Parser) {
34     // Call the base implementation.
35     MCAsmParserExtension::Initialize(Parser);
36
37     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
38     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
39     AddDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
40     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
41     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
42     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
43     AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
44   }
45
46   bool ParseSectionDirectiveText(StringRef, SMLoc) {
47     return ParseSectionSwitch(".text",
48                               COFF::IMAGE_SCN_CNT_CODE
49                             | COFF::IMAGE_SCN_MEM_EXECUTE
50                             | COFF::IMAGE_SCN_MEM_READ,
51                               SectionKind::getText());
52   }
53   bool ParseSectionDirectiveData(StringRef, SMLoc) {
54     return ParseSectionSwitch(".data",
55                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
56                             | COFF::IMAGE_SCN_MEM_READ
57                             | COFF::IMAGE_SCN_MEM_WRITE,
58                               SectionKind::getDataRel());
59   }
60   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
61     return ParseSectionSwitch(".bss",
62                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
63                             | COFF::IMAGE_SCN_MEM_READ
64                             | COFF::IMAGE_SCN_MEM_WRITE,
65                               SectionKind::getBSS());
66   }
67
68   bool ParseDirectiveDef(StringRef, SMLoc);
69   bool ParseDirectiveScl(StringRef, SMLoc);
70   bool ParseDirectiveType(StringRef, SMLoc);
71   bool ParseDirectiveEndef(StringRef, SMLoc);
72
73 public:
74   COFFAsmParser() {}
75 };
76
77 } // end annonomous namespace.
78
79 bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
80                                        unsigned Characteristics,
81                                        SectionKind Kind) {
82   if (getLexer().isNot(AsmToken::EndOfStatement))
83     return TokError("unexpected token in section switching directive");
84   Lex();
85
86   getStreamer().SwitchSection(getContext().getCOFFSection(
87                                 Section, Characteristics, Kind));
88
89   return false;
90 }
91
92 bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
93   StringRef SymbolName;
94
95   if (getParser().ParseIdentifier(SymbolName))
96     return TokError("expected identifier in directive");
97
98   MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
99
100   getStreamer().BeginCOFFSymbolDef(Sym);
101
102   Lex();
103   return false;
104 }
105
106 bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
107   int64_t SymbolStorageClass;
108   if (getParser().ParseAbsoluteExpression(SymbolStorageClass))
109     return true;
110
111   if (getLexer().isNot(AsmToken::EndOfStatement))
112     return TokError("unexpected token in directive");
113
114   Lex();
115   getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
116   return false;
117 }
118
119 bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
120   int64_t Type;
121   if (getParser().ParseAbsoluteExpression(Type))
122     return true;
123
124   if (getLexer().isNot(AsmToken::EndOfStatement))
125     return TokError("unexpected token in directive");
126
127   Lex();
128   getStreamer().EmitCOFFSymbolType(Type);
129   return false;
130 }
131
132 bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
133   Lex();
134   getStreamer().EndCOFFSymbolDef();
135   return false;
136 }
137
138 namespace llvm {
139
140 MCAsmParserExtension *createCOFFAsmParser() {
141   return new COFFAsmParser;
142 }
143
144 }