COFFAsmParser.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. //===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/MC/MCParser/MCAsmParserExtension.h"
  10. #include "llvm/ADT/StringSwitch.h"
  11. #include "llvm/ADT/Twine.h"
  12. #include "llvm/MC/MCAsmInfo.h"
  13. #include "llvm/MC/MCContext.h"
  14. #include "llvm/MC/MCExpr.h"
  15. #include "llvm/MC/MCObjectFileInfo.h"
  16. #include "llvm/MC/MCParser/MCAsmLexer.h"
  17. #include "llvm/MC/MCRegisterInfo.h"
  18. #include "llvm/MC/MCSectionCOFF.h"
  19. #include "llvm/MC/MCStreamer.h"
  20. #include "llvm/MC/MCTargetAsmParser.h"
  21. #include "llvm/Support/COFF.h"
  22. using namespace llvm;
  23. namespace {
  24. class COFFAsmParser : public MCAsmParserExtension {
  25. template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
  26. void addDirectiveHandler(StringRef Directive) {
  27. MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
  28. this, HandleDirective<COFFAsmParser, HandlerMethod>);
  29. getParser().addDirectiveHandler(Directive, Handler);
  30. }
  31. bool ParseSectionSwitch(StringRef Section,
  32. unsigned Characteristics,
  33. SectionKind Kind);
  34. bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
  35. SectionKind Kind, StringRef COMDATSymName,
  36. COFF::COMDATType Type);
  37. bool ParseSectionName(StringRef &SectionName);
  38. bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
  39. void Initialize(MCAsmParser &Parser) override {
  40. // Call the base implementation.
  41. MCAsmParserExtension::Initialize(Parser);
  42. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
  43. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
  44. addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
  45. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
  46. addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
  47. addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
  48. addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
  49. addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
  50. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
  51. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
  52. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
  53. addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
  54. // Win64 EH directives.
  55. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
  56. ".seh_proc");
  57. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
  58. ".seh_endproc");
  59. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
  60. ".seh_startchained");
  61. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
  62. ".seh_endchained");
  63. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
  64. ".seh_handler");
  65. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
  66. ".seh_handlerdata");
  67. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
  68. ".seh_pushreg");
  69. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
  70. ".seh_setframe");
  71. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
  72. ".seh_stackalloc");
  73. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
  74. ".seh_savereg");
  75. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
  76. ".seh_savexmm");
  77. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
  78. ".seh_pushframe");
  79. addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
  80. ".seh_endprologue");
  81. addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
  82. }
  83. bool ParseSectionDirectiveText(StringRef, SMLoc) {
  84. return ParseSectionSwitch(".text",
  85. COFF::IMAGE_SCN_CNT_CODE
  86. | COFF::IMAGE_SCN_MEM_EXECUTE
  87. | COFF::IMAGE_SCN_MEM_READ,
  88. SectionKind::getText());
  89. }
  90. bool ParseSectionDirectiveData(StringRef, SMLoc) {
  91. return ParseSectionSwitch(".data",
  92. COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
  93. | COFF::IMAGE_SCN_MEM_READ
  94. | COFF::IMAGE_SCN_MEM_WRITE,
  95. SectionKind::getDataRel());
  96. }
  97. bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
  98. return ParseSectionSwitch(".bss",
  99. COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
  100. | COFF::IMAGE_SCN_MEM_READ
  101. | COFF::IMAGE_SCN_MEM_WRITE,
  102. SectionKind::getBSS());
  103. }
  104. bool ParseDirectiveSection(StringRef, SMLoc);
  105. bool ParseDirectiveDef(StringRef, SMLoc);
  106. bool ParseDirectiveScl(StringRef, SMLoc);
  107. bool ParseDirectiveType(StringRef, SMLoc);
  108. bool ParseDirectiveEndef(StringRef, SMLoc);
  109. bool ParseDirectiveSecRel32(StringRef, SMLoc);
  110. bool ParseDirectiveSecIdx(StringRef, SMLoc);
  111. bool ParseDirectiveSafeSEH(StringRef, SMLoc);
  112. bool parseCOMDATType(COFF::COMDATType &Type);
  113. bool ParseDirectiveLinkOnce(StringRef, SMLoc);
  114. // Win64 EH directives.
  115. bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
  116. bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
  117. bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
  118. bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
  119. bool ParseSEHDirectiveHandler(StringRef, SMLoc);
  120. bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
  121. bool ParseSEHDirectivePushReg(StringRef, SMLoc);
  122. bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
  123. bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
  124. bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
  125. bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
  126. bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
  127. bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
  128. bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
  129. bool ParseSEHRegisterNumber(unsigned &RegNo);
  130. bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
  131. public:
  132. COFFAsmParser() {}
  133. };
  134. } // end annonomous namespace.
  135. static SectionKind computeSectionKind(unsigned Flags) {
  136. if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
  137. return SectionKind::getText();
  138. if (Flags & COFF::IMAGE_SCN_MEM_READ &&
  139. (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
  140. return SectionKind::getReadOnly();
  141. return SectionKind::getDataRel();
  142. }
  143. bool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
  144. enum {
  145. None = 0,
  146. Alloc = 1 << 0,
  147. Code = 1 << 1,
  148. Load = 1 << 2,
  149. InitData = 1 << 3,
  150. Shared = 1 << 4,
  151. NoLoad = 1 << 5,
  152. NoRead = 1 << 6,
  153. NoWrite = 1 << 7
  154. };
  155. bool ReadOnlyRemoved = false;
  156. unsigned SecFlags = None;
  157. for (char FlagChar : FlagsString) {
  158. switch (FlagChar) {
  159. case 'a':
  160. // Ignored.
  161. break;
  162. case 'b': // bss section
  163. SecFlags |= Alloc;
  164. if (SecFlags & InitData)
  165. return TokError("conflicting section flags 'b' and 'd'.");
  166. SecFlags &= ~Load;
  167. break;
  168. case 'd': // data section
  169. SecFlags |= InitData;
  170. if (SecFlags & Alloc)
  171. return TokError("conflicting section flags 'b' and 'd'.");
  172. SecFlags &= ~NoWrite;
  173. if ((SecFlags & NoLoad) == 0)
  174. SecFlags |= Load;
  175. break;
  176. case 'n': // section is not loaded
  177. SecFlags |= NoLoad;
  178. SecFlags &= ~Load;
  179. break;
  180. case 'r': // read-only
  181. ReadOnlyRemoved = false;
  182. SecFlags |= NoWrite;
  183. if ((SecFlags & Code) == 0)
  184. SecFlags |= InitData;
  185. if ((SecFlags & NoLoad) == 0)
  186. SecFlags |= Load;
  187. break;
  188. case 's': // shared section
  189. SecFlags |= Shared | InitData;
  190. SecFlags &= ~NoWrite;
  191. if ((SecFlags & NoLoad) == 0)
  192. SecFlags |= Load;
  193. break;
  194. case 'w': // writable
  195. SecFlags &= ~NoWrite;
  196. ReadOnlyRemoved = true;
  197. break;
  198. case 'x': // executable section
  199. SecFlags |= Code;
  200. if ((SecFlags & NoLoad) == 0)
  201. SecFlags |= Load;
  202. if (!ReadOnlyRemoved)
  203. SecFlags |= NoWrite;
  204. break;
  205. case 'y': // not readable
  206. SecFlags |= NoRead | NoWrite;
  207. break;
  208. default:
  209. return TokError("unknown flag");
  210. }
  211. }
  212. *Flags = 0;
  213. if (SecFlags == None)
  214. SecFlags = InitData;
  215. if (SecFlags & Code)
  216. *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
  217. if (SecFlags & InitData)
  218. *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  219. if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
  220. *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
  221. if (SecFlags & NoLoad)
  222. *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
  223. if ((SecFlags & NoRead) == 0)
  224. *Flags |= COFF::IMAGE_SCN_MEM_READ;
  225. if ((SecFlags & NoWrite) == 0)
  226. *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
  227. if (SecFlags & Shared)
  228. *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
  229. return false;
  230. }
  231. /// ParseDirectiveSymbolAttribute
  232. /// ::= { ".weak", ... } [ identifier ( , identifier )* ]
  233. bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
  234. MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
  235. .Case(".weak", MCSA_Weak)
  236. .Default(MCSA_Invalid);
  237. assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
  238. if (getLexer().isNot(AsmToken::EndOfStatement)) {
  239. for (;;) {
  240. StringRef Name;
  241. if (getParser().parseIdentifier(Name))
  242. return TokError("expected identifier in directive");
  243. MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
  244. getStreamer().EmitSymbolAttribute(Sym, Attr);
  245. if (getLexer().is(AsmToken::EndOfStatement))
  246. break;
  247. if (getLexer().isNot(AsmToken::Comma))
  248. return TokError("unexpected token in directive");
  249. Lex();
  250. }
  251. }
  252. Lex();
  253. return false;
  254. }
  255. bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
  256. unsigned Characteristics,
  257. SectionKind Kind) {
  258. return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
  259. }
  260. bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
  261. unsigned Characteristics,
  262. SectionKind Kind,
  263. StringRef COMDATSymName,
  264. COFF::COMDATType Type) {
  265. if (getLexer().isNot(AsmToken::EndOfStatement))
  266. return TokError("unexpected token in section switching directive");
  267. Lex();
  268. getStreamer().SwitchSection(getContext().getCOFFSection(
  269. Section, Characteristics, Kind, COMDATSymName, Type));
  270. return false;
  271. }
  272. bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
  273. if (!getLexer().is(AsmToken::Identifier))
  274. return true;
  275. SectionName = getTok().getIdentifier();
  276. Lex();
  277. return false;
  278. }
  279. // .section name [, "flags"] [, identifier [ identifier ], identifier]
  280. //
  281. // Supported flags:
  282. // a: Ignored.
  283. // b: BSS section (uninitialized data)
  284. // d: data section (initialized data)
  285. // n: Discardable section
  286. // r: Readable section
  287. // s: Shared section
  288. // w: Writable section
  289. // x: Executable section
  290. // y: Not-readable section (clears 'r')
  291. //
  292. // Subsections are not supported.
  293. bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
  294. StringRef SectionName;
  295. if (ParseSectionName(SectionName))
  296. return TokError("expected identifier in directive");
  297. unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
  298. COFF::IMAGE_SCN_MEM_READ |
  299. COFF::IMAGE_SCN_MEM_WRITE;
  300. if (getLexer().is(AsmToken::Comma)) {
  301. Lex();
  302. if (getLexer().isNot(AsmToken::String))
  303. return TokError("expected string in directive");
  304. StringRef FlagsStr = getTok().getStringContents();
  305. Lex();
  306. if (ParseSectionFlags(FlagsStr, &Flags))
  307. return true;
  308. }
  309. COFF::COMDATType Type = (COFF::COMDATType)0;
  310. StringRef COMDATSymName;
  311. if (getLexer().is(AsmToken::Comma)) {
  312. Type = COFF::IMAGE_COMDAT_SELECT_ANY;
  313. Lex();
  314. Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
  315. if (!getLexer().is(AsmToken::Identifier))
  316. return TokError("expected comdat type such as 'discard' or 'largest' "
  317. "after protection bits");
  318. if (parseCOMDATType(Type))
  319. return true;
  320. if (getLexer().isNot(AsmToken::Comma))
  321. return TokError("expected comma in directive");
  322. Lex();
  323. if (getParser().parseIdentifier(COMDATSymName))
  324. return TokError("expected identifier in directive");
  325. }
  326. if (getLexer().isNot(AsmToken::EndOfStatement))
  327. return TokError("unexpected token in directive");
  328. SectionKind Kind = computeSectionKind(Flags);
  329. if (Kind.isText()) {
  330. const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
  331. if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
  332. Flags |= COFF::IMAGE_SCN_MEM_16BIT;
  333. }
  334. ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
  335. return false;
  336. }
  337. bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
  338. StringRef SymbolName;
  339. if (getParser().parseIdentifier(SymbolName))
  340. return TokError("expected identifier in directive");
  341. MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
  342. getStreamer().BeginCOFFSymbolDef(Sym);
  343. Lex();
  344. return false;
  345. }
  346. bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
  347. int64_t SymbolStorageClass;
  348. if (getParser().parseAbsoluteExpression(SymbolStorageClass))
  349. return true;
  350. if (getLexer().isNot(AsmToken::EndOfStatement))
  351. return TokError("unexpected token in directive");
  352. Lex();
  353. getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
  354. return false;
  355. }
  356. bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
  357. int64_t Type;
  358. if (getParser().parseAbsoluteExpression(Type))
  359. return true;
  360. if (getLexer().isNot(AsmToken::EndOfStatement))
  361. return TokError("unexpected token in directive");
  362. Lex();
  363. getStreamer().EmitCOFFSymbolType(Type);
  364. return false;
  365. }
  366. bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
  367. Lex();
  368. getStreamer().EndCOFFSymbolDef();
  369. return false;
  370. }
  371. bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
  372. StringRef SymbolID;
  373. if (getParser().parseIdentifier(SymbolID))
  374. return TokError("expected identifier in directive");
  375. if (getLexer().isNot(AsmToken::EndOfStatement))
  376. return TokError("unexpected token in directive");
  377. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  378. Lex();
  379. getStreamer().EmitCOFFSecRel32(Symbol);
  380. return false;
  381. }
  382. bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
  383. StringRef SymbolID;
  384. if (getParser().parseIdentifier(SymbolID))
  385. return TokError("expected identifier in directive");
  386. if (getLexer().isNot(AsmToken::EndOfStatement))
  387. return TokError("unexpected token in directive");
  388. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  389. Lex();
  390. getStreamer().EmitCOFFSafeSEH(Symbol);
  391. return false;
  392. }
  393. bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
  394. StringRef SymbolID;
  395. if (getParser().parseIdentifier(SymbolID))
  396. return TokError("expected identifier in directive");
  397. if (getLexer().isNot(AsmToken::EndOfStatement))
  398. return TokError("unexpected token in directive");
  399. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  400. Lex();
  401. getStreamer().EmitCOFFSectionIndex(Symbol);
  402. return false;
  403. }
  404. /// ::= [ identifier ]
  405. bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
  406. StringRef TypeId = getTok().getIdentifier();
  407. Type = StringSwitch<COFF::COMDATType>(TypeId)
  408. .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
  409. .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
  410. .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
  411. .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
  412. .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
  413. .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
  414. .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
  415. .Default((COFF::COMDATType)0);
  416. if (Type == 0)
  417. return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
  418. Lex();
  419. return false;
  420. }
  421. /// ParseDirectiveLinkOnce
  422. /// ::= .linkonce [ identifier ]
  423. bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
  424. COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
  425. if (getLexer().is(AsmToken::Identifier))
  426. if (parseCOMDATType(Type))
  427. return true;
  428. const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
  429. getStreamer().getCurrentSection().first);
  430. if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
  431. return Error(Loc, "cannot make section associative with .linkonce");
  432. if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
  433. return Error(Loc, Twine("section '") + Current->getSectionName() +
  434. "' is already linkonce");
  435. Current->setSelection(Type);
  436. if (getLexer().isNot(AsmToken::EndOfStatement))
  437. return TokError("unexpected token in directive");
  438. return false;
  439. }
  440. bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
  441. StringRef SymbolID;
  442. if (getParser().parseIdentifier(SymbolID))
  443. return true;
  444. if (getLexer().isNot(AsmToken::EndOfStatement))
  445. return TokError("unexpected token in directive");
  446. MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
  447. Lex();
  448. getStreamer().EmitWinCFIStartProc(Symbol);
  449. return false;
  450. }
  451. bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
  452. Lex();
  453. getStreamer().EmitWinCFIEndProc();
  454. return false;
  455. }
  456. bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
  457. Lex();
  458. getStreamer().EmitWinCFIStartChained();
  459. return false;
  460. }
  461. bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
  462. Lex();
  463. getStreamer().EmitWinCFIEndChained();
  464. return false;
  465. }
  466. bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
  467. StringRef SymbolID;
  468. if (getParser().parseIdentifier(SymbolID))
  469. return true;
  470. if (getLexer().isNot(AsmToken::Comma))
  471. return TokError("you must specify one or both of @unwind or @except");
  472. Lex();
  473. bool unwind = false, except = false;
  474. if (ParseAtUnwindOrAtExcept(unwind, except))
  475. return true;
  476. if (getLexer().is(AsmToken::Comma)) {
  477. Lex();
  478. if (ParseAtUnwindOrAtExcept(unwind, except))
  479. return true;
  480. }
  481. if (getLexer().isNot(AsmToken::EndOfStatement))
  482. return TokError("unexpected token in directive");
  483. MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
  484. Lex();
  485. getStreamer().EmitWinEHHandler(handler, unwind, except);
  486. return false;
  487. }
  488. bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
  489. Lex();
  490. getStreamer().EmitWinEHHandlerData();
  491. return false;
  492. }
  493. bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
  494. unsigned Reg = 0;
  495. if (ParseSEHRegisterNumber(Reg))
  496. return true;
  497. if (getLexer().isNot(AsmToken::EndOfStatement))
  498. return TokError("unexpected token in directive");
  499. Lex();
  500. getStreamer().EmitWinCFIPushReg(Reg);
  501. return false;
  502. }
  503. bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
  504. unsigned Reg = 0;
  505. int64_t Off;
  506. if (ParseSEHRegisterNumber(Reg))
  507. return true;
  508. if (getLexer().isNot(AsmToken::Comma))
  509. return TokError("you must specify a stack pointer offset");
  510. Lex();
  511. SMLoc startLoc = getLexer().getLoc();
  512. if (getParser().parseAbsoluteExpression(Off))
  513. return true;
  514. if (Off & 0x0F)
  515. return Error(startLoc, "offset is not a multiple of 16");
  516. if (getLexer().isNot(AsmToken::EndOfStatement))
  517. return TokError("unexpected token in directive");
  518. Lex();
  519. getStreamer().EmitWinCFISetFrame(Reg, Off);
  520. return false;
  521. }
  522. bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
  523. int64_t Size;
  524. SMLoc startLoc = getLexer().getLoc();
  525. if (getParser().parseAbsoluteExpression(Size))
  526. return true;
  527. if (Size & 7)
  528. return Error(startLoc, "size is not a multiple of 8");
  529. if (getLexer().isNot(AsmToken::EndOfStatement))
  530. return TokError("unexpected token in directive");
  531. Lex();
  532. getStreamer().EmitWinCFIAllocStack(Size);
  533. return false;
  534. }
  535. bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
  536. unsigned Reg = 0;
  537. int64_t Off;
  538. if (ParseSEHRegisterNumber(Reg))
  539. return true;
  540. if (getLexer().isNot(AsmToken::Comma))
  541. return TokError("you must specify an offset on the stack");
  542. Lex();
  543. SMLoc startLoc = getLexer().getLoc();
  544. if (getParser().parseAbsoluteExpression(Off))
  545. return true;
  546. if (Off & 7)
  547. return Error(startLoc, "size is not a multiple of 8");
  548. if (getLexer().isNot(AsmToken::EndOfStatement))
  549. return TokError("unexpected token in directive");
  550. Lex();
  551. // FIXME: Err on %xmm* registers
  552. getStreamer().EmitWinCFISaveReg(Reg, Off);
  553. return false;
  554. }
  555. // FIXME: This method is inherently x86-specific. It should really be in the
  556. // x86 backend.
  557. bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
  558. unsigned Reg = 0;
  559. int64_t Off;
  560. if (ParseSEHRegisterNumber(Reg))
  561. return true;
  562. if (getLexer().isNot(AsmToken::Comma))
  563. return TokError("you must specify an offset on the stack");
  564. Lex();
  565. SMLoc startLoc = getLexer().getLoc();
  566. if (getParser().parseAbsoluteExpression(Off))
  567. return true;
  568. if (getLexer().isNot(AsmToken::EndOfStatement))
  569. return TokError("unexpected token in directive");
  570. if (Off & 0x0F)
  571. return Error(startLoc, "offset is not a multiple of 16");
  572. Lex();
  573. // FIXME: Err on non-%xmm* registers
  574. getStreamer().EmitWinCFISaveXMM(Reg, Off);
  575. return false;
  576. }
  577. bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
  578. bool Code = false;
  579. StringRef CodeID;
  580. if (getLexer().is(AsmToken::At)) {
  581. SMLoc startLoc = getLexer().getLoc();
  582. Lex();
  583. if (!getParser().parseIdentifier(CodeID)) {
  584. if (CodeID != "code")
  585. return Error(startLoc, "expected @code");
  586. Code = true;
  587. }
  588. }
  589. if (getLexer().isNot(AsmToken::EndOfStatement))
  590. return TokError("unexpected token in directive");
  591. Lex();
  592. getStreamer().EmitWinCFIPushFrame(Code);
  593. return false;
  594. }
  595. bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
  596. Lex();
  597. getStreamer().EmitWinCFIEndProlog();
  598. return false;
  599. }
  600. bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
  601. StringRef identifier;
  602. if (getLexer().isNot(AsmToken::At))
  603. return TokError("a handler attribute must begin with '@'");
  604. SMLoc startLoc = getLexer().getLoc();
  605. Lex();
  606. if (getParser().parseIdentifier(identifier))
  607. return Error(startLoc, "expected @unwind or @except");
  608. if (identifier == "unwind")
  609. unwind = true;
  610. else if (identifier == "except")
  611. except = true;
  612. else
  613. return Error(startLoc, "expected @unwind or @except");
  614. return false;
  615. }
  616. bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
  617. SMLoc startLoc = getLexer().getLoc();
  618. if (getLexer().is(AsmToken::Percent)) {
  619. const MCRegisterInfo *MRI = getContext().getRegisterInfo();
  620. SMLoc endLoc;
  621. unsigned LLVMRegNo;
  622. if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
  623. return true;
  624. #if 0
  625. // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
  626. // violation so this validation code is disabled.
  627. // Check that this is a non-volatile register.
  628. const unsigned *NVRegs = TAI.getCalleeSavedRegs();
  629. unsigned i;
  630. for (i = 0; NVRegs[i] != 0; ++i)
  631. if (NVRegs[i] == LLVMRegNo)
  632. break;
  633. if (NVRegs[i] == 0)
  634. return Error(startLoc, "expected non-volatile register");
  635. #endif
  636. int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
  637. if (SEHRegNo < 0)
  638. return Error(startLoc,"register can't be represented in SEH unwind info");
  639. RegNo = SEHRegNo;
  640. }
  641. else {
  642. int64_t n;
  643. if (getParser().parseAbsoluteExpression(n))
  644. return true;
  645. if (n > 15)
  646. return Error(startLoc, "register number is too high");
  647. RegNo = n;
  648. }
  649. return false;
  650. }
  651. namespace llvm {
  652. MCAsmParserExtension *createCOFFAsmParser() {
  653. return new COFFAsmParser;
  654. }
  655. }