COFFAsmParser.cpp revision 263508
155714Skris//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
255714Skris//
355714Skris//                     The LLVM Compiler Infrastructure
455714Skris//
555714Skris// This file is distributed under the University of Illinois Open Source
655714Skris// License. See LICENSE.TXT for details.
755714Skris//
8280297Sjkim//===----------------------------------------------------------------------===//
955714Skris
1055714Skris#include "llvm/MC/MCParser/MCAsmParserExtension.h"
1155714Skris#include "llvm/ADT/StringSwitch.h"
1255714Skris#include "llvm/ADT/Twine.h"
1355714Skris#include "llvm/MC/MCAsmInfo.h"
1455714Skris#include "llvm/MC/MCContext.h"
15280297Sjkim#include "llvm/MC/MCExpr.h"
1655714Skris#include "llvm/MC/MCParser/MCAsmLexer.h"
1755714Skris#include "llvm/MC/MCRegisterInfo.h"
1855714Skris#include "llvm/MC/MCSectionCOFF.h"
1955714Skris#include "llvm/MC/MCStreamer.h"
2055714Skris#include "llvm/MC/MCTargetAsmParser.h"
2155714Skris#include "llvm/Support/COFF.h"
22280297Sjkimusing namespace llvm;
2355714Skris
2455714Skrisnamespace {
2555714Skris
2655714Skrisclass COFFAsmParser : public MCAsmParserExtension {
2755714Skris  template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
2855714Skris  void addDirectiveHandler(StringRef Directive) {
2955714Skris    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
3055714Skris        this, HandleDirective<COFFAsmParser, HandlerMethod>);
3155714Skris    getParser().addDirectiveHandler(Directive, Handler);
3255714Skris  }
3355714Skris
3455714Skris  bool ParseSectionSwitch(StringRef Section,
3555714Skris                          unsigned Characteristics,
3655714Skris                          SectionKind Kind);
37280297Sjkim
3855714Skris  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
3955714Skris                          SectionKind Kind, StringRef COMDATSymName,
40280297Sjkim                          COFF::COMDATType Type, const MCSectionCOFF *Assoc);
4155714Skris
4255714Skris  bool ParseSectionName(StringRef &SectionName);
4355714Skris  bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
4455714Skris
4555714Skris  virtual void Initialize(MCAsmParser &Parser) {
4655714Skris    // Call the base implementation.
4755714Skris    MCAsmParserExtension::Initialize(Parser);
4855714Skris
4955714Skris    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
5055714Skris    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
5155714Skris    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
52280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
5355714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
5455714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
5555714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
5655714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
5755714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
5855714Skris    addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
5955714Skris
60280297Sjkim    // Win64 EH directives.
6155714Skris    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
62280297Sjkim                                                                   ".seh_proc");
63109998Smarkm    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
64280297Sjkim                                                                ".seh_endproc");
65280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
66280297Sjkim                                                           ".seh_startchained");
67280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
68280297Sjkim                                                             ".seh_endchained");
6955714Skris    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
70280297Sjkim                                                                ".seh_handler");
71280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
7255714Skris                                                            ".seh_handlerdata");
73280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
74280297Sjkim                                                                ".seh_pushreg");
75280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
76280297Sjkim                                                               ".seh_setframe");
77280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
78280297Sjkim                                                             ".seh_stackalloc");
79280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
80280297Sjkim                                                                ".seh_savereg");
81280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
82280297Sjkim                                                                ".seh_savexmm");
83280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
8455714Skris                                                              ".seh_pushframe");
85280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
86280297Sjkim                                                            ".seh_endprologue");
87280297Sjkim    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
88280297Sjkim  }
89280297Sjkim
90280297Sjkim  bool ParseSectionDirectiveText(StringRef, SMLoc) {
9155714Skris    return ParseSectionSwitch(".text",
92280297Sjkim                              COFF::IMAGE_SCN_CNT_CODE
93280297Sjkim                            | COFF::IMAGE_SCN_MEM_EXECUTE
94280297Sjkim                            | COFF::IMAGE_SCN_MEM_READ,
9555714Skris                              SectionKind::getText());
96280297Sjkim  }
97280297Sjkim  bool ParseSectionDirectiveData(StringRef, SMLoc) {
98280297Sjkim    return ParseSectionSwitch(".data",
99280297Sjkim                              COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
100109998Smarkm                            | COFF::IMAGE_SCN_MEM_READ
101280297Sjkim                            | COFF::IMAGE_SCN_MEM_WRITE,
102280297Sjkim                              SectionKind::getDataRel());
10355714Skris  }
10455714Skris  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
105280297Sjkim    return ParseSectionSwitch(".bss",
106280297Sjkim                              COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
10755714Skris                            | COFF::IMAGE_SCN_MEM_READ
108280297Sjkim                            | COFF::IMAGE_SCN_MEM_WRITE,
109280297Sjkim                              SectionKind::getBSS());
110280297Sjkim  }
111280297Sjkim
11255714Skris  bool ParseDirectiveSection(StringRef, SMLoc);
11355714Skris  bool ParseDirectiveDef(StringRef, SMLoc);
114280297Sjkim  bool ParseDirectiveScl(StringRef, SMLoc);
115280297Sjkim  bool ParseDirectiveType(StringRef, SMLoc);
116280297Sjkim  bool ParseDirectiveEndef(StringRef, SMLoc);
117280297Sjkim  bool ParseDirectiveSecRel32(StringRef, SMLoc);
118280297Sjkim  bool parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
119280297Sjkim                               const MCSectionCOFF *&Assoc);
120280297Sjkim  bool ParseDirectiveLinkOnce(StringRef, SMLoc);
121280297Sjkim
122280297Sjkim  // Win64 EH directives.
123280297Sjkim  bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
124280297Sjkim  bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
125280297Sjkim  bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
126280297Sjkim  bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
127280297Sjkim  bool ParseSEHDirectiveHandler(StringRef, SMLoc);
12855714Skris  bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
129280297Sjkim  bool ParseSEHDirectivePushReg(StringRef, SMLoc);
130280297Sjkim  bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
131280297Sjkim  bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
132280297Sjkim  bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
13355714Skris  bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
134280297Sjkim  bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
135280297Sjkim  bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
136280297Sjkim
137280297Sjkim  bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
138280297Sjkim  bool ParseSEHRegisterNumber(unsigned &RegNo);
13955714Skris  bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
140280297Sjkimpublic:
141280297Sjkim  COFFAsmParser() {}
142280297Sjkim};
143280297Sjkim
14455714Skris} // end annonomous namespace.
145280297Sjkim
146280297Sjkimstatic SectionKind computeSectionKind(unsigned Flags) {
147280297Sjkim  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
148280297Sjkim    return SectionKind::getText();
14955714Skris  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
15055714Skris      (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
151280297Sjkim    return SectionKind::getReadOnly();
152280297Sjkim  return SectionKind::getDataRel();
153280297Sjkim}
154280297Sjkim
155280297Sjkimbool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
156280297Sjkim  enum {
157280297Sjkim    None      = 0,
158280297Sjkim    Alloc     = 1 << 0,
159280297Sjkim    Code      = 1 << 1,
160280297Sjkim    Load      = 1 << 2,
161280297Sjkim    InitData  = 1 << 3,
162280297Sjkim    Shared    = 1 << 4,
163280297Sjkim    NoLoad    = 1 << 5,
16455714Skris    NoRead    = 1 << 6,
165290207Sjkim    NoWrite  =  1 << 7
166280297Sjkim  };
167290207Sjkim
168290207Sjkim  bool ReadOnlyRemoved = false;
169280297Sjkim  unsigned SecFlags = None;
170280297Sjkim
171280297Sjkim  for (unsigned i = 0; i < FlagsString.size(); ++i) {
172280297Sjkim    switch (FlagsString[i]) {
173280297Sjkim    case 'a':
174280297Sjkim      // Ignored.
175280297Sjkim      break;
176280297Sjkim
177280297Sjkim    case 'b': // bss section
178280297Sjkim      SecFlags |= Alloc;
179109998Smarkm      if (SecFlags & InitData)
180280297Sjkim        return TokError("conflicting section flags 'b' and 'd'.");
181280297Sjkim      SecFlags &= ~Load;
182280297Sjkim      break;
18355714Skris
184280297Sjkim    case 'd': // data section
185280297Sjkim      SecFlags |= InitData;
186280297Sjkim      if (SecFlags & Alloc)
187280297Sjkim        return TokError("conflicting section flags 'b' and 'd'.");
18855714Skris      SecFlags &= ~NoWrite;
189280297Sjkim      if ((SecFlags & NoLoad) == 0)
19055714Skris        SecFlags |= Load;
191280297Sjkim      break;
192280297Sjkim
19355714Skris    case 'n': // section is not loaded
194280297Sjkim      SecFlags |= NoLoad;
195280297Sjkim      SecFlags &= ~Load;
196280297Sjkim      break;
197280297Sjkim
198280297Sjkim    case 'r': // read-only
199280297Sjkim      ReadOnlyRemoved = false;
200280297Sjkim      SecFlags |= NoWrite;
201280297Sjkim      if ((SecFlags & Code) == 0)
202280297Sjkim        SecFlags |= InitData;
203280297Sjkim      if ((SecFlags & NoLoad) == 0)
204280297Sjkim        SecFlags |= Load;
20555714Skris      break;
206280297Sjkim
207280297Sjkim    case 's': // shared section
208280297Sjkim      SecFlags |= Shared | InitData;
209280297Sjkim      SecFlags &= ~NoWrite;
210280297Sjkim      if ((SecFlags & NoLoad) == 0)
211280297Sjkim        SecFlags |= Load;
212280297Sjkim      break;
213280297Sjkim
214280297Sjkim    case 'w': // writable
21555714Skris      SecFlags &= ~NoWrite;
216280297Sjkim      ReadOnlyRemoved = true;
217280297Sjkim      break;
218280297Sjkim
219280297Sjkim    case 'x': // executable section
220280297Sjkim      SecFlags |= Code;
22155714Skris      if ((SecFlags & NoLoad) == 0)
222280297Sjkim        SecFlags |= Load;
223280297Sjkim      if (!ReadOnlyRemoved)
224280297Sjkim        SecFlags |= NoWrite;
225280297Sjkim      break;
226280297Sjkim
227280297Sjkim    case 'y': // not readable
228280297Sjkim      SecFlags |= NoRead | NoWrite;
229280297Sjkim      break;
230280297Sjkim
231280297Sjkim    default:
232280297Sjkim      return TokError("unknown flag");
233280297Sjkim    }
234280297Sjkim  }
235280297Sjkim
236280297Sjkim  *Flags = 0;
237280297Sjkim
238280297Sjkim  if (SecFlags == None)
239280297Sjkim    SecFlags = InitData;
240280297Sjkim
241280297Sjkim  if (SecFlags & Code)
242280297Sjkim    *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
243280297Sjkim  if (SecFlags & InitData)
244280297Sjkim    *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
245280297Sjkim  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
246280297Sjkim    *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
247280297Sjkim  if (SecFlags & NoLoad)
248280297Sjkim    *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
249280297Sjkim  if ((SecFlags & NoRead) == 0)
250280297Sjkim    *Flags |= COFF::IMAGE_SCN_MEM_READ;
251280297Sjkim  if ((SecFlags & NoWrite) == 0)
252280297Sjkim    *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
253280297Sjkim  if (SecFlags & Shared)
254280297Sjkim    *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
255280297Sjkim
256280297Sjkim  return false;
257280297Sjkim}
258280297Sjkim
259280297Sjkim/// ParseDirectiveSymbolAttribute
260280297Sjkim///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
261280297Sjkimbool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
262280297Sjkim  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
263280297Sjkim    .Case(".weak", MCSA_Weak)
264280297Sjkim    .Default(MCSA_Invalid);
265280297Sjkim  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
266280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
267280297Sjkim    for (;;) {
268280297Sjkim      StringRef Name;
269280297Sjkim
270280297Sjkim      if (getParser().parseIdentifier(Name))
271280297Sjkim        return TokError("expected identifier in directive");
272280297Sjkim
273280297Sjkim      MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
274280297Sjkim
275280297Sjkim      getStreamer().EmitSymbolAttribute(Sym, Attr);
276280297Sjkim
277280297Sjkim      if (getLexer().is(AsmToken::EndOfStatement))
278280297Sjkim        break;
279280297Sjkim
280280297Sjkim      if (getLexer().isNot(AsmToken::Comma))
281280297Sjkim        return TokError("unexpected token in directive");
282280297Sjkim      Lex();
283280297Sjkim    }
284280297Sjkim  }
285280297Sjkim
286280297Sjkim  Lex();
287280297Sjkim  return false;
288280297Sjkim}
289280297Sjkim
290280297Sjkimbool COFFAsmParser::ParseSectionSwitch(StringRef Section,
291280297Sjkim                                       unsigned Characteristics,
292280297Sjkim                                       SectionKind Kind) {
29355714Skris  return ParseSectionSwitch(Section, Characteristics, Kind, "",
294280297Sjkim                            COFF::IMAGE_COMDAT_SELECT_ANY, 0);
29555714Skris}
296280297Sjkim
297280297Sjkimbool COFFAsmParser::ParseSectionSwitch(StringRef Section,
298280297Sjkim                                       unsigned Characteristics,
299280297Sjkim                                       SectionKind Kind,
300280297Sjkim                                       StringRef COMDATSymName,
301280297Sjkim                                       COFF::COMDATType Type,
302280297Sjkim                                       const MCSectionCOFF *Assoc) {
303280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement))
304280297Sjkim    return TokError("unexpected token in section switching directive");
305280297Sjkim  Lex();
306280297Sjkim
307280297Sjkim  getStreamer().SwitchSection(getContext().getCOFFSection(
308280297Sjkim      Section, Characteristics, Kind, COMDATSymName, Type, Assoc));
309280297Sjkim
310280297Sjkim  return false;
311280297Sjkim}
312280297Sjkim
313280297Sjkimbool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
314280297Sjkim  if (!getLexer().is(AsmToken::Identifier))
315280297Sjkim    return true;
316280297Sjkim
317280297Sjkim  SectionName = getTok().getIdentifier();
318280297Sjkim  Lex();
319280297Sjkim  return false;
320280297Sjkim}
321280297Sjkim
322280297Sjkim// .section name [, "flags"] [, identifier [ identifier ], identifier]
323280297Sjkim//
324280297Sjkim// Supported flags:
325280297Sjkim//   a: Ignored.
326280297Sjkim//   b: BSS section (uninitialized data)
327280297Sjkim//   d: data section (initialized data)
328280297Sjkim//   n: Discardable section
329280297Sjkim//   r: Readable section
330280297Sjkim//   s: Shared section
331280297Sjkim//   w: Writable section
332280297Sjkim//   x: Executable section
333280297Sjkim//   y: Not-readable section (clears 'r')
334280297Sjkim//
335280297Sjkim// Subsections are not supported.
336280297Sjkimbool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
337280297Sjkim  StringRef SectionName;
338280297Sjkim
339280297Sjkim  if (ParseSectionName(SectionName))
340280297Sjkim    return TokError("expected identifier in directive");
341280297Sjkim
342280297Sjkim  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
343280297Sjkim                   COFF::IMAGE_SCN_MEM_READ |
344280297Sjkim                   COFF::IMAGE_SCN_MEM_WRITE;
345280297Sjkim
346280297Sjkim  if (getLexer().is(AsmToken::Comma)) {
347280297Sjkim    Lex();
348280297Sjkim
349280297Sjkim    if (getLexer().isNot(AsmToken::String))
350280297Sjkim      return TokError("expected string in directive");
351280297Sjkim
352280297Sjkim    StringRef FlagsStr = getTok().getStringContents();
353280297Sjkim    Lex();
354280297Sjkim
35555714Skris    if (ParseSectionFlags(FlagsStr, &Flags))
356280297Sjkim      return true;
35755714Skris  }
358280297Sjkim
359280297Sjkim  COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
360280297Sjkim  const MCSectionCOFF *Assoc = 0;
361280297Sjkim  StringRef COMDATSymName;
362280297Sjkim  if (getLexer().is(AsmToken::Comma)) {
363280297Sjkim    Lex();
364280297Sjkim
365280297Sjkim    Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
366280297Sjkim
367280297Sjkim    if (parseCOMDATTypeAndAssoc(Type, Assoc))
368280297Sjkim      return true;
369280297Sjkim
370280297Sjkim    if (getLexer().isNot(AsmToken::Comma))
371280297Sjkim      return TokError("expected comma in directive");
37255714Skris    Lex();
373280297Sjkim
374280297Sjkim    if (getParser().parseIdentifier(COMDATSymName))
375280297Sjkim      return TokError("expected identifier in directive");
376280297Sjkim  }
377280297Sjkim
378280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement))
379280297Sjkim    return TokError("unexpected token in directive");
38055714Skris
381280297Sjkim  SectionKind Kind = computeSectionKind(Flags);
382280297Sjkim  ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type, Assoc);
383280297Sjkim  return false;
384280297Sjkim}
38555714Skris
386280297Sjkimbool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
387280297Sjkim  StringRef SymbolName;
388280297Sjkim
389280297Sjkim  if (getParser().parseIdentifier(SymbolName))
390280297Sjkim    return TokError("expected identifier in directive");
391280297Sjkim
392280297Sjkim  MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
393280297Sjkim
39455714Skris  getStreamer().BeginCOFFSymbolDef(Sym);
395280297Sjkim
396280297Sjkim  Lex();
397280297Sjkim  return false;
398280297Sjkim}
399280297Sjkim
400280297Sjkimbool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
401280297Sjkim  int64_t SymbolStorageClass;
402280297Sjkim  if (getParser().parseAbsoluteExpression(SymbolStorageClass))
403280297Sjkim    return true;
40455714Skris
405280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement))
406280297Sjkim    return TokError("unexpected token in directive");
407280297Sjkim
408280297Sjkim  Lex();
409280297Sjkim  getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
410280297Sjkim  return false;
411280297Sjkim}
412280297Sjkim
413280297Sjkimbool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
41455714Skris  int64_t Type;
415280297Sjkim  if (getParser().parseAbsoluteExpression(Type))
416280297Sjkim    return true;
417280297Sjkim
418280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement))
419280297Sjkim    return TokError("unexpected token in directive");
420280297Sjkim
421280297Sjkim  Lex();
422280297Sjkim  getStreamer().EmitCOFFSymbolType(Type);
423280297Sjkim  return false;
42455714Skris}
425280297Sjkim
426280297Sjkimbool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
427280297Sjkim  Lex();
428280297Sjkim  getStreamer().EndCOFFSymbolDef();
429280297Sjkim  return false;
430280297Sjkim}
431280297Sjkim
432280297Sjkimbool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
433280297Sjkim  StringRef SymbolID;
43455714Skris  if (getParser().parseIdentifier(SymbolID))
435160814Ssimon    return true;
43655714Skris
437280297Sjkim  if (getLexer().isNot(AsmToken::EndOfStatement))
438280297Sjkim    return TokError("unexpected token in directive");
439238405Sjkim
440280297Sjkim  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
441280297Sjkim
442280297Sjkim  Lex();
44355714Skris  getStreamer().EmitCOFFSecRel32(Symbol);
444  return false;
445}
446
447/// ::= [ identifier [ identifier ] ]
448bool COFFAsmParser::parseCOMDATTypeAndAssoc(COFF::COMDATType &Type,
449                                            const MCSectionCOFF *&Assoc) {
450  StringRef TypeId = getTok().getIdentifier();
451
452  Type = StringSwitch<COFF::COMDATType>(TypeId)
453    .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
454    .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
455    .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
456    .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
457    .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
458    .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
459    .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
460    .Default((COFF::COMDATType)0);
461
462  if (Type == 0)
463    return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
464
465  Lex();
466
467  if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
468    SMLoc Loc = getTok().getLoc();
469    StringRef AssocName;
470    if (ParseSectionName(AssocName))
471      return TokError("expected associated section name");
472
473    Assoc = static_cast<const MCSectionCOFF*>(
474                                        getContext().getCOFFSection(AssocName));
475    if (!Assoc)
476      return Error(Loc, "cannot associate unknown section '" + AssocName + "'");
477    if (!(Assoc->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT))
478      return Error(Loc, "associated section must be a COMDAT section");
479    if (Assoc->getSelection() == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
480      return Error(Loc, "associated section cannot be itself associative");
481  }
482
483  return false;
484}
485
486/// ParseDirectiveLinkOnce
487///  ::= .linkonce [ identifier [ identifier ] ]
488bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
489  COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
490  const MCSectionCOFF *Assoc = 0;
491  if (getLexer().is(AsmToken::Identifier))
492    if (parseCOMDATTypeAndAssoc(Type, Assoc))
493      return true;
494
495  const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
496                                       getStreamer().getCurrentSection().first);
497
498
499  if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
500    if (Assoc == Current)
501      return Error(Loc, "cannot associate a section with itself");
502  }
503
504  if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
505    return Error(Loc, Twine("section '") + Current->getSectionName() +
506                                                       "' is already linkonce");
507
508  Current->setSelection(Type, Assoc);
509
510  if (getLexer().isNot(AsmToken::EndOfStatement))
511    return TokError("unexpected token in directive");
512
513  return false;
514}
515
516bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
517  StringRef SymbolID;
518  if (getParser().parseIdentifier(SymbolID))
519    return true;
520
521  if (getLexer().isNot(AsmToken::EndOfStatement))
522    return TokError("unexpected token in directive");
523
524  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
525
526  Lex();
527  getStreamer().EmitWin64EHStartProc(Symbol);
528  return false;
529}
530
531bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
532  Lex();
533  getStreamer().EmitWin64EHEndProc();
534  return false;
535}
536
537bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
538  Lex();
539  getStreamer().EmitWin64EHStartChained();
540  return false;
541}
542
543bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
544  Lex();
545  getStreamer().EmitWin64EHEndChained();
546  return false;
547}
548
549bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
550  StringRef SymbolID;
551  if (getParser().parseIdentifier(SymbolID))
552    return true;
553
554  if (getLexer().isNot(AsmToken::Comma))
555    return TokError("you must specify one or both of @unwind or @except");
556  Lex();
557  bool unwind = false, except = false;
558  if (ParseAtUnwindOrAtExcept(unwind, except))
559    return true;
560  if (getLexer().is(AsmToken::Comma)) {
561    Lex();
562    if (ParseAtUnwindOrAtExcept(unwind, except))
563      return true;
564  }
565  if (getLexer().isNot(AsmToken::EndOfStatement))
566    return TokError("unexpected token in directive");
567
568  MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
569
570  Lex();
571  getStreamer().EmitWin64EHHandler(handler, unwind, except);
572  return false;
573}
574
575bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
576  Lex();
577  getStreamer().EmitWin64EHHandlerData();
578  return false;
579}
580
581bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
582  unsigned Reg;
583  if (ParseSEHRegisterNumber(Reg))
584    return true;
585
586  if (getLexer().isNot(AsmToken::EndOfStatement))
587    return TokError("unexpected token in directive");
588
589  Lex();
590  getStreamer().EmitWin64EHPushReg(Reg);
591  return false;
592}
593
594bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
595  unsigned Reg;
596  int64_t Off;
597  if (ParseSEHRegisterNumber(Reg))
598    return true;
599  if (getLexer().isNot(AsmToken::Comma))
600    return TokError("you must specify a stack pointer offset");
601
602  Lex();
603  SMLoc startLoc = getLexer().getLoc();
604  if (getParser().parseAbsoluteExpression(Off))
605    return true;
606
607  if (Off & 0x0F)
608    return Error(startLoc, "offset is not a multiple of 16");
609
610  if (getLexer().isNot(AsmToken::EndOfStatement))
611    return TokError("unexpected token in directive");
612
613  Lex();
614  getStreamer().EmitWin64EHSetFrame(Reg, Off);
615  return false;
616}
617
618bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
619  int64_t Size;
620  SMLoc startLoc = getLexer().getLoc();
621  if (getParser().parseAbsoluteExpression(Size))
622    return true;
623
624  if (Size & 7)
625    return Error(startLoc, "size is not a multiple of 8");
626
627  if (getLexer().isNot(AsmToken::EndOfStatement))
628    return TokError("unexpected token in directive");
629
630  Lex();
631  getStreamer().EmitWin64EHAllocStack(Size);
632  return false;
633}
634
635bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
636  unsigned Reg;
637  int64_t Off;
638  if (ParseSEHRegisterNumber(Reg))
639    return true;
640  if (getLexer().isNot(AsmToken::Comma))
641    return TokError("you must specify an offset on the stack");
642
643  Lex();
644  SMLoc startLoc = getLexer().getLoc();
645  if (getParser().parseAbsoluteExpression(Off))
646    return true;
647
648  if (Off & 7)
649    return Error(startLoc, "size is not a multiple of 8");
650
651  if (getLexer().isNot(AsmToken::EndOfStatement))
652    return TokError("unexpected token in directive");
653
654  Lex();
655  // FIXME: Err on %xmm* registers
656  getStreamer().EmitWin64EHSaveReg(Reg, Off);
657  return false;
658}
659
660// FIXME: This method is inherently x86-specific. It should really be in the
661// x86 backend.
662bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
663  unsigned Reg;
664  int64_t Off;
665  if (ParseSEHRegisterNumber(Reg))
666    return true;
667  if (getLexer().isNot(AsmToken::Comma))
668    return TokError("you must specify an offset on the stack");
669
670  Lex();
671  SMLoc startLoc = getLexer().getLoc();
672  if (getParser().parseAbsoluteExpression(Off))
673    return true;
674
675  if (getLexer().isNot(AsmToken::EndOfStatement))
676    return TokError("unexpected token in directive");
677
678  if (Off & 0x0F)
679    return Error(startLoc, "offset is not a multiple of 16");
680
681  Lex();
682  // FIXME: Err on non-%xmm* registers
683  getStreamer().EmitWin64EHSaveXMM(Reg, Off);
684  return false;
685}
686
687bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
688  bool Code = false;
689  StringRef CodeID;
690  if (getLexer().is(AsmToken::At)) {
691    SMLoc startLoc = getLexer().getLoc();
692    Lex();
693    if (!getParser().parseIdentifier(CodeID)) {
694      if (CodeID != "code")
695        return Error(startLoc, "expected @code");
696      Code = true;
697    }
698  }
699
700  if (getLexer().isNot(AsmToken::EndOfStatement))
701    return TokError("unexpected token in directive");
702
703  Lex();
704  getStreamer().EmitWin64EHPushFrame(Code);
705  return false;
706}
707
708bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
709  Lex();
710  getStreamer().EmitWin64EHEndProlog();
711  return false;
712}
713
714bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
715  StringRef identifier;
716  if (getLexer().isNot(AsmToken::At))
717    return TokError("a handler attribute must begin with '@'");
718  SMLoc startLoc = getLexer().getLoc();
719  Lex();
720  if (getParser().parseIdentifier(identifier))
721    return Error(startLoc, "expected @unwind or @except");
722  if (identifier == "unwind")
723    unwind = true;
724  else if (identifier == "except")
725    except = true;
726  else
727    return Error(startLoc, "expected @unwind or @except");
728  return false;
729}
730
731bool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
732  SMLoc startLoc = getLexer().getLoc();
733  if (getLexer().is(AsmToken::Percent)) {
734    const MCRegisterInfo *MRI = getContext().getRegisterInfo();
735    SMLoc endLoc;
736    unsigned LLVMRegNo;
737    if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
738      return true;
739
740#if 0
741    // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
742    // violation so this validation code is disabled.
743
744    // Check that this is a non-volatile register.
745    const unsigned *NVRegs = TAI.getCalleeSavedRegs();
746    unsigned i;
747    for (i = 0; NVRegs[i] != 0; ++i)
748      if (NVRegs[i] == LLVMRegNo)
749        break;
750    if (NVRegs[i] == 0)
751      return Error(startLoc, "expected non-volatile register");
752#endif
753
754    int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
755    if (SEHRegNo < 0)
756      return Error(startLoc,"register can't be represented in SEH unwind info");
757    RegNo = SEHRegNo;
758  }
759  else {
760    int64_t n;
761    if (getParser().parseAbsoluteExpression(n))
762      return true;
763    if (n > 15)
764      return Error(startLoc, "register number is too high");
765    RegNo = n;
766  }
767
768  return false;
769}
770
771namespace llvm {
772
773MCAsmParserExtension *createCOFFAsmParser() {
774  return new COFFAsmParser;
775}
776
777}
778