COFFMasmParser.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. //===- COFFMasmParser.cpp - COFF MASM 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/Twine.h"
  10. #include "llvm/BinaryFormat/COFF.h"
  11. #include "llvm/MC/MCAsmMacro.h"
  12. #include "llvm/MC/MCContext.h"
  13. #include "llvm/MC/MCParser/MCAsmLexer.h"
  14. #include "llvm/MC/MCParser/MCAsmParserExtension.h"
  15. #include "llvm/MC/MCParser/MCTargetAsmParser.h"
  16. #include "llvm/MC/MCSectionCOFF.h"
  17. #include "llvm/MC/MCStreamer.h"
  18. #include "llvm/MC/MCSymbolCOFF.h"
  19. #include "llvm/MC/SectionKind.h"
  20. #include "llvm/Support/Casting.h"
  21. #include "llvm/Support/SMLoc.h"
  22. #include <cstdint>
  23. #include <utility>
  24. using namespace llvm;
  25. namespace {
  26. class COFFMasmParser : public MCAsmParserExtension {
  27. template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
  28. void addDirectiveHandler(StringRef Directive) {
  29. MCAsmParser::ExtensionDirectiveHandler Handler =
  30. std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
  31. getParser().addDirectiveHandler(Directive, Handler);
  32. }
  33. bool ParseSectionSwitch(StringRef SectionName, unsigned Characteristics,
  34. SectionKind Kind);
  35. bool ParseSectionSwitch(StringRef SectionName, unsigned Characteristics,
  36. SectionKind Kind, StringRef COMDATSymName,
  37. COFF::COMDATType Type, Align Alignment);
  38. bool ParseDirectiveProc(StringRef, SMLoc);
  39. bool ParseDirectiveEndProc(StringRef, SMLoc);
  40. bool ParseDirectiveSegment(StringRef, SMLoc);
  41. bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
  42. bool ParseDirectiveIncludelib(StringRef, SMLoc);
  43. bool ParseDirectiveOption(StringRef, SMLoc);
  44. bool ParseDirectiveAlias(StringRef, SMLoc);
  45. bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
  46. bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
  47. bool IgnoreDirective(StringRef, SMLoc) {
  48. while (!getLexer().is(AsmToken::EndOfStatement)) {
  49. Lex();
  50. }
  51. return false;
  52. }
  53. void Initialize(MCAsmParser &Parser) override {
  54. // Call the base implementation.
  55. MCAsmParserExtension::Initialize(Parser);
  56. // x64 directives
  57. addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveAllocStack>(
  58. ".allocstack");
  59. addDirectiveHandler<&COFFMasmParser::ParseSEHDirectiveEndProlog>(
  60. ".endprolog");
  61. // Code label directives
  62. // label
  63. // org
  64. // Conditional control flow directives
  65. // .break
  66. // .continue
  67. // .else
  68. // .elseif
  69. // .endif
  70. // .endw
  71. // .if
  72. // .repeat
  73. // .until
  74. // .untilcxz
  75. // .while
  76. // Data allocation directives
  77. // align
  78. // even
  79. // mmword
  80. // tbyte
  81. // xmmword
  82. // ymmword
  83. // Listing control directives
  84. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
  85. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
  86. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
  87. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
  88. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
  89. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
  90. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
  91. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
  92. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
  93. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
  94. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
  95. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
  96. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
  97. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
  98. // Macro directives
  99. // goto
  100. // Miscellaneous directives
  101. addDirectiveHandler<&COFFMasmParser::ParseDirectiveAlias>("alias");
  102. // assume
  103. // .fpo
  104. addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
  105. "includelib");
  106. addDirectiveHandler<&COFFMasmParser::ParseDirectiveOption>("option");
  107. // popcontext
  108. // pushcontext
  109. // .safeseh
  110. // Procedure directives
  111. addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
  112. // invoke (32-bit only)
  113. addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
  114. // proto
  115. // Processor directives; all ignored
  116. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
  117. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386p");
  118. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
  119. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
  120. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486p");
  121. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
  122. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586p");
  123. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
  124. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686p");
  125. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
  126. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
  127. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
  128. // Scope directives
  129. // comm
  130. // externdef
  131. // Segment directives
  132. // .alpha (32-bit only, order segments alphabetically)
  133. // .dosseg (32-bit only, order segments in DOS convention)
  134. // .seq (32-bit only, order segments sequentially)
  135. addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
  136. // group (32-bit only)
  137. addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
  138. // Simplified segment directives
  139. addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
  140. // .const
  141. addDirectiveHandler<
  142. &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data");
  143. addDirectiveHandler<
  144. &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
  145. // .exit
  146. // .fardata
  147. // .fardata?
  148. addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
  149. // .stack
  150. // .startup
  151. // String directives, written <name> <directive> <params>
  152. // catstr (equivalent to <name> TEXTEQU <params>)
  153. // instr (equivalent to <name> = @InStr(<params>))
  154. // sizestr (equivalent to <name> = @SizeStr(<params>))
  155. // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
  156. // Structure and record directives
  157. // record
  158. // typedef
  159. }
  160. bool ParseSectionDirectiveCode(StringRef, SMLoc) {
  161. return ParseSectionSwitch(".text",
  162. COFF::IMAGE_SCN_CNT_CODE
  163. | COFF::IMAGE_SCN_MEM_EXECUTE
  164. | COFF::IMAGE_SCN_MEM_READ,
  165. SectionKind::getText());
  166. }
  167. bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
  168. return ParseSectionSwitch(".data",
  169. COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
  170. | COFF::IMAGE_SCN_MEM_READ
  171. | COFF::IMAGE_SCN_MEM_WRITE,
  172. SectionKind::getData());
  173. }
  174. bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
  175. return ParseSectionSwitch(".bss",
  176. COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
  177. | COFF::IMAGE_SCN_MEM_READ
  178. | COFF::IMAGE_SCN_MEM_WRITE,
  179. SectionKind::getBSS());
  180. }
  181. /// Stack of active procedure definitions.
  182. SmallVector<StringRef, 1> CurrentProcedures;
  183. SmallVector<bool, 1> CurrentProceduresFramed;
  184. public:
  185. COFFMasmParser() = default;
  186. };
  187. } // end anonymous namespace.
  188. bool COFFMasmParser::ParseSectionSwitch(StringRef SectionName,
  189. unsigned Characteristics,
  190. SectionKind Kind) {
  191. return ParseSectionSwitch(SectionName, Characteristics, Kind, "",
  192. (COFF::COMDATType)0, Align(16));
  193. }
  194. bool COFFMasmParser::ParseSectionSwitch(
  195. StringRef SectionName, unsigned Characteristics, SectionKind Kind,
  196. StringRef COMDATSymName, COFF::COMDATType Type, Align Alignment) {
  197. if (getLexer().isNot(AsmToken::EndOfStatement))
  198. return TokError("unexpected token in section switching directive");
  199. Lex();
  200. MCSection *Section = getContext().getCOFFSection(SectionName, Characteristics,
  201. Kind, COMDATSymName, Type);
  202. Section->setAlignment(Alignment);
  203. getStreamer().switchSection(Section);
  204. return false;
  205. }
  206. bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
  207. StringRef SegmentName;
  208. if (!getLexer().is(AsmToken::Identifier))
  209. return TokError("expected identifier in directive");
  210. SegmentName = getTok().getIdentifier();
  211. Lex();
  212. StringRef SectionName = SegmentName;
  213. SmallVector<char, 247> SectionNameVector;
  214. StringRef Class;
  215. if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
  216. if (SegmentName.size() == 5) {
  217. SectionName = ".text";
  218. } else {
  219. SectionName =
  220. (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
  221. }
  222. Class = "CODE";
  223. }
  224. // Parse all options to end of statement.
  225. // Alignment defaults to PARA if unspecified.
  226. int64_t Alignment = 16;
  227. // Default flags are used only if no characteristics are set.
  228. bool DefaultCharacteristics = true;
  229. unsigned Flags = 0;
  230. // "obsolete" according to the documentation, but still supported.
  231. bool Readonly = false;
  232. while (getLexer().isNot(AsmToken::EndOfStatement)) {
  233. switch (getTok().getKind()) {
  234. default:
  235. break;
  236. case AsmToken::String: {
  237. // Class identifier; overrides Kind.
  238. Class = getTok().getStringContents();
  239. Lex();
  240. break;
  241. }
  242. case AsmToken::Identifier: {
  243. SMLoc KeywordLoc = getTok().getLoc();
  244. StringRef Keyword;
  245. if (getParser().parseIdentifier(Keyword)) {
  246. llvm_unreachable("failed to parse identifier at an identifier token");
  247. }
  248. if (Keyword.equals_insensitive("byte")) {
  249. Alignment = 1;
  250. } else if (Keyword.equals_insensitive("word")) {
  251. Alignment = 2;
  252. } else if (Keyword.equals_insensitive("dword")) {
  253. Alignment = 4;
  254. } else if (Keyword.equals_insensitive("para")) {
  255. Alignment = 16;
  256. } else if (Keyword.equals_insensitive("page")) {
  257. Alignment = 256;
  258. } else if (Keyword.equals_insensitive("align")) {
  259. if (getParser().parseToken(AsmToken::LParen) ||
  260. getParser().parseIntToken(Alignment,
  261. "Expected integer alignment") ||
  262. getParser().parseToken(AsmToken::RParen)) {
  263. return Error(getTok().getLoc(),
  264. "Expected (n) following ALIGN in SEGMENT directive");
  265. }
  266. if (!isPowerOf2_64(Alignment) || Alignment > 8192) {
  267. return Error(KeywordLoc,
  268. "ALIGN argument must be a power of 2 from 1 to 8192");
  269. }
  270. } else if (Keyword.equals_insensitive("alias")) {
  271. if (getParser().parseToken(AsmToken::LParen) ||
  272. !getTok().is(AsmToken::String))
  273. return Error(
  274. getTok().getLoc(),
  275. "Expected (string) following ALIAS in SEGMENT directive");
  276. SectionName = getTok().getStringContents();
  277. Lex();
  278. if (getParser().parseToken(AsmToken::RParen))
  279. return Error(
  280. getTok().getLoc(),
  281. "Expected (string) following ALIAS in SEGMENT directive");
  282. } else if (Keyword.equals_insensitive("readonly")) {
  283. Readonly = true;
  284. } else {
  285. unsigned Characteristic =
  286. StringSwitch<unsigned>(Keyword)
  287. .CaseLower("info", COFF::IMAGE_SCN_LNK_INFO)
  288. .CaseLower("read", COFF::IMAGE_SCN_MEM_READ)
  289. .CaseLower("write", COFF::IMAGE_SCN_MEM_WRITE)
  290. .CaseLower("execute", COFF::IMAGE_SCN_MEM_EXECUTE)
  291. .CaseLower("shared", COFF::IMAGE_SCN_MEM_SHARED)
  292. .CaseLower("nopage", COFF::IMAGE_SCN_MEM_NOT_PAGED)
  293. .CaseLower("nocache", COFF::IMAGE_SCN_MEM_NOT_CACHED)
  294. .CaseLower("discard", COFF::IMAGE_SCN_MEM_DISCARDABLE)
  295. .Default(-1);
  296. if (Characteristic == static_cast<unsigned>(-1)) {
  297. return Error(KeywordLoc,
  298. "Expected characteristic in SEGMENT directive; found '" +
  299. Keyword + "'");
  300. }
  301. Flags |= Characteristic;
  302. DefaultCharacteristics = false;
  303. }
  304. }
  305. }
  306. }
  307. SectionKind Kind = StringSwitch<SectionKind>(Class)
  308. .CaseLower("data", SectionKind::getData())
  309. .CaseLower("code", SectionKind::getText())
  310. .CaseLower("const", SectionKind::getReadOnly())
  311. .Default(SectionKind::getData());
  312. if (Kind.isText()) {
  313. if (DefaultCharacteristics) {
  314. Flags |= COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ;
  315. }
  316. Flags |= COFF::IMAGE_SCN_CNT_CODE;
  317. } else {
  318. if (DefaultCharacteristics) {
  319. Flags |= COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
  320. }
  321. Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  322. }
  323. if (Readonly) {
  324. Flags &= ~COFF::IMAGE_SCN_MEM_WRITE;
  325. }
  326. MCSection *Section = getContext().getCOFFSection(SectionName, Flags, Kind, "",
  327. (COFF::COMDATType)(0));
  328. if (Alignment != 0) {
  329. Section->setAlignment(Align(Alignment));
  330. }
  331. getStreamer().switchSection(Section);
  332. return false;
  333. }
  334. /// ParseDirectiveSegmentEnd
  335. /// ::= identifier "ends"
  336. bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
  337. StringRef SegmentName;
  338. if (!getLexer().is(AsmToken::Identifier))
  339. return TokError("expected identifier in directive");
  340. SegmentName = getTok().getIdentifier();
  341. // Ignore; no action necessary.
  342. Lex();
  343. return false;
  344. }
  345. /// ParseDirectiveIncludelib
  346. /// ::= "includelib" identifier
  347. bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
  348. StringRef Lib;
  349. if (getParser().parseIdentifier(Lib))
  350. return TokError("expected identifier in includelib directive");
  351. unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
  352. SectionKind Kind = SectionKind::getData();
  353. getStreamer().pushSection();
  354. getStreamer().switchSection(getContext().getCOFFSection(
  355. ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
  356. getStreamer().emitBytes("/DEFAULTLIB:");
  357. getStreamer().emitBytes(Lib);
  358. getStreamer().emitBytes(" ");
  359. getStreamer().popSection();
  360. return false;
  361. }
  362. /// ParseDirectiveOption
  363. /// ::= "option" option-list
  364. bool COFFMasmParser::ParseDirectiveOption(StringRef Directive, SMLoc Loc) {
  365. auto parseOption = [&]() -> bool {
  366. StringRef Option;
  367. if (getParser().parseIdentifier(Option))
  368. return TokError("expected identifier for option name");
  369. if (Option.equals_insensitive("prologue")) {
  370. StringRef MacroId;
  371. if (parseToken(AsmToken::Colon) || getParser().parseIdentifier(MacroId))
  372. return TokError("expected :macroId after OPTION PROLOGUE");
  373. if (MacroId.equals_insensitive("none")) {
  374. // Since we currently don't implement prologues/epilogues, NONE is our
  375. // default.
  376. return false;
  377. }
  378. return TokError("OPTION PROLOGUE is currently unsupported");
  379. }
  380. if (Option.equals_insensitive("epilogue")) {
  381. StringRef MacroId;
  382. if (parseToken(AsmToken::Colon) || getParser().parseIdentifier(MacroId))
  383. return TokError("expected :macroId after OPTION EPILOGUE");
  384. if (MacroId.equals_insensitive("none")) {
  385. // Since we currently don't implement prologues/epilogues, NONE is our
  386. // default.
  387. return false;
  388. }
  389. return TokError("OPTION EPILOGUE is currently unsupported");
  390. }
  391. return TokError("OPTION '" + Option + "' is currently unsupported");
  392. };
  393. if (parseMany(parseOption))
  394. return addErrorSuffix(" in OPTION directive");
  395. return false;
  396. }
  397. /// ParseDirectiveProc
  398. /// TODO(epastor): Implement parameters and other attributes.
  399. /// ::= label "proc" [[distance]]
  400. /// statements
  401. /// label "endproc"
  402. bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
  403. StringRef Label;
  404. if (getParser().parseIdentifier(Label))
  405. return Error(Loc, "expected identifier for procedure");
  406. if (getLexer().is(AsmToken::Identifier)) {
  407. StringRef nextVal = getTok().getString();
  408. SMLoc nextLoc = getTok().getLoc();
  409. if (nextVal.equals_insensitive("far")) {
  410. // TODO(epastor): Handle far procedure definitions.
  411. Lex();
  412. return Error(nextLoc, "far procedure definitions not yet supported");
  413. } else if (nextVal.equals_insensitive("near")) {
  414. Lex();
  415. nextVal = getTok().getString();
  416. nextLoc = getTok().getLoc();
  417. }
  418. }
  419. MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext().getOrCreateSymbol(Label));
  420. // Define symbol as simple external function
  421. Sym->setExternal(true);
  422. Sym->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT);
  423. bool Framed = false;
  424. if (getLexer().is(AsmToken::Identifier) &&
  425. getTok().getString().equals_insensitive("frame")) {
  426. Lex();
  427. Framed = true;
  428. getStreamer().emitWinCFIStartProc(Sym, Loc);
  429. }
  430. getStreamer().emitLabel(Sym, Loc);
  431. CurrentProcedures.push_back(Label);
  432. CurrentProceduresFramed.push_back(Framed);
  433. return false;
  434. }
  435. bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
  436. StringRef Label;
  437. SMLoc LabelLoc = getTok().getLoc();
  438. if (getParser().parseIdentifier(Label))
  439. return Error(LabelLoc, "expected identifier for procedure end");
  440. if (CurrentProcedures.empty())
  441. return Error(Loc, "endp outside of procedure block");
  442. else if (!CurrentProcedures.back().equals_insensitive(Label))
  443. return Error(LabelLoc, "endp does not match current procedure '" +
  444. CurrentProcedures.back() + "'");
  445. if (CurrentProceduresFramed.back()) {
  446. getStreamer().emitWinCFIEndProc(Loc);
  447. }
  448. CurrentProcedures.pop_back();
  449. CurrentProceduresFramed.pop_back();
  450. return false;
  451. }
  452. bool COFFMasmParser::ParseDirectiveAlias(StringRef Directive, SMLoc Loc) {
  453. std::string AliasName, ActualName;
  454. if (getTok().isNot(AsmToken::Less) ||
  455. getParser().parseAngleBracketString(AliasName))
  456. return Error(getTok().getLoc(), "expected <aliasName>");
  457. if (getParser().parseToken(AsmToken::Equal))
  458. return addErrorSuffix(" in " + Directive + " directive");
  459. if (getTok().isNot(AsmToken::Less) ||
  460. getParser().parseAngleBracketString(ActualName))
  461. return Error(getTok().getLoc(), "expected <actualName>");
  462. MCSymbol *Alias = getContext().getOrCreateSymbol(AliasName);
  463. MCSymbol *Actual = getContext().getOrCreateSymbol(ActualName);
  464. getStreamer().emitWeakReference(Alias, Actual);
  465. return false;
  466. }
  467. bool COFFMasmParser::ParseSEHDirectiveAllocStack(StringRef Directive,
  468. SMLoc Loc) {
  469. int64_t Size;
  470. SMLoc SizeLoc = getTok().getLoc();
  471. if (getParser().parseAbsoluteExpression(Size))
  472. return Error(SizeLoc, "expected integer size");
  473. if (Size % 8 != 0)
  474. return Error(SizeLoc, "stack size must be a multiple of 8");
  475. getStreamer().emitWinCFIAllocStack(static_cast<unsigned>(Size), Loc);
  476. return false;
  477. }
  478. bool COFFMasmParser::ParseSEHDirectiveEndProlog(StringRef Directive,
  479. SMLoc Loc) {
  480. getStreamer().emitWinCFIEndProlog(Loc);
  481. return false;
  482. }
  483. namespace llvm {
  484. MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
  485. } // end namespace llvm