COFFAsmParser.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ADT/StringRef.h"
  9. #include "llvm/ADT/StringSwitch.h"
  10. #include "llvm/ADT/Triple.h"
  11. #include "llvm/ADT/Twine.h"
  12. #include "llvm/BinaryFormat/COFF.h"
  13. #include "llvm/MC/MCContext.h"
  14. #include "llvm/MC/MCDirectives.h"
  15. #include "llvm/MC/MCParser/MCAsmLexer.h"
  16. #include "llvm/MC/MCParser/MCAsmParserExtension.h"
  17. #include "llvm/MC/MCSectionCOFF.h"
  18. #include "llvm/MC/MCStreamer.h"
  19. #include "llvm/MC/SectionKind.h"
  20. #include "llvm/Support/SMLoc.h"
  21. #include <cassert>
  22. #include <cstdint>
  23. #include <limits>
  24. #include <utility>
  25. using namespace llvm;
  26. namespace {
  27. class COFFAsmParser : public MCAsmParserExtension {
  28. template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
  29. void addDirectiveHandler(StringRef Directive) {
  30. MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
  31. this, HandleDirective<COFFAsmParser, HandlerMethod>);
  32. getParser().addDirectiveHandler(Directive, Handler);
  33. }
  34. bool ParseSectionSwitch(StringRef Section,
  35. unsigned Characteristics,
  36. SectionKind Kind);
  37. bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
  38. SectionKind Kind, StringRef COMDATSymName,
  39. COFF::COMDATType Type);
  40. bool ParseSectionName(StringRef &SectionName);
  41. bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
  42. unsigned *Flags);
  43. void Initialize(MCAsmParser &Parser) override {
  44. // Call the base implementation.
  45. MCAsmParserExtension::Initialize(Parser);
  46. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
  47. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
  48. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
  49. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
  50. addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
  51. addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
  52. addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
  53. addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
  54. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
  55. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
  56. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
  57. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
  58. addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
  59. addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
  60. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
  61. addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
  62. // Win64 EH directives.
  63. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
  64. ".seh_proc");
  65. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
  66. ".seh_endproc");
  67. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc>(
  68. ".seh_endfunclet");
  69. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
  70. ".seh_startchained");
  71. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
  72. ".seh_endchained");
  73. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
  74. ".seh_handler");
  75. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
  76. ".seh_handlerdata");
  77. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
  78. ".seh_stackalloc");
  79. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
  80. ".seh_endprologue");
  81. }
  82. bool ParseSectionDirectiveText(StringRef, SMLoc) {
  83. return ParseSectionSwitch(".text",
  84. COFF::IMAGE_SCN_CNT_CODE
  85. | COFF::IMAGE_SCN_MEM_EXECUTE
  86. | COFF::IMAGE_SCN_MEM_READ,
  87. SectionKind::getText());
  88. }
  89. bool ParseSectionDirectiveData(StringRef, SMLoc) {
  90. return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
  91. COFF::IMAGE_SCN_MEM_READ |
  92. COFF::IMAGE_SCN_MEM_WRITE,
  93. SectionKind::getData());
  94. }
  95. bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
  96. return ParseSectionSwitch(".bss",
  97. COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
  98. | COFF::IMAGE_SCN_MEM_READ
  99. | COFF::IMAGE_SCN_MEM_WRITE,
  100. SectionKind::getBSS());
  101. }
  102. bool ParseDirectiveSection(StringRef, SMLoc);
  103. bool ParseDirectiveDef(StringRef, SMLoc);
  104. bool ParseDirectiveScl(StringRef, SMLoc);
  105. bool ParseDirectiveType(StringRef, SMLoc);
  106. bool ParseDirectiveEndef(StringRef, SMLoc);
  107. bool ParseDirectiveSecRel32(StringRef, SMLoc);
  108. bool ParseDirectiveSecIdx(StringRef, SMLoc);
  109. bool ParseDirectiveSafeSEH(StringRef, SMLoc);
  110. bool ParseDirectiveSymIdx(StringRef, SMLoc);
  111. bool parseCOMDATType(COFF::COMDATType &Type);
  112. bool ParseDirectiveLinkOnce(StringRef, SMLoc);
  113. bool ParseDirectiveRVA(StringRef, SMLoc);
  114. bool ParseDirectiveCGProfile(StringRef, SMLoc);
  115. // Win64 EH directives.
  116. bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
  117. bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
  118. bool ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc);
  119. bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
  120. bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
  121. bool ParseSEHDirectiveHandler(StringRef, SMLoc);
  122. bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
  123. bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
  124. bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
  125. bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
  126. bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
  127. public:
  128. COFFAsmParser() = default;
  129. };
  130. } // end anonymous namespace.
  131. static SectionKind computeSectionKind(unsigned Flags) {
  132. if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
  133. return SectionKind::getText();
  134. if (Flags & COFF::IMAGE_SCN_MEM_READ &&
  135. (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
  136. return SectionKind::getReadOnly();
  137. return SectionKind::getData();
  138. }
  139. bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
  140. StringRef FlagsString, unsigned *Flags) {
  141. enum {
  142. None = 0,
  143. Alloc = 1 << 0,
  144. Code = 1 << 1,
  145. Load = 1 << 2,
  146. InitData = 1 << 3,
  147. Shared = 1 << 4,
  148. NoLoad = 1 << 5,
  149. NoRead = 1 << 6,
  150. NoWrite = 1 << 7,
  151. Discardable = 1 << 8,
  152. Info = 1 << 9,
  153. };
  154. bool ReadOnlyRemoved = false;
  155. unsigned SecFlags = None;
  156. for (char FlagChar : FlagsString) {
  157. switch (FlagChar) {
  158. case 'a':
  159. // Ignored.
  160. break;
  161. case 'b': // bss section
  162. SecFlags |= Alloc;
  163. if (SecFlags & InitData)
  164. return TokError("conflicting section flags 'b' and 'd'.");
  165. SecFlags &= ~Load;
  166. break;
  167. case 'd': // data section
  168. SecFlags |= InitData;
  169. if (SecFlags & Alloc)
  170. return TokError("conflicting section flags 'b' and 'd'.");
  171. SecFlags &= ~NoWrite;
  172. if ((SecFlags & NoLoad) == 0)
  173. SecFlags |= Load;
  174. break;
  175. case 'n': // section is not loaded
  176. SecFlags |= NoLoad;
  177. SecFlags &= ~Load;
  178. break;
  179. case 'D': // discardable
  180. SecFlags |= Discardable;
  181. break;
  182. case 'r': // read-only
  183. ReadOnlyRemoved = false;
  184. SecFlags |= NoWrite;
  185. if ((SecFlags & Code) == 0)
  186. SecFlags |= InitData;
  187. if ((SecFlags & NoLoad) == 0)
  188. SecFlags |= Load;
  189. break;
  190. case 's': // shared section
  191. SecFlags |= Shared | InitData;
  192. SecFlags &= ~NoWrite;
  193. if ((SecFlags & NoLoad) == 0)
  194. SecFlags |= Load;
  195. break;
  196. case 'w': // writable
  197. SecFlags &= ~NoWrite;
  198. ReadOnlyRemoved = true;
  199. break;
  200. case 'x': // executable section
  201. SecFlags |= Code;
  202. if ((SecFlags & NoLoad) == 0)
  203. SecFlags |= Load;
  204. if (!ReadOnlyRemoved)
  205. SecFlags |= NoWrite;
  206. break;
  207. case 'y': // not readable
  208. SecFlags |= NoRead | NoWrite;
  209. break;
  210. case 'i': // info
  211. SecFlags |= Info;
  212. break;
  213. default:
  214. return TokError("unknown flag");
  215. }
  216. }
  217. *Flags = 0;
  218. if (SecFlags == None)
  219. SecFlags = InitData;
  220. if (SecFlags & Code)
  221. *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
  222. if (SecFlags & InitData)
  223. *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  224. if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
  225. *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
  226. if (SecFlags & NoLoad)
  227. *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
  228. if ((SecFlags & Discardable) ||
  229. MCSectionCOFF::isImplicitlyDiscardable(SectionName))
  230. *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
  231. if ((SecFlags & NoRead) == 0)
  232. *Flags |= COFF::IMAGE_SCN_MEM_READ;
  233. if ((SecFlags & NoWrite) == 0)
  234. *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
  235. if (SecFlags & Shared)
  236. *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
  237. if (SecFlags & Info)
  238. *Flags |= COFF::IMAGE_SCN_LNK_INFO;
  239. return false;
  240. }
  241. /// ParseDirectiveSymbolAttribute
  242. /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
  243. bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
  244. MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
  245. .Case(".weak", MCSA_Weak)
  246. .Default(MCSA_Invalid);
  247. assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
  248. if (getLexer().isNot(AsmToken::EndOfStatement)) {
  249. while (true) {
  250. StringRef Name;
  251. if (getParser().parseIdentifier(Name))
  252. return TokError("expected identifier in directive");
  253. MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
  254. getStreamer().emitSymbolAttribute(Sym, Attr);
  255. if (getLexer().is(AsmToken::EndOfStatement))
  256. break;
  257. if (getLexer().isNot(AsmToken::Comma))
  258. return TokError("unexpected token in directive");
  259. Lex();
  260. }
  261. }
  262. Lex();
  263. return false;
  264. }
  265. bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
  266. return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
  267. }
  268. bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
  269. unsigned Characteristics,
  270. SectionKind Kind) {
  271. return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
  272. }
  273. bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
  274. unsigned Characteristics,
  275. SectionKind Kind,
  276. StringRef COMDATSymName,
  277. COFF::COMDATType Type) {
  278. if (getLexer().isNot(AsmToken::EndOfStatement))
  279. return TokError("unexpected token in section switching directive");
  280. Lex();
  281. getStreamer().switchSection(getContext().getCOFFSection(
  282. Section, Characteristics, Kind, COMDATSymName, Type));
  283. return false;
  284. }
  285. bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
  286. if (!getLexer().is(AsmToken::Identifier) && !getLexer().is(AsmToken::String))
  287. return true;
  288. SectionName = getTok().getIdentifier();
  289. Lex();
  290. return false;
  291. }
  292. // .section name [, "flags"] [, identifier [ identifier ], identifier]
  293. //
  294. // Supported flags:
  295. // a: Ignored.
  296. // b: BSS section (uninitialized data)
  297. // d: data section (initialized data)
  298. // n: "noload" section (removed by linker)
  299. // D: Discardable section
  300. // r: Readable section
  301. // s: Shared section
  302. // w: Writable section
  303. // x: Executable section
  304. // y: Not-readable section (clears 'r')
  305. //
  306. // Subsections are not supported.
  307. bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
  308. StringRef SectionName;
  309. if (ParseSectionName(SectionName))
  310. return TokError("expected identifier in directive");
  311. unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
  312. COFF::IMAGE_SCN_MEM_READ |
  313. COFF::IMAGE_SCN_MEM_WRITE;
  314. if (getLexer().is(AsmToken::Comma)) {
  315. Lex();
  316. if (getLexer().isNot(AsmToken::String))
  317. return TokError("expected string in directive");
  318. StringRef FlagsStr = getTok().getStringContents();
  319. Lex();
  320. if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
  321. return true;
  322. }
  323. COFF::COMDATType Type = (COFF::COMDATType)0;
  324. StringRef COMDATSymName;
  325. if (getLexer().is(AsmToken::Comma)) {
  326. Type = COFF::IMAGE_COMDAT_SELECT_ANY;
  327. Lex();
  328. Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
  329. if (!getLexer().is(AsmToken::Identifier))
  330. return TokError("expected comdat type such as 'discard' or 'largest' "
  331. "after protection bits");
  332. if (parseCOMDATType(Type))
  333. return true;
  334. if (getLexer().isNot(AsmToken::Comma))
  335. return TokError("expected comma in directive");
  336. Lex();
  337. if (getParser().parseIdentifier(COMDATSymName))
  338. return TokError("expected identifier in directive");
  339. }
  340. if (getLexer().isNot(AsmToken::EndOfStatement))
  341. return TokError("unexpected token in directive");
  342. SectionKind Kind = computeSectionKind(Flags);
  343. if (Kind.isText()) {
  344. const Triple &T = getContext().getTargetTriple();
  345. if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
  346. Flags |= COFF::IMAGE_SCN_MEM_16BIT;
  347. }
  348. ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
  349. return false;
  350. }
  351. bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
  352. StringRef SymbolName;
  353. if (getParser().parseIdentifier(SymbolName))
  354. return TokError("expected identifier in directive");
  355. MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
  356. getStreamer().beginCOFFSymbolDef(Sym);
  357. Lex();
  358. return false;
  359. }
  360. bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
  361. int64_t SymbolStorageClass;
  362. if (getParser().parseAbsoluteExpression(SymbolStorageClass))
  363. return true;
  364. if (getLexer().isNot(AsmToken::EndOfStatement))
  365. return TokError("unexpected token in directive");
  366. Lex();
  367. getStreamer().emitCOFFSymbolStorageClass(SymbolStorageClass);
  368. return false;
  369. }
  370. bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
  371. int64_t Type;
  372. if (getParser().parseAbsoluteExpression(Type))
  373. return true;
  374. if (getLexer().isNot(AsmToken::EndOfStatement))
  375. return TokError("unexpected token in directive");
  376. Lex();
  377. getStreamer().emitCOFFSymbolType(Type);
  378. return false;
  379. }
  380. bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
  381. Lex();
  382. getStreamer().endCOFFSymbolDef();
  383. return false;
  384. }
  385. bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
  386. StringRef SymbolID;
  387. if (getParser().parseIdentifier(SymbolID))
  388. return TokError("expected identifier in directive");
  389. int64_t Offset = 0;
  390. SMLoc OffsetLoc;
  391. if (getLexer().is(AsmToken::Plus)) {
  392. OffsetLoc = getLexer().getLoc();
  393. if (getParser().parseAbsoluteExpression(Offset))
  394. return true;
  395. }
  396. if (getLexer().isNot(AsmToken::EndOfStatement))
  397. return TokError("unexpected token in directive");
  398. if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
  399. return Error(
  400. OffsetLoc,
  401. "invalid '.secrel32' directive offset, can't be less "
  402. "than zero or greater than std::numeric_limits<uint32_t>::max()");
  403. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  404. Lex();
  405. getStreamer().emitCOFFSecRel32(Symbol, Offset);
  406. return false;
  407. }
  408. bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
  409. auto parseOp = [&]() -> bool {
  410. StringRef SymbolID;
  411. if (getParser().parseIdentifier(SymbolID))
  412. return TokError("expected identifier in directive");
  413. int64_t Offset = 0;
  414. SMLoc OffsetLoc;
  415. if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
  416. OffsetLoc = getLexer().getLoc();
  417. if (getParser().parseAbsoluteExpression(Offset))
  418. return true;
  419. }
  420. if (Offset < std::numeric_limits<int32_t>::min() ||
  421. Offset > std::numeric_limits<int32_t>::max())
  422. return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
  423. "than -2147483648 or greater than "
  424. "2147483647");
  425. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  426. getStreamer().emitCOFFImgRel32(Symbol, Offset);
  427. return false;
  428. };
  429. if (getParser().parseMany(parseOp))
  430. return addErrorSuffix(" in directive");
  431. return false;
  432. }
  433. bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
  434. StringRef SymbolID;
  435. if (getParser().parseIdentifier(SymbolID))
  436. return TokError("expected identifier in directive");
  437. if (getLexer().isNot(AsmToken::EndOfStatement))
  438. return TokError("unexpected token in directive");
  439. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  440. Lex();
  441. getStreamer().emitCOFFSafeSEH(Symbol);
  442. return false;
  443. }
  444. bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
  445. StringRef SymbolID;
  446. if (getParser().parseIdentifier(SymbolID))
  447. return TokError("expected identifier in directive");
  448. if (getLexer().isNot(AsmToken::EndOfStatement))
  449. return TokError("unexpected token in directive");
  450. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  451. Lex();
  452. getStreamer().emitCOFFSectionIndex(Symbol);
  453. return false;
  454. }
  455. bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
  456. StringRef SymbolID;
  457. if (getParser().parseIdentifier(SymbolID))
  458. return TokError("expected identifier in directive");
  459. if (getLexer().isNot(AsmToken::EndOfStatement))
  460. return TokError("unexpected token in directive");
  461. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  462. Lex();
  463. getStreamer().emitCOFFSymbolIndex(Symbol);
  464. return false;
  465. }
  466. /// ::= [ identifier ]
  467. bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
  468. StringRef TypeId = getTok().getIdentifier();
  469. Type = StringSwitch<COFF::COMDATType>(TypeId)
  470. .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
  471. .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
  472. .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
  473. .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
  474. .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
  475. .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
  476. .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
  477. .Default((COFF::COMDATType)0);
  478. if (Type == 0)
  479. return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
  480. Lex();
  481. return false;
  482. }
  483. /// ParseDirectiveLinkOnce
  484. /// ::= .linkonce [ identifier ]
  485. bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
  486. COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
  487. if (getLexer().is(AsmToken::Identifier))
  488. if (parseCOMDATType(Type))
  489. return true;
  490. const MCSectionCOFF *Current =
  491. static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
  492. if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
  493. return Error(Loc, "cannot make section associative with .linkonce");
  494. if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
  495. return Error(Loc, Twine("section '") + Current->getName() +
  496. "' is already linkonce");
  497. Current->setSelection(Type);
  498. if (getLexer().isNot(AsmToken::EndOfStatement))
  499. return TokError("unexpected token in directive");
  500. return false;
  501. }
  502. bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
  503. StringRef SymbolID;
  504. if (getParser().parseIdentifier(SymbolID))
  505. return true;
  506. if (getLexer().isNot(AsmToken::EndOfStatement))
  507. return TokError("unexpected token in directive");
  508. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  509. Lex();
  510. getStreamer().emitWinCFIStartProc(Symbol, Loc);
  511. return false;
  512. }
  513. bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
  514. Lex();
  515. getStreamer().emitWinCFIEndProc(Loc);
  516. return false;
  517. }
  518. bool COFFAsmParser::ParseSEHDirectiveEndFuncletOrFunc(StringRef, SMLoc Loc) {
  519. Lex();
  520. getStreamer().emitWinCFIFuncletOrFuncEnd(Loc);
  521. return false;
  522. }
  523. bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
  524. Lex();
  525. getStreamer().emitWinCFIStartChained(Loc);
  526. return false;
  527. }
  528. bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
  529. Lex();
  530. getStreamer().emitWinCFIEndChained(Loc);
  531. return false;
  532. }
  533. bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
  534. StringRef SymbolID;
  535. if (getParser().parseIdentifier(SymbolID))
  536. return true;
  537. if (getLexer().isNot(AsmToken::Comma))
  538. return TokError("you must specify one or both of @unwind or @except");
  539. Lex();
  540. bool unwind = false, except = false;
  541. if (ParseAtUnwindOrAtExcept(unwind, except))
  542. return true;
  543. if (getLexer().is(AsmToken::Comma)) {
  544. Lex();
  545. if (ParseAtUnwindOrAtExcept(unwind, except))
  546. return true;
  547. }
  548. if (getLexer().isNot(AsmToken::EndOfStatement))
  549. return TokError("unexpected token in directive");
  550. MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
  551. Lex();
  552. getStreamer().emitWinEHHandler(handler, unwind, except, Loc);
  553. return false;
  554. }
  555. bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
  556. Lex();
  557. getStreamer().emitWinEHHandlerData();
  558. return false;
  559. }
  560. bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
  561. int64_t Size;
  562. if (getParser().parseAbsoluteExpression(Size))
  563. return true;
  564. if (getLexer().isNot(AsmToken::EndOfStatement))
  565. return TokError("unexpected token in directive");
  566. Lex();
  567. getStreamer().emitWinCFIAllocStack(Size, Loc);
  568. return false;
  569. }
  570. bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
  571. Lex();
  572. getStreamer().emitWinCFIEndProlog(Loc);
  573. return false;
  574. }
  575. bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
  576. StringRef identifier;
  577. if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))
  578. return TokError("a handler attribute must begin with '@' or '%'");
  579. SMLoc startLoc = getLexer().getLoc();
  580. Lex();
  581. if (getParser().parseIdentifier(identifier))
  582. return Error(startLoc, "expected @unwind or @except");
  583. if (identifier == "unwind")
  584. unwind = true;
  585. else if (identifier == "except")
  586. except = true;
  587. else
  588. return Error(startLoc, "expected @unwind or @except");
  589. return false;
  590. }
  591. namespace llvm {
  592. MCAsmParserExtension *createCOFFAsmParser() {
  593. return new COFFAsmParser;
  594. }
  595. } // end namespace llvm