xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCParser/COFFMasmParser.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h"
10*5ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h"
11*5ffd83dbSDimitry Andric #include "llvm/ADT/Triple.h"
12*5ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h"
13*5ffd83dbSDimitry Andric #include "llvm/BinaryFormat/COFF.h"
14*5ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
15*5ffd83dbSDimitry Andric #include "llvm/MC/MCDirectives.h"
16*5ffd83dbSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
17*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
18*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
19*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h"
20*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
21*5ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
22*5ffd83dbSDimitry Andric #include "llvm/MC/MCSectionCOFF.h"
23*5ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h"
24*5ffd83dbSDimitry Andric #include "llvm/MC/SectionKind.h"
25*5ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h"
26*5ffd83dbSDimitry Andric #include <cassert>
27*5ffd83dbSDimitry Andric #include <cstdint>
28*5ffd83dbSDimitry Andric #include <limits>
29*5ffd83dbSDimitry Andric #include <utility>
30*5ffd83dbSDimitry Andric 
31*5ffd83dbSDimitry Andric using namespace llvm;
32*5ffd83dbSDimitry Andric 
33*5ffd83dbSDimitry Andric namespace {
34*5ffd83dbSDimitry Andric 
35*5ffd83dbSDimitry Andric class COFFMasmParser : public MCAsmParserExtension {
36*5ffd83dbSDimitry Andric   template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
37*5ffd83dbSDimitry Andric   void addDirectiveHandler(StringRef Directive) {
38*5ffd83dbSDimitry Andric     MCAsmParser::ExtensionDirectiveHandler Handler =
39*5ffd83dbSDimitry Andric         std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
40*5ffd83dbSDimitry Andric     getParser().addDirectiveHandler(Directive, Handler);
41*5ffd83dbSDimitry Andric   }
42*5ffd83dbSDimitry Andric 
43*5ffd83dbSDimitry Andric   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
44*5ffd83dbSDimitry Andric                           SectionKind Kind);
45*5ffd83dbSDimitry Andric 
46*5ffd83dbSDimitry Andric   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
47*5ffd83dbSDimitry Andric                           SectionKind Kind, StringRef COMDATSymName,
48*5ffd83dbSDimitry Andric                           COFF::COMDATType Type);
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric   bool ParseDirectiveProc(StringRef, SMLoc);
51*5ffd83dbSDimitry Andric   bool ParseDirectiveEndProc(StringRef, SMLoc);
52*5ffd83dbSDimitry Andric   bool ParseDirectiveSegment(StringRef, SMLoc);
53*5ffd83dbSDimitry Andric   bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
54*5ffd83dbSDimitry Andric   bool ParseDirectiveIncludelib(StringRef, SMLoc);
55*5ffd83dbSDimitry Andric 
56*5ffd83dbSDimitry Andric   bool IgnoreDirective(StringRef, SMLoc) {
57*5ffd83dbSDimitry Andric     while (!getLexer().is(AsmToken::EndOfStatement)) {
58*5ffd83dbSDimitry Andric       Lex();
59*5ffd83dbSDimitry Andric     }
60*5ffd83dbSDimitry Andric     return false;
61*5ffd83dbSDimitry Andric   }
62*5ffd83dbSDimitry Andric 
63*5ffd83dbSDimitry Andric   void Initialize(MCAsmParser &Parser) override {
64*5ffd83dbSDimitry Andric     // Call the base implementation.
65*5ffd83dbSDimitry Andric     MCAsmParserExtension::Initialize(Parser);
66*5ffd83dbSDimitry Andric 
67*5ffd83dbSDimitry Andric     // x64 directives
68*5ffd83dbSDimitry Andric     // .allocstack
69*5ffd83dbSDimitry Andric     // .endprolog
70*5ffd83dbSDimitry Andric     // .pushframe
71*5ffd83dbSDimitry Andric     // .pushreg
72*5ffd83dbSDimitry Andric     // .savereg
73*5ffd83dbSDimitry Andric     // .savexmm128
74*5ffd83dbSDimitry Andric     // .setframe
75*5ffd83dbSDimitry Andric 
76*5ffd83dbSDimitry Andric     // Code label directives
77*5ffd83dbSDimitry Andric     // label
78*5ffd83dbSDimitry Andric     // org
79*5ffd83dbSDimitry Andric 
80*5ffd83dbSDimitry Andric     // Conditional control flow directives
81*5ffd83dbSDimitry Andric     // .break
82*5ffd83dbSDimitry Andric     // .continue
83*5ffd83dbSDimitry Andric     // .else
84*5ffd83dbSDimitry Andric     // .elseif
85*5ffd83dbSDimitry Andric     // .endif
86*5ffd83dbSDimitry Andric     // .endw
87*5ffd83dbSDimitry Andric     // .if
88*5ffd83dbSDimitry Andric     // .repeat
89*5ffd83dbSDimitry Andric     // .until
90*5ffd83dbSDimitry Andric     // .untilcxz
91*5ffd83dbSDimitry Andric     // .while
92*5ffd83dbSDimitry Andric 
93*5ffd83dbSDimitry Andric     // Data allocation directives
94*5ffd83dbSDimitry Andric     // align
95*5ffd83dbSDimitry Andric     // byte/sbyte
96*5ffd83dbSDimitry Andric     // dword/sdword
97*5ffd83dbSDimitry Andric     // even
98*5ffd83dbSDimitry Andric     // fword
99*5ffd83dbSDimitry Andric     // qword
100*5ffd83dbSDimitry Andric     // real4
101*5ffd83dbSDimitry Andric     // real8
102*5ffd83dbSDimitry Andric     // real10
103*5ffd83dbSDimitry Andric     // tbyte
104*5ffd83dbSDimitry Andric     // word/sword
105*5ffd83dbSDimitry Andric 
106*5ffd83dbSDimitry Andric     // Listing control directives
107*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
108*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
109*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
110*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
111*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
112*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
113*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
114*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
115*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
116*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
117*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
118*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
119*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
120*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
121*5ffd83dbSDimitry Andric 
122*5ffd83dbSDimitry Andric     // Macro directives
123*5ffd83dbSDimitry Andric     // endm
124*5ffd83dbSDimitry Andric     // exitm
125*5ffd83dbSDimitry Andric     // goto
126*5ffd83dbSDimitry Andric     // local
127*5ffd83dbSDimitry Andric     // macro
128*5ffd83dbSDimitry Andric     // purge
129*5ffd83dbSDimitry Andric 
130*5ffd83dbSDimitry Andric     // Miscellaneous directives
131*5ffd83dbSDimitry Andric     // alias
132*5ffd83dbSDimitry Andric     // assume
133*5ffd83dbSDimitry Andric     // .fpo
134*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
135*5ffd83dbSDimitry Andric         "includelib");
136*5ffd83dbSDimitry Andric     // mmword
137*5ffd83dbSDimitry Andric     // option
138*5ffd83dbSDimitry Andric     // popcontext
139*5ffd83dbSDimitry Andric     // pushcontext
140*5ffd83dbSDimitry Andric     // .radix
141*5ffd83dbSDimitry Andric     // .safeseh
142*5ffd83dbSDimitry Andric     // xmmword
143*5ffd83dbSDimitry Andric     // ymmword
144*5ffd83dbSDimitry Andric 
145*5ffd83dbSDimitry Andric     // Procedure directives
146*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
147*5ffd83dbSDimitry Andric     // invoke (32-bit only)
148*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
149*5ffd83dbSDimitry Andric     // proto
150*5ffd83dbSDimitry Andric 
151*5ffd83dbSDimitry Andric     // Processor directives
152*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
153*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
154*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
155*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
156*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
157*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
158*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
159*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
160*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
161*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
162*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
163*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
164*5ffd83dbSDimitry Andric 
165*5ffd83dbSDimitry Andric     // Repeat blocks directives
166*5ffd83dbSDimitry Andric     // for
167*5ffd83dbSDimitry Andric     // forc
168*5ffd83dbSDimitry Andric     // goto
169*5ffd83dbSDimitry Andric     // repeat
170*5ffd83dbSDimitry Andric     // while
171*5ffd83dbSDimitry Andric 
172*5ffd83dbSDimitry Andric     // Scope directives
173*5ffd83dbSDimitry Andric     // comm
174*5ffd83dbSDimitry Andric     // externdef
175*5ffd83dbSDimitry Andric 
176*5ffd83dbSDimitry Andric     // Segment directives
177*5ffd83dbSDimitry Andric     // .alpha (32-bit only, order segments alphabetically)
178*5ffd83dbSDimitry Andric     // .dosseg (32-bit only, order segments in DOS convention)
179*5ffd83dbSDimitry Andric     // .seq (32-bit only, order segments sequentially)
180*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
181*5ffd83dbSDimitry Andric     // group (32-bit only)
182*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
183*5ffd83dbSDimitry Andric 
184*5ffd83dbSDimitry Andric     // Simplified segment directives
185*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
186*5ffd83dbSDimitry Andric     // .const
187*5ffd83dbSDimitry Andric     addDirectiveHandler<
188*5ffd83dbSDimitry Andric         &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
189*5ffd83dbSDimitry Andric     addDirectiveHandler<
190*5ffd83dbSDimitry Andric         &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
191*5ffd83dbSDimitry Andric     // .exit
192*5ffd83dbSDimitry Andric     // .fardata
193*5ffd83dbSDimitry Andric     // .fardata?
194*5ffd83dbSDimitry Andric     addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
195*5ffd83dbSDimitry Andric     // .stack
196*5ffd83dbSDimitry Andric     // .startup
197*5ffd83dbSDimitry Andric 
198*5ffd83dbSDimitry Andric     // String directives, written <name> <directive> <params>
199*5ffd83dbSDimitry Andric     // catstr (equivalent to <name> TEXTEQU <params>)
200*5ffd83dbSDimitry Andric     // instr (equivalent to <name> = @InStr(<params>))
201*5ffd83dbSDimitry Andric     // sizestr (equivalent to <name> = @SizeStr(<params>))
202*5ffd83dbSDimitry Andric     // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
203*5ffd83dbSDimitry Andric 
204*5ffd83dbSDimitry Andric     // Structure and record directives
205*5ffd83dbSDimitry Andric     // ends
206*5ffd83dbSDimitry Andric     // record
207*5ffd83dbSDimitry Andric     // struct
208*5ffd83dbSDimitry Andric     // typedef
209*5ffd83dbSDimitry Andric     // union
210*5ffd83dbSDimitry Andric   }
211*5ffd83dbSDimitry Andric 
212*5ffd83dbSDimitry Andric   bool ParseSectionDirectiveCode(StringRef, SMLoc) {
213*5ffd83dbSDimitry Andric     return ParseSectionSwitch(".text",
214*5ffd83dbSDimitry Andric                               COFF::IMAGE_SCN_CNT_CODE
215*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_EXECUTE
216*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_READ,
217*5ffd83dbSDimitry Andric                               SectionKind::getText());
218*5ffd83dbSDimitry Andric   }
219*5ffd83dbSDimitry Andric 
220*5ffd83dbSDimitry Andric   bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
221*5ffd83dbSDimitry Andric     return ParseSectionSwitch(".data",
222*5ffd83dbSDimitry Andric                               COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
223*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_READ
224*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_WRITE,
225*5ffd83dbSDimitry Andric                               SectionKind::getData());
226*5ffd83dbSDimitry Andric   }
227*5ffd83dbSDimitry Andric 
228*5ffd83dbSDimitry Andric   bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
229*5ffd83dbSDimitry Andric     return ParseSectionSwitch(".bss",
230*5ffd83dbSDimitry Andric                               COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
231*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_READ
232*5ffd83dbSDimitry Andric                             | COFF::IMAGE_SCN_MEM_WRITE,
233*5ffd83dbSDimitry Andric                               SectionKind::getBSS());
234*5ffd83dbSDimitry Andric   }
235*5ffd83dbSDimitry Andric 
236*5ffd83dbSDimitry Andric   StringRef CurrentProcedure;
237*5ffd83dbSDimitry Andric 
238*5ffd83dbSDimitry Andric public:
239*5ffd83dbSDimitry Andric   COFFMasmParser() = default;
240*5ffd83dbSDimitry Andric };
241*5ffd83dbSDimitry Andric 
242*5ffd83dbSDimitry Andric } // end anonymous namespace.
243*5ffd83dbSDimitry Andric 
244*5ffd83dbSDimitry Andric static SectionKind computeSectionKind(unsigned Flags) {
245*5ffd83dbSDimitry Andric   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
246*5ffd83dbSDimitry Andric     return SectionKind::getText();
247*5ffd83dbSDimitry Andric   if (Flags & COFF::IMAGE_SCN_MEM_READ &&
248*5ffd83dbSDimitry Andric       (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
249*5ffd83dbSDimitry Andric     return SectionKind::getReadOnly();
250*5ffd83dbSDimitry Andric   return SectionKind::getData();
251*5ffd83dbSDimitry Andric }
252*5ffd83dbSDimitry Andric 
253*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
254*5ffd83dbSDimitry Andric                                         unsigned Characteristics,
255*5ffd83dbSDimitry Andric                                         SectionKind Kind) {
256*5ffd83dbSDimitry Andric   return ParseSectionSwitch(Section, Characteristics, Kind, "",
257*5ffd83dbSDimitry Andric                             (COFF::COMDATType)0);
258*5ffd83dbSDimitry Andric }
259*5ffd83dbSDimitry Andric 
260*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
261*5ffd83dbSDimitry Andric                                         unsigned Characteristics,
262*5ffd83dbSDimitry Andric                                         SectionKind Kind,
263*5ffd83dbSDimitry Andric                                         StringRef COMDATSymName,
264*5ffd83dbSDimitry Andric                                         COFF::COMDATType Type) {
265*5ffd83dbSDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
266*5ffd83dbSDimitry Andric     return TokError("unexpected token in section switching directive");
267*5ffd83dbSDimitry Andric   Lex();
268*5ffd83dbSDimitry Andric 
269*5ffd83dbSDimitry Andric   getStreamer().SwitchSection(getContext().getCOFFSection(
270*5ffd83dbSDimitry Andric       Section, Characteristics, Kind, COMDATSymName, Type));
271*5ffd83dbSDimitry Andric 
272*5ffd83dbSDimitry Andric   return false;
273*5ffd83dbSDimitry Andric }
274*5ffd83dbSDimitry Andric 
275*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
276*5ffd83dbSDimitry Andric   StringRef SegmentName;
277*5ffd83dbSDimitry Andric   if (!getLexer().is(AsmToken::Identifier))
278*5ffd83dbSDimitry Andric     return TokError("expected identifier in directive");
279*5ffd83dbSDimitry Andric   SegmentName = getTok().getIdentifier();
280*5ffd83dbSDimitry Andric   Lex();
281*5ffd83dbSDimitry Andric 
282*5ffd83dbSDimitry Andric   StringRef SectionName = SegmentName;
283*5ffd83dbSDimitry Andric   SmallVector<char, 247> SectionNameVector;
284*5ffd83dbSDimitry Andric   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
285*5ffd83dbSDimitry Andric                    COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
286*5ffd83dbSDimitry Andric   if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
287*5ffd83dbSDimitry Andric     if (SegmentName.size() == 5) {
288*5ffd83dbSDimitry Andric       SectionName = ".text";
289*5ffd83dbSDimitry Andric     } else {
290*5ffd83dbSDimitry Andric       SectionName =
291*5ffd83dbSDimitry Andric           (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
292*5ffd83dbSDimitry Andric     }
293*5ffd83dbSDimitry Andric     Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
294*5ffd83dbSDimitry Andric             COFF::IMAGE_SCN_MEM_READ;
295*5ffd83dbSDimitry Andric   }
296*5ffd83dbSDimitry Andric   SectionKind Kind = computeSectionKind(Flags);
297*5ffd83dbSDimitry Andric   getStreamer().SwitchSection(getContext().getCOFFSection(
298*5ffd83dbSDimitry Andric       SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
299*5ffd83dbSDimitry Andric   return false;
300*5ffd83dbSDimitry Andric }
301*5ffd83dbSDimitry Andric 
302*5ffd83dbSDimitry Andric /// ParseDirectiveSegmentEnd
303*5ffd83dbSDimitry Andric ///  ::= identifier "ends"
304*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
305*5ffd83dbSDimitry Andric   StringRef SegmentName;
306*5ffd83dbSDimitry Andric   if (!getLexer().is(AsmToken::Identifier))
307*5ffd83dbSDimitry Andric     return TokError("expected identifier in directive");
308*5ffd83dbSDimitry Andric   SegmentName = getTok().getIdentifier();
309*5ffd83dbSDimitry Andric 
310*5ffd83dbSDimitry Andric   // Ignore; no action necessary.
311*5ffd83dbSDimitry Andric   Lex();
312*5ffd83dbSDimitry Andric   return false;
313*5ffd83dbSDimitry Andric }
314*5ffd83dbSDimitry Andric 
315*5ffd83dbSDimitry Andric /// ParseDirectiveIncludelib
316*5ffd83dbSDimitry Andric ///  ::= "includelib" identifier
317*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
318*5ffd83dbSDimitry Andric   StringRef Lib;
319*5ffd83dbSDimitry Andric   if (getParser().parseIdentifier(Lib))
320*5ffd83dbSDimitry Andric     return TokError("expected identifier in includelib directive");
321*5ffd83dbSDimitry Andric 
322*5ffd83dbSDimitry Andric   unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
323*5ffd83dbSDimitry Andric   SectionKind Kind = computeSectionKind(Flags);
324*5ffd83dbSDimitry Andric   getStreamer().PushSection();
325*5ffd83dbSDimitry Andric   getStreamer().SwitchSection(getContext().getCOFFSection(
326*5ffd83dbSDimitry Andric       ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
327*5ffd83dbSDimitry Andric   getStreamer().emitBytes("/DEFAULTLIB:");
328*5ffd83dbSDimitry Andric   getStreamer().emitBytes(Lib);
329*5ffd83dbSDimitry Andric   getStreamer().emitBytes(" ");
330*5ffd83dbSDimitry Andric   getStreamer().PopSection();
331*5ffd83dbSDimitry Andric   return false;
332*5ffd83dbSDimitry Andric }
333*5ffd83dbSDimitry Andric 
334*5ffd83dbSDimitry Andric /// ParseDirectiveProc
335*5ffd83dbSDimitry Andric /// TODO(epastor): Implement parameters and other attributes.
336*5ffd83dbSDimitry Andric ///  ::= label "proc" [[distance]]
337*5ffd83dbSDimitry Andric ///          statements
338*5ffd83dbSDimitry Andric ///      label "endproc"
339*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
340*5ffd83dbSDimitry Andric   StringRef Label;
341*5ffd83dbSDimitry Andric   if (getParser().parseIdentifier(Label))
342*5ffd83dbSDimitry Andric     return Error(Loc, "expected identifier for procedure");
343*5ffd83dbSDimitry Andric   if (getLexer().is(AsmToken::Identifier)) {
344*5ffd83dbSDimitry Andric     StringRef nextVal = getTok().getString();
345*5ffd83dbSDimitry Andric     SMLoc nextLoc = getTok().getLoc();
346*5ffd83dbSDimitry Andric     if (nextVal.equals_lower("far")) {
347*5ffd83dbSDimitry Andric       // TODO(epastor): Handle far procedure definitions.
348*5ffd83dbSDimitry Andric       Lex();
349*5ffd83dbSDimitry Andric       return Error(nextLoc, "far procedure definitions not yet supported");
350*5ffd83dbSDimitry Andric     } else if (nextVal.equals_lower("near")) {
351*5ffd83dbSDimitry Andric       Lex();
352*5ffd83dbSDimitry Andric       nextVal = getTok().getString();
353*5ffd83dbSDimitry Andric       nextLoc = getTok().getLoc();
354*5ffd83dbSDimitry Andric     }
355*5ffd83dbSDimitry Andric   }
356*5ffd83dbSDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Label);
357*5ffd83dbSDimitry Andric 
358*5ffd83dbSDimitry Andric   // Define symbol as simple function
359*5ffd83dbSDimitry Andric   getStreamer().BeginCOFFSymbolDef(Sym);
360*5ffd83dbSDimitry Andric   getStreamer().EmitCOFFSymbolStorageClass(2);
361*5ffd83dbSDimitry Andric   getStreamer().EmitCOFFSymbolType(0x20);
362*5ffd83dbSDimitry Andric   getStreamer().EndCOFFSymbolDef();
363*5ffd83dbSDimitry Andric 
364*5ffd83dbSDimitry Andric   getStreamer().emitLabel(Sym, Loc);
365*5ffd83dbSDimitry Andric   CurrentProcedure = Label;
366*5ffd83dbSDimitry Andric   return false;
367*5ffd83dbSDimitry Andric }
368*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
369*5ffd83dbSDimitry Andric   StringRef Label;
370*5ffd83dbSDimitry Andric   SMLoc LabelLoc = getTok().getLoc();
371*5ffd83dbSDimitry Andric   if (getParser().parseIdentifier(Label))
372*5ffd83dbSDimitry Andric     return Error(LabelLoc, "expected identifier for procedure end");
373*5ffd83dbSDimitry Andric 
374*5ffd83dbSDimitry Andric   if (CurrentProcedure.empty())
375*5ffd83dbSDimitry Andric     return Error(Loc, "endp outside of procedure block");
376*5ffd83dbSDimitry Andric   else if (CurrentProcedure != Label)
377*5ffd83dbSDimitry Andric     return Error(LabelLoc, "endp does not match current procedure '" +
378*5ffd83dbSDimitry Andric                                CurrentProcedure + "'");
379*5ffd83dbSDimitry Andric   return false;
380*5ffd83dbSDimitry Andric }
381*5ffd83dbSDimitry Andric 
382*5ffd83dbSDimitry Andric namespace llvm {
383*5ffd83dbSDimitry Andric 
384*5ffd83dbSDimitry Andric MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
385*5ffd83dbSDimitry Andric 
386*5ffd83dbSDimitry Andric } // end namespace llvm
387