xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCParser/COFFAsmParser.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
100b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
110b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCSectionCOFF.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
190b57cec5SDimitry Andric #include "llvm/MC/SectionKind.h"
200b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
2106c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
220b57cec5SDimitry Andric #include <cassert>
230b57cec5SDimitry Andric #include <cstdint>
240b57cec5SDimitry Andric #include <limits>
250b57cec5SDimitry Andric #include <utility>
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class COFFAsmParser : public MCAsmParserExtension {
320b57cec5SDimitry Andric   template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
330b57cec5SDimitry Andric   void addDirectiveHandler(StringRef Directive) {
340b57cec5SDimitry Andric     MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
350b57cec5SDimitry Andric         this, HandleDirective<COFFAsmParser, HandlerMethod>);
360b57cec5SDimitry Andric     getParser().addDirectiveHandler(Directive, Handler);
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric 
39*0fca6ea1SDimitry Andric   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
42*0fca6ea1SDimitry Andric                           StringRef COMDATSymName, COFF::COMDATType Type);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   bool ParseSectionName(StringRef &SectionName);
450b57cec5SDimitry Andric   bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
460b57cec5SDimitry Andric                          unsigned *Flags);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   void Initialize(MCAsmParser &Parser) override {
490b57cec5SDimitry Andric     // Call the base implementation.
500b57cec5SDimitry Andric     MCAsmParserExtension::Initialize(Parser);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
530b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
540b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
550b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
5606c3fb27SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectivePushSection>(
5706c3fb27SDimitry Andric         ".pushsection");
5806c3fb27SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectivePopSection>(
5906c3fb27SDimitry Andric         ".popsection");
600b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
610b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
620b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
630b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
640b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
650b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
660b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
670b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
680b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
690b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
708bcb0991SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
7106c3fb27SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak_anti_dep");
725ffd83dbSDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric     // Win64 EH directives.
750b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
760b57cec5SDimitry Andric                                                                    ".seh_proc");
770b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
780b57cec5SDimitry Andric                                                                 ".seh_endproc");
79e8d8bef9SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>(
80e8d8bef9SDimitry Andric                                                                 ".seh_endfunclet");
810b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
820b57cec5SDimitry Andric                                                            ".seh_startchained");
830b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
840b57cec5SDimitry Andric                                                              ".seh_endchained");
850b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
860b57cec5SDimitry Andric                                                                 ".seh_handler");
870b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
880b57cec5SDimitry Andric                                                             ".seh_handlerdata");
890b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
900b57cec5SDimitry Andric                                                              ".seh_stackalloc");
910b57cec5SDimitry Andric     addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
920b57cec5SDimitry Andric                                                             ".seh_endprologue");
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   bool ParseSectionDirectiveText(StringRef, SMLoc) {
96*0fca6ea1SDimitry Andric     return ParseSectionSwitch(".text", COFF::IMAGE_SCN_CNT_CODE |
97*0fca6ea1SDimitry Andric                                            COFF::IMAGE_SCN_MEM_EXECUTE |
98*0fca6ea1SDimitry Andric                                            COFF::IMAGE_SCN_MEM_READ);
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   bool ParseSectionDirectiveData(StringRef, SMLoc) {
1020b57cec5SDimitry Andric     return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
1030b57cec5SDimitry Andric                                            COFF::IMAGE_SCN_MEM_READ |
104*0fca6ea1SDimitry Andric                                            COFF::IMAGE_SCN_MEM_WRITE);
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
108*0fca6ea1SDimitry Andric     return ParseSectionSwitch(".bss", COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
109*0fca6ea1SDimitry Andric                                           COFF::IMAGE_SCN_MEM_READ |
110*0fca6ea1SDimitry Andric                                           COFF::IMAGE_SCN_MEM_WRITE);
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   bool ParseDirectiveSection(StringRef, SMLoc);
11406c3fb27SDimitry Andric   bool parseSectionArguments(StringRef, SMLoc);
11506c3fb27SDimitry Andric   bool ParseDirectivePushSection(StringRef, SMLoc);
11606c3fb27SDimitry Andric   bool ParseDirectivePopSection(StringRef, SMLoc);
1170b57cec5SDimitry Andric   bool ParseDirectiveDef(StringRef, SMLoc);
1180b57cec5SDimitry Andric   bool ParseDirectiveScl(StringRef, SMLoc);
1190b57cec5SDimitry Andric   bool ParseDirectiveType(StringRef, SMLoc);
1200b57cec5SDimitry Andric   bool ParseDirectiveEndef(StringRef, SMLoc);
1210b57cec5SDimitry Andric   bool ParseDirectiveSecRel32(StringRef, SMLoc);
1220b57cec5SDimitry Andric   bool ParseDirectiveSecIdx(StringRef, SMLoc);
1230b57cec5SDimitry Andric   bool ParseDirectiveSafeSEH(StringRef, SMLoc);
1240b57cec5SDimitry Andric   bool ParseDirectiveSymIdx(StringRef, SMLoc);
1250b57cec5SDimitry Andric   bool parseCOMDATType(COFF::COMDATType &Type);
1260b57cec5SDimitry Andric   bool ParseDirectiveLinkOnce(StringRef, SMLoc);
1270b57cec5SDimitry Andric   bool ParseDirectiveRVA(StringRef, SMLoc);
1285ffd83dbSDimitry Andric   bool ParseDirectiveCGProfile(StringRef, SMLoc);
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   // Win64 EH directives.
1310b57cec5SDimitry Andric   bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
1320b57cec5SDimitry Andric   bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
133e8d8bef9SDimitry Andric   bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);
1340b57cec5SDimitry Andric   bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
1350b57cec5SDimitry Andric   bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
1360b57cec5SDimitry Andric   bool ParseSEHDirectiveHandler(StringRef, SMLoc);
1370b57cec5SDimitry Andric   bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
1380b57cec5SDimitry Andric   bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
1390b57cec5SDimitry Andric   bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
1420b57cec5SDimitry Andric   bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric public:
1450b57cec5SDimitry Andric   COFFAsmParser() = default;
1460b57cec5SDimitry Andric };
1470b57cec5SDimitry Andric 
148480093f4SDimitry Andric } // end anonymous namespace.
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
1510b57cec5SDimitry Andric                                       StringRef FlagsString, unsigned *Flags) {
1520b57cec5SDimitry Andric   enum {
1530b57cec5SDimitry Andric     None = 0,
1540b57cec5SDimitry Andric     Alloc = 1 << 0,
1550b57cec5SDimitry Andric     Code = 1 << 1,
1560b57cec5SDimitry Andric     Load = 1 << 2,
1570b57cec5SDimitry Andric     InitData = 1 << 3,
1580b57cec5SDimitry Andric     Shared = 1 << 4,
1590b57cec5SDimitry Andric     NoLoad = 1 << 5,
1600b57cec5SDimitry Andric     NoRead = 1 << 6,
1610b57cec5SDimitry Andric     NoWrite = 1 << 7,
1620b57cec5SDimitry Andric     Discardable = 1 << 8,
163bdd1243dSDimitry Andric     Info = 1 << 9,
1640b57cec5SDimitry Andric   };
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   bool ReadOnlyRemoved = false;
1670b57cec5SDimitry Andric   unsigned SecFlags = None;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   for (char FlagChar : FlagsString) {
1700b57cec5SDimitry Andric     switch (FlagChar) {
1710b57cec5SDimitry Andric     case 'a':
1720b57cec5SDimitry Andric       // Ignored.
1730b57cec5SDimitry Andric       break;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric     case 'b': // bss section
1760b57cec5SDimitry Andric       SecFlags |= Alloc;
1770b57cec5SDimitry Andric       if (SecFlags & InitData)
1780b57cec5SDimitry Andric         return TokError("conflicting section flags 'b' and 'd'.");
1790b57cec5SDimitry Andric       SecFlags &= ~Load;
1800b57cec5SDimitry Andric       break;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     case 'd': // data section
1830b57cec5SDimitry Andric       SecFlags |= InitData;
1840b57cec5SDimitry Andric       if (SecFlags & Alloc)
1850b57cec5SDimitry Andric         return TokError("conflicting section flags 'b' and 'd'.");
1860b57cec5SDimitry Andric       SecFlags &= ~NoWrite;
1870b57cec5SDimitry Andric       if ((SecFlags & NoLoad) == 0)
1880b57cec5SDimitry Andric         SecFlags |= Load;
1890b57cec5SDimitry Andric       break;
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     case 'n': // section is not loaded
1920b57cec5SDimitry Andric       SecFlags |= NoLoad;
1930b57cec5SDimitry Andric       SecFlags &= ~Load;
1940b57cec5SDimitry Andric       break;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric     case 'D': // discardable
1970b57cec5SDimitry Andric       SecFlags |= Discardable;
1980b57cec5SDimitry Andric       break;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     case 'r': // read-only
2010b57cec5SDimitry Andric       ReadOnlyRemoved = false;
2020b57cec5SDimitry Andric       SecFlags |= NoWrite;
2030b57cec5SDimitry Andric       if ((SecFlags & Code) == 0)
2040b57cec5SDimitry Andric         SecFlags |= InitData;
2050b57cec5SDimitry Andric       if ((SecFlags & NoLoad) == 0)
2060b57cec5SDimitry Andric         SecFlags |= Load;
2070b57cec5SDimitry Andric       break;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     case 's': // shared section
2100b57cec5SDimitry Andric       SecFlags |= Shared | InitData;
2110b57cec5SDimitry Andric       SecFlags &= ~NoWrite;
2120b57cec5SDimitry Andric       if ((SecFlags & NoLoad) == 0)
2130b57cec5SDimitry Andric         SecFlags |= Load;
2140b57cec5SDimitry Andric       break;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric     case 'w': // writable
2170b57cec5SDimitry Andric       SecFlags &= ~NoWrite;
2180b57cec5SDimitry Andric       ReadOnlyRemoved = true;
2190b57cec5SDimitry Andric       break;
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric     case 'x': // executable section
2220b57cec5SDimitry Andric       SecFlags |= Code;
2230b57cec5SDimitry Andric       if ((SecFlags & NoLoad) == 0)
2240b57cec5SDimitry Andric         SecFlags |= Load;
2250b57cec5SDimitry Andric       if (!ReadOnlyRemoved)
2260b57cec5SDimitry Andric         SecFlags |= NoWrite;
2270b57cec5SDimitry Andric       break;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     case 'y': // not readable
2300b57cec5SDimitry Andric       SecFlags |= NoRead | NoWrite;
2310b57cec5SDimitry Andric       break;
2320b57cec5SDimitry Andric 
233bdd1243dSDimitry Andric     case 'i': // info
234bdd1243dSDimitry Andric       SecFlags |= Info;
235bdd1243dSDimitry Andric       break;
236bdd1243dSDimitry Andric 
2370b57cec5SDimitry Andric     default:
2380b57cec5SDimitry Andric       return TokError("unknown flag");
2390b57cec5SDimitry Andric     }
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   *Flags = 0;
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (SecFlags == None)
2450b57cec5SDimitry Andric     SecFlags = InitData;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   if (SecFlags & Code)
2480b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
2490b57cec5SDimitry Andric   if (SecFlags & InitData)
2500b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
2510b57cec5SDimitry Andric   if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
2520b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
2530b57cec5SDimitry Andric   if (SecFlags & NoLoad)
2540b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
2550b57cec5SDimitry Andric   if ((SecFlags & Discardable) ||
2560b57cec5SDimitry Andric       MCSectionCOFF::isImplicitlyDiscardable(SectionName))
2570b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
2580b57cec5SDimitry Andric   if ((SecFlags & NoRead) == 0)
2590b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_MEM_READ;
2600b57cec5SDimitry Andric   if ((SecFlags & NoWrite) == 0)
2610b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
2620b57cec5SDimitry Andric   if (SecFlags & Shared)
2630b57cec5SDimitry Andric     *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
264bdd1243dSDimitry Andric   if (SecFlags & Info)
265bdd1243dSDimitry Andric     *Flags |= COFF::IMAGE_SCN_LNK_INFO;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   return false;
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric /// ParseDirectiveSymbolAttribute
2710b57cec5SDimitry Andric ///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
2720b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
2730b57cec5SDimitry Andric   MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
2740b57cec5SDimitry Andric     .Case(".weak", MCSA_Weak)
27506c3fb27SDimitry Andric     .Case(".weak_anti_dep", MCSA_WeakAntiDep)
2760b57cec5SDimitry Andric     .Default(MCSA_Invalid);
2770b57cec5SDimitry Andric   assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
2780b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement)) {
2790b57cec5SDimitry Andric     while (true) {
2800b57cec5SDimitry Andric       StringRef Name;
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric       if (getParser().parseIdentifier(Name))
2830b57cec5SDimitry Andric         return TokError("expected identifier in directive");
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric       MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
2860b57cec5SDimitry Andric 
2875ffd83dbSDimitry Andric       getStreamer().emitSymbolAttribute(Sym, Attr);
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric       if (getLexer().is(AsmToken::EndOfStatement))
2900b57cec5SDimitry Andric         break;
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::Comma))
2930b57cec5SDimitry Andric         return TokError("unexpected token in directive");
2940b57cec5SDimitry Andric       Lex();
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   Lex();
2990b57cec5SDimitry Andric   return false;
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
3025ffd83dbSDimitry Andric bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
3035ffd83dbSDimitry Andric   return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
3045ffd83dbSDimitry Andric }
3055ffd83dbSDimitry Andric 
3060b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
307*0fca6ea1SDimitry Andric                                        unsigned Characteristics) {
308*0fca6ea1SDimitry Andric   return ParseSectionSwitch(Section, Characteristics, "", (COFF::COMDATType)0);
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
3120b57cec5SDimitry Andric                                        unsigned Characteristics,
3130b57cec5SDimitry Andric                                        StringRef COMDATSymName,
3140b57cec5SDimitry Andric                                        COFF::COMDATType Type) {
3150b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
3160b57cec5SDimitry Andric     return TokError("unexpected token in section switching directive");
3170b57cec5SDimitry Andric   Lex();
3180b57cec5SDimitry Andric 
31981ad6265SDimitry Andric   getStreamer().switchSection(getContext().getCOFFSection(
320*0fca6ea1SDimitry Andric       Section, Characteristics, COMDATSymName, Type));
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   return false;
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
3265ffd83dbSDimitry Andric   if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
3270b57cec5SDimitry Andric     return true;
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   SectionName = getTok().getIdentifier();
3300b57cec5SDimitry Andric   Lex();
3310b57cec5SDimitry Andric   return false;
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
33406c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectiveSection(StringRef directive, SMLoc loc) {
33506c3fb27SDimitry Andric   return parseSectionArguments(directive, loc);
33606c3fb27SDimitry Andric }
33706c3fb27SDimitry Andric 
3380b57cec5SDimitry Andric // .section name [, "flags"] [, identifier [ identifier ], identifier]
33906c3fb27SDimitry Andric // .pushsection <same as above>
3400b57cec5SDimitry Andric //
3410b57cec5SDimitry Andric // Supported flags:
3420b57cec5SDimitry Andric //   a: Ignored.
3430b57cec5SDimitry Andric //   b: BSS section (uninitialized data)
3440b57cec5SDimitry Andric //   d: data section (initialized data)
3450b57cec5SDimitry Andric //   n: "noload" section (removed by linker)
3460b57cec5SDimitry Andric //   D: Discardable section
3470b57cec5SDimitry Andric //   r: Readable section
3480b57cec5SDimitry Andric //   s: Shared section
3490b57cec5SDimitry Andric //   w: Writable section
3500b57cec5SDimitry Andric //   x: Executable section
3510b57cec5SDimitry Andric //   y: Not-readable section (clears 'r')
3520b57cec5SDimitry Andric //
3530b57cec5SDimitry Andric // Subsections are not supported.
35406c3fb27SDimitry Andric bool COFFAsmParser::parseSectionArguments(StringRef, SMLoc) {
3550b57cec5SDimitry Andric   StringRef SectionName;
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   if (ParseSectionName(SectionName))
3580b57cec5SDimitry Andric     return TokError("expected identifier in directive");
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
3610b57cec5SDimitry Andric                    COFF::IMAGE_SCN_MEM_READ |
3620b57cec5SDimitry Andric                    COFF::IMAGE_SCN_MEM_WRITE;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
3650b57cec5SDimitry Andric     Lex();
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::String))
3680b57cec5SDimitry Andric       return TokError("expected string in directive");
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric     StringRef FlagsStr = getTok().getStringContents();
3710b57cec5SDimitry Andric     Lex();
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric     if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
3740b57cec5SDimitry Andric       return true;
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   COFF::COMDATType Type = (COFF::COMDATType)0;
3780b57cec5SDimitry Andric   StringRef COMDATSymName;
3790b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
3800b57cec5SDimitry Andric     Type = COFF::IMAGE_COMDAT_SELECT_ANY;
3810b57cec5SDimitry Andric     Lex();
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric     Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::Identifier))
3860b57cec5SDimitry Andric       return TokError("expected comdat type such as 'discard' or 'largest' "
3870b57cec5SDimitry Andric                       "after protection bits");
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric     if (parseCOMDATType(Type))
3900b57cec5SDimitry Andric       return true;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::Comma))
3930b57cec5SDimitry Andric       return TokError("expected comma in directive");
3940b57cec5SDimitry Andric     Lex();
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric     if (getParser().parseIdentifier(COMDATSymName))
3970b57cec5SDimitry Andric       return TokError("expected identifier in directive");
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4010b57cec5SDimitry Andric     return TokError("unexpected token in directive");
4020b57cec5SDimitry Andric 
403*0fca6ea1SDimitry Andric   if (Flags & COFF::IMAGE_SCN_CNT_CODE) {
404fe6060f1SDimitry Andric     const Triple &T = getContext().getTargetTriple();
4050b57cec5SDimitry Andric     if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
4060b57cec5SDimitry Andric       Flags |= COFF::IMAGE_SCN_MEM_16BIT;
4070b57cec5SDimitry Andric   }
408*0fca6ea1SDimitry Andric   ParseSectionSwitch(SectionName, Flags, COMDATSymName, Type);
4090b57cec5SDimitry Andric   return false;
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric 
41206c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectivePushSection(StringRef directive, SMLoc loc) {
41306c3fb27SDimitry Andric   getStreamer().pushSection();
41406c3fb27SDimitry Andric 
41506c3fb27SDimitry Andric   if (parseSectionArguments(directive, loc)) {
41606c3fb27SDimitry Andric     getStreamer().popSection();
41706c3fb27SDimitry Andric     return true;
41806c3fb27SDimitry Andric   }
41906c3fb27SDimitry Andric 
42006c3fb27SDimitry Andric   return false;
42106c3fb27SDimitry Andric }
42206c3fb27SDimitry Andric 
42306c3fb27SDimitry Andric bool COFFAsmParser::ParseDirectivePopSection(StringRef, SMLoc) {
42406c3fb27SDimitry Andric   if (!getStreamer().popSection())
42506c3fb27SDimitry Andric     return TokError(".popsection without corresponding .pushsection");
42606c3fb27SDimitry Andric   return false;
42706c3fb27SDimitry Andric }
42806c3fb27SDimitry Andric 
4290b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
4300b57cec5SDimitry Andric   StringRef SymbolName;
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolName))
4330b57cec5SDimitry Andric     return TokError("expected identifier in directive");
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
4360b57cec5SDimitry Andric 
43781ad6265SDimitry Andric   getStreamer().beginCOFFSymbolDef(Sym);
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   Lex();
4400b57cec5SDimitry Andric   return false;
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
4440b57cec5SDimitry Andric   int64_t SymbolStorageClass;
4450b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(SymbolStorageClass))
4460b57cec5SDimitry Andric     return true;
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4490b57cec5SDimitry Andric     return TokError("unexpected token in directive");
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   Lex();
45281ad6265SDimitry Andric   getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);
4530b57cec5SDimitry Andric   return false;
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
4570b57cec5SDimitry Andric   int64_t Type;
4580b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(Type))
4590b57cec5SDimitry Andric     return true;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4620b57cec5SDimitry Andric     return TokError("unexpected token in directive");
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   Lex();
46581ad6265SDimitry Andric   getStreamer().emitCOFFSymbolType(Type);
4660b57cec5SDimitry Andric   return false;
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
4700b57cec5SDimitry Andric   Lex();
47181ad6265SDimitry Andric   getStreamer().endCOFFSymbolDef();
4720b57cec5SDimitry Andric   return false;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
4760b57cec5SDimitry Andric   StringRef SymbolID;
4770b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
4780b57cec5SDimitry Andric     return TokError("expected identifier in directive");
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   int64_t Offset = 0;
4810b57cec5SDimitry Andric   SMLoc OffsetLoc;
4820b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Plus)) {
4830b57cec5SDimitry Andric     OffsetLoc = getLexer().getLoc();
4840b57cec5SDimitry Andric     if (getParser().parseAbsoluteExpression(Offset))
4850b57cec5SDimitry Andric       return true;
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4890b57cec5SDimitry Andric     return TokError("unexpected token in directive");
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
4920b57cec5SDimitry Andric     return Error(
4930b57cec5SDimitry Andric         OffsetLoc,
4940b57cec5SDimitry Andric         "invalid '.secrel32' directive offset, can't be less "
4950b57cec5SDimitry Andric         "than zero or greater than std::numeric_limits<uint32_t>::max()");
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   Lex();
50081ad6265SDimitry Andric   getStreamer().emitCOFFSecRel32(Symbol, Offset);
5010b57cec5SDimitry Andric   return false;
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
5050b57cec5SDimitry Andric   auto parseOp = [&]() -> bool {
5060b57cec5SDimitry Andric     StringRef SymbolID;
5070b57cec5SDimitry Andric     if (getParser().parseIdentifier(SymbolID))
5080b57cec5SDimitry Andric       return TokError("expected identifier in directive");
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     int64_t Offset = 0;
5110b57cec5SDimitry Andric     SMLoc OffsetLoc;
5120b57cec5SDimitry Andric     if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
5130b57cec5SDimitry Andric       OffsetLoc = getLexer().getLoc();
5140b57cec5SDimitry Andric       if (getParser().parseAbsoluteExpression(Offset))
5150b57cec5SDimitry Andric         return true;
5160b57cec5SDimitry Andric     }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric     if (Offset < std::numeric_limits<int32_t>::min() ||
5190b57cec5SDimitry Andric         Offset > std::numeric_limits<int32_t>::max())
5200b57cec5SDimitry Andric       return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
5210b57cec5SDimitry Andric                               "than -2147483648 or greater than "
5220b57cec5SDimitry Andric                               "2147483647");
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
5250b57cec5SDimitry Andric 
52681ad6265SDimitry Andric     getStreamer().emitCOFFImgRel32(Symbol, Offset);
5270b57cec5SDimitry Andric     return false;
5280b57cec5SDimitry Andric   };
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   if (getParser().parseMany(parseOp))
5310b57cec5SDimitry Andric     return addErrorSuffix(" in directive");
5320b57cec5SDimitry Andric   return false;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
5360b57cec5SDimitry Andric   StringRef SymbolID;
5370b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
5380b57cec5SDimitry Andric     return TokError("expected identifier in directive");
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
5410b57cec5SDimitry Andric     return TokError("unexpected token in directive");
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   Lex();
54681ad6265SDimitry Andric   getStreamer().emitCOFFSafeSEH(Symbol);
5470b57cec5SDimitry Andric   return false;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
5510b57cec5SDimitry Andric   StringRef SymbolID;
5520b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
5530b57cec5SDimitry Andric     return TokError("expected identifier in directive");
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
5560b57cec5SDimitry Andric     return TokError("unexpected token in directive");
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   Lex();
56181ad6265SDimitry Andric   getStreamer().emitCOFFSectionIndex(Symbol);
5620b57cec5SDimitry Andric   return false;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
5660b57cec5SDimitry Andric   StringRef SymbolID;
5670b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
5680b57cec5SDimitry Andric     return TokError("expected identifier in directive");
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
5710b57cec5SDimitry Andric     return TokError("unexpected token in directive");
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   Lex();
57681ad6265SDimitry Andric   getStreamer().emitCOFFSymbolIndex(Symbol);
5770b57cec5SDimitry Andric   return false;
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric /// ::= [ identifier ]
5810b57cec5SDimitry Andric bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
5820b57cec5SDimitry Andric   StringRef TypeId = getTok().getIdentifier();
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   Type = StringSwitch<COFF::COMDATType>(TypeId)
5850b57cec5SDimitry Andric     .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
5860b57cec5SDimitry Andric     .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
5870b57cec5SDimitry Andric     .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
5880b57cec5SDimitry Andric     .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
5890b57cec5SDimitry Andric     .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
5900b57cec5SDimitry Andric     .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
5910b57cec5SDimitry Andric     .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
5920b57cec5SDimitry Andric     .Default((COFF::COMDATType)0);
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   if (Type == 0)
5950b57cec5SDimitry Andric     return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   Lex();
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   return false;
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric /// ParseDirectiveLinkOnce
6030b57cec5SDimitry Andric ///  ::= .linkonce [ identifier ]
6040b57cec5SDimitry Andric bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
6050b57cec5SDimitry Andric   COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
6060b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Identifier))
6070b57cec5SDimitry Andric     if (parseCOMDATType(Type))
6080b57cec5SDimitry Andric       return true;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   const MCSectionCOFF *Current =
6110b57cec5SDimitry Andric       static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
6140b57cec5SDimitry Andric     return Error(Loc, "cannot make section associative with .linkonce");
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
6175ffd83dbSDimitry Andric     return Error(Loc, Twine("section '") + Current->getName() +
6180b57cec5SDimitry Andric                           "' is already linkonce");
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   Current->setSelection(Type);
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
6230b57cec5SDimitry Andric     return TokError("unexpected token in directive");
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   return false;
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
6290b57cec5SDimitry Andric   StringRef SymbolID;
6300b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
6310b57cec5SDimitry Andric     return true;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
6340b57cec5SDimitry Andric     return TokError("unexpected token in directive");
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   Lex();
63981ad6265SDimitry Andric   getStreamer().emitWinCFIStartProc(Symbol, Loc);
6400b57cec5SDimitry Andric   return false;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
6440b57cec5SDimitry Andric   Lex();
64581ad6265SDimitry Andric   getStreamer().emitWinCFIEndProc(Loc);
6460b57cec5SDimitry Andric   return false;
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
649e8d8bef9SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
650e8d8bef9SDimitry Andric   Lex();
65181ad6265SDimitry Andric   getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);
652e8d8bef9SDimitry Andric   return false;
653e8d8bef9SDimitry Andric }
654e8d8bef9SDimitry Andric 
6550b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
6560b57cec5SDimitry Andric   Lex();
65781ad6265SDimitry Andric   getStreamer().emitWinCFIStartChained(Loc);
6580b57cec5SDimitry Andric   return false;
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
6620b57cec5SDimitry Andric   Lex();
66381ad6265SDimitry Andric   getStreamer().emitWinCFIEndChained(Loc);
6640b57cec5SDimitry Andric   return false;
6650b57cec5SDimitry Andric }
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
6680b57cec5SDimitry Andric   StringRef SymbolID;
6690b57cec5SDimitry Andric   if (getParser().parseIdentifier(SymbolID))
6700b57cec5SDimitry Andric     return true;
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
6730b57cec5SDimitry Andric     return TokError("you must specify one or both of @unwind or @except");
6740b57cec5SDimitry Andric   Lex();
6750b57cec5SDimitry Andric   bool unwind = false, except = false;
6760b57cec5SDimitry Andric   if (ParseAtUnwindOrAtExcept(unwind, except))
6770b57cec5SDimitry Andric     return true;
6780b57cec5SDimitry Andric   if (getLexer().is(AsmToken::Comma)) {
6790b57cec5SDimitry Andric     Lex();
6800b57cec5SDimitry Andric     if (ParseAtUnwindOrAtExcept(unwind, except))
6810b57cec5SDimitry Andric       return true;
6820b57cec5SDimitry Andric   }
6830b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
6840b57cec5SDimitry Andric     return TokError("unexpected token in directive");
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   Lex();
68981ad6265SDimitry Andric   getStreamer().emitWinEHHandler(handler, unwind, except, Loc);
6900b57cec5SDimitry Andric   return false;
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
6940b57cec5SDimitry Andric   Lex();
69581ad6265SDimitry Andric   getStreamer().emitWinEHHandlerData();
6960b57cec5SDimitry Andric   return false;
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
7000b57cec5SDimitry Andric   int64_t Size;
7010b57cec5SDimitry Andric   if (getParser().parseAbsoluteExpression(Size))
7020b57cec5SDimitry Andric     return true;
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
7050b57cec5SDimitry Andric     return TokError("unexpected token in directive");
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   Lex();
70881ad6265SDimitry Andric   getStreamer().emitWinCFIAllocStack(Size, Loc);
7090b57cec5SDimitry Andric   return false;
7100b57cec5SDimitry Andric }
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
7130b57cec5SDimitry Andric   Lex();
71481ad6265SDimitry Andric   getStreamer().emitWinCFIEndProlog(Loc);
7150b57cec5SDimitry Andric   return false;
7160b57cec5SDimitry Andric }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
7190b57cec5SDimitry Andric   StringRef identifier;
72081ad6265SDimitry Andric   if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))
72181ad6265SDimitry Andric     return TokError("a handler attribute must begin with '@' or '%'");
7220b57cec5SDimitry Andric   SMLoc startLoc = getLexer().getLoc();
7230b57cec5SDimitry Andric   Lex();
7240b57cec5SDimitry Andric   if (getParser().parseIdentifier(identifier))
7250b57cec5SDimitry Andric     return Error(startLoc, "expected @unwind or @except");
7260b57cec5SDimitry Andric   if (identifier == "unwind")
7270b57cec5SDimitry Andric     unwind = true;
7280b57cec5SDimitry Andric   else if (identifier == "except")
7290b57cec5SDimitry Andric     except = true;
7300b57cec5SDimitry Andric   else
7310b57cec5SDimitry Andric     return Error(startLoc, "expected @unwind or @except");
7320b57cec5SDimitry Andric   return false;
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric namespace llvm {
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric MCAsmParserExtension *createCOFFAsmParser() {
7380b57cec5SDimitry Andric   return new COFFAsmParser;
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric } // end namespace llvm
742