17d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
27d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//
37d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//                     The LLVM Compiler Infrastructure
47d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//
57d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer// This file is distributed under the University of Illinois Open Source
67d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer// License. See LICENSE.TXT for details.
77d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//
87d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer//===----------------------------------------------------------------------===//
97d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
107d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCParser/MCAsmParserExtension.h"
11f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach#include "llvm/ADT/StringSwitch.h"
127d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/ADT/Twine.h"
137d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCAsmInfo.h"
147d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCContext.h"
15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/MC/MCExpr.h"
16cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/MC/MCObjectFileInfo.h"
177d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCParser/MCAsmLexer.h"
180e6a052331f674dd70e28af41f654a7874405eabEvan Cheng#include "llvm/MC/MCRegisterInfo.h"
197d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCSectionCOFF.h"
207d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/MC/MCStreamer.h"
2194b9550a32d189704a8eae55505edf62662c0534Evan Cheng#include "llvm/MC/MCTargetAsmParser.h"
227d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer#include "llvm/Support/COFF.h"
237d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerusing namespace llvm;
247d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
257d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencernamespace {
267d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
277d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerclass COFFAsmParser : public MCAsmParserExtension {
28171192f149dce679cd520f85ffced4789448b017Eli Bendersky  template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
29cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  void addDirectiveHandler(StringRef Directive) {
30171192f149dce679cd520f85ffced4789448b017Eli Bendersky    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
31171192f149dce679cd520f85ffced4789448b017Eli Bendersky        this, HandleDirective<COFFAsmParser, HandlerMethod>);
32cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    getParser().addDirectiveHandler(Directive, Handler);
337d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  }
347d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
357d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseSectionSwitch(StringRef Section,
367d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                          unsigned Characteristics,
377d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                          SectionKind Kind);
387d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
390ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
400ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling                          SectionKind Kind, StringRef COMDATSymName,
41cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                          COFF::COMDATType Type);
420ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
43a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  bool ParseSectionName(StringRef &SectionName);
44a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  bool ParseSectionFlags(StringRef FlagsString, unsigned* Flags);
45a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
4636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  void Initialize(MCAsmParser &Parser) override {
477d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    // Call the base implementation.
487d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    MCAsmParserExtension::Initialize(Parser);
497d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
50cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
51cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
52cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
53a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
54cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
55cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
56cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
57cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
58cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
6080646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck    addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
61fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
62fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    // Win64 EH directives.
63cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
64fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                   ".seh_proc");
65cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
66fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                ".seh_endproc");
67cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
68fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                           ".seh_startchained");
69cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
70fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                             ".seh_endchained");
71cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
72fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                ".seh_handler");
73cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
74fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                            ".seh_handlerdata");
75cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushReg>(
76fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                ".seh_pushreg");
77cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSetFrame>(
78fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                               ".seh_setframe");
79cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
80fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                             ".seh_stackalloc");
81cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveReg>(
82fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                ".seh_savereg");
83cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveSaveXMM>(
84fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                                ".seh_savexmm");
85cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectivePushFrame>(
86fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                              ".seh_pushframe");
87cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
88fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis                                                            ".seh_endprologue");
89cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
907d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  }
917d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
927d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseSectionDirectiveText(StringRef, SMLoc) {
937d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return ParseSectionSwitch(".text",
947d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              COFF::IMAGE_SCN_CNT_CODE
957d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_EXECUTE
967d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_READ,
977d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              SectionKind::getText());
987d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  }
997d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseSectionDirectiveData(StringRef, SMLoc) {
1007d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return ParseSectionSwitch(".data",
1017d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
1027d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_READ
1037d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_WRITE,
1047d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              SectionKind::getDataRel());
1057d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  }
1067d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
1077d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return ParseSectionSwitch(".bss",
1087d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
1097d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_READ
1107d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                            | COFF::IMAGE_SCN_MEM_WRITE,
1117d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                              SectionKind::getBSS());
1127d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  }
1137d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
114a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  bool ParseDirectiveSection(StringRef, SMLoc);
1157d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseDirectiveDef(StringRef, SMLoc);
1167d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseDirectiveScl(StringRef, SMLoc);
1177d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseDirectiveType(StringRef, SMLoc);
1187d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  bool ParseDirectiveEndef(StringRef, SMLoc);
1198f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  bool ParseDirectiveSecRel32(StringRef, SMLoc);
12036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  bool ParseDirectiveSecIdx(StringRef, SMLoc);
121cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  bool parseCOMDATType(COFF::COMDATType &Type);
12280646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck  bool ParseDirectiveLinkOnce(StringRef, SMLoc);
1237d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
124fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  // Win64 EH directives.
125fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
126fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
127fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
128fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
129fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveHandler(StringRef, SMLoc);
130fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
1313b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectivePushReg(StringRef, SMLoc);
1323b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectiveSetFrame(StringRef, SMLoc);
1333b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
1343b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectiveSaveReg(StringRef, SMLoc);
1353b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectiveSaveXMM(StringRef, SMLoc);
1363b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHDirectivePushFrame(StringRef, SMLoc);
137fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
138fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
139fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
1403b32d0240c820a8aa829a950628586512a406ea0Charles Davis  bool ParseSEHRegisterNumber(unsigned &RegNo);
141f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
1427d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerpublic:
1437d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  COFFAsmParser() {}
1447d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer};
1457d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
1467d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer} // end annonomous namespace.
1477d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
148a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieckstatic SectionKind computeSectionKind(unsigned Flags) {
149a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
150a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    return SectionKind::getText();
151a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
152a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
153a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    return SectionKind::getReadOnly();
154a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  return SectionKind::getDataRel();
155a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck}
156a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
157a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieckbool COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
158a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  enum {
159a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    None      = 0,
160a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Alloc     = 1 << 0,
161a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Code      = 1 << 1,
162a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Load      = 1 << 2,
163a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    InitData  = 1 << 3,
164a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Shared    = 1 << 4,
165a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    NoLoad    = 1 << 5,
166a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    NoRead    = 1 << 6,
167a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    NoWrite  =  1 << 7
168a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  };
169a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
170a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  bool ReadOnlyRemoved = false;
171a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  unsigned SecFlags = None;
172a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
173cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  for (char FlagChar : FlagsString) {
174cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    switch (FlagChar) {
175a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'a':
176a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      // Ignored.
177a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
178a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
179a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'b': // bss section
180a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= Alloc;
181a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if (SecFlags & InitData)
182a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        return TokError("conflicting section flags 'b' and 'd'.");
183a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags &= ~Load;
184a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
185a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
186a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'd': // data section
187a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= InitData;
188a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if (SecFlags & Alloc)
189a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        return TokError("conflicting section flags 'b' and 'd'.");
190a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags &= ~NoWrite;
191a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if ((SecFlags & NoLoad) == 0)
192a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= Load;
193a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
194a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
195a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'n': // section is not loaded
196a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= NoLoad;
197a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags &= ~Load;
198a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
199a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
200a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'r': // read-only
201a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      ReadOnlyRemoved = false;
202a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= NoWrite;
203a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if ((SecFlags & Code) == 0)
204a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= InitData;
205a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if ((SecFlags & NoLoad) == 0)
206a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= Load;
207a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
208a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
209a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 's': // shared section
210a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= Shared | InitData;
211a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags &= ~NoWrite;
212a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if ((SecFlags & NoLoad) == 0)
213a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= Load;
214a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
215a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
216a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'w': // writable
217a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags &= ~NoWrite;
218a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      ReadOnlyRemoved = true;
219a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
220a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
221a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'x': // executable section
222a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= Code;
223a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if ((SecFlags & NoLoad) == 0)
224a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= Load;
225a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      if (!ReadOnlyRemoved)
226a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck        SecFlags |= NoWrite;
227a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
228a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
229a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    case 'y': // not readable
230a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      SecFlags |= NoRead | NoWrite;
231a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      break;
232a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
233a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    default:
234a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      return TokError("unknown flag");
235a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    }
236a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  }
237a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
238a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  *Flags = 0;
239a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
240a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (SecFlags == None)
241a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    SecFlags = InitData;
242a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
243a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (SecFlags & Code)
244a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
245a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (SecFlags & InitData)
246a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
247a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
248a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
249a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (SecFlags & NoLoad)
250a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
251a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if ((SecFlags & NoRead) == 0)
252a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_MEM_READ;
253a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if ((SecFlags & NoWrite) == 0)
254a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
255a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (SecFlags & Shared)
256a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
257a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
258a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  return false;
259a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck}
260a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
261f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach/// ParseDirectiveSymbolAttribute
262f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
263f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbachbool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
264f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
265f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach    .Case(".weak", MCSA_Weak)
266f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach    .Default(MCSA_Invalid);
267f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
268f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  if (getLexer().isNot(AsmToken::EndOfStatement)) {
269f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach    for (;;) {
270f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      StringRef Name;
271f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
272cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach      if (getParser().parseIdentifier(Name))
273f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach        return TokError("expected identifier in directive");
274f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
275f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
276f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
277f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      getStreamer().EmitSymbolAttribute(Sym, Attr);
278f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
279f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      if (getLexer().is(AsmToken::EndOfStatement))
280f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach        break;
281f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
282f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      if (getLexer().isNot(AsmToken::Comma))
283f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach        return TokError("unexpected token in directive");
284f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach      Lex();
285f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach    }
286f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  }
287f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
288f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  Lex();
289f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach  return false;
290f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach}
291f2a35fbd60fbb86465ad2fb4d801cd5c240decd7Jim Grosbach
2927d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerbool COFFAsmParser::ParseSectionSwitch(StringRef Section,
2937d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                                       unsigned Characteristics,
2947d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer                                       SectionKind Kind) {
295cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
2960ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling}
2970ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
2980ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendlingbool COFFAsmParser::ParseSectionSwitch(StringRef Section,
2990ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling                                       unsigned Characteristics,
3000ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling                                       SectionKind Kind,
3010ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling                                       StringRef COMDATSymName,
302cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                       COFF::COMDATType Type) {
3037d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  if (getLexer().isNot(AsmToken::EndOfStatement))
3047d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return TokError("unexpected token in section switching directive");
3057d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  Lex();
3067d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
3077d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  getStreamer().SwitchSection(getContext().getCOFFSection(
308cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Section, Characteristics, Kind, COMDATSymName, Type));
3097d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
3107d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return false;
3117d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
3127d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
313a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieckbool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
314ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg  if (!getLexer().is(AsmToken::Identifier))
315ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg    return true;
316ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg
317ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg  SectionName = getTok().getIdentifier();
318ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg  Lex();
319ab887bf52c99c2c9a4346b6dea2b8118e18a4282Hans Wennborg  return false;
320a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck}
321a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
3220ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling// .section name [, "flags"] [, identifier [ identifier ], identifier]
323a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//
324a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck// Supported flags:
325a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   a: Ignored.
326a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   b: BSS section (uninitialized data)
327a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   d: data section (initialized data)
328a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   n: Discardable section
329a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   r: Readable section
330a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   s: Shared section
331a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   w: Writable section
332a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   x: Executable section
333a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//   y: Not-readable section (clears 'r')
334a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck//
335a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck// Subsections are not supported.
336a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieckbool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
337a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  StringRef SectionName;
338a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
339a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (ParseSectionName(SectionName))
340a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    return TokError("expected identifier in directive");
341a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
342a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
343a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck                   COFF::IMAGE_SCN_MEM_READ |
344a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck                   COFF::IMAGE_SCN_MEM_WRITE;
345a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
346a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (getLexer().is(AsmToken::Comma)) {
347a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Lex();
348a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
349a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    if (getLexer().isNot(AsmToken::String))
350a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      return TokError("expected string in directive");
351a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
352a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    StringRef FlagsStr = getTok().getStringContents();
353a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    Lex();
354a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
355a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    if (ParseSectionFlags(FlagsStr, &Flags))
356a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck      return true;
357a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  }
358a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
359cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  COFF::COMDATType Type = (COFF::COMDATType)0;
3600ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  StringRef COMDATSymName;
3610ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  if (getLexer().is(AsmToken::Comma)) {
362cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    Type = COFF::IMAGE_COMDAT_SELECT_ANY;;
3630ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    Lex();
3640ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
3650ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
3660ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
367cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (parseCOMDATType(Type))
3680ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling      return true;
3690ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
3700ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    if (getLexer().isNot(AsmToken::Comma))
3710ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling      return TokError("expected comma in directive");
3720ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    Lex();
3730ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
3740ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    if (getParser().parseIdentifier(COMDATSymName))
3750ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling      return TokError("expected identifier in directive");
3760ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  }
3770ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
378a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  if (getLexer().isNot(AsmToken::EndOfStatement))
379a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck    return TokError("unexpected token in directive");
380a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
381a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  SectionKind Kind = computeSectionKind(Flags);
382cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Kind.isText()) {
383cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
384cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
385cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines      Flags |= COFF::IMAGE_SCN_MEM_16BIT;
386cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  }
387cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
388a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck  return false;
389a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck}
390a6d343a688073664b3a80aa117e0d3cbecf28014Nico Rieck
3917d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerbool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
3927d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  StringRef SymbolName;
3937d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
394cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseIdentifier(SymbolName))
3957d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return TokError("expected identifier in directive");
3967d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
3977d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3987d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
3997d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  getStreamer().BeginCOFFSymbolDef(Sym);
4007d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4017d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  Lex();
4027d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return false;
4037d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
4047d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4057d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerbool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
4067d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  int64_t SymbolStorageClass;
407cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(SymbolStorageClass))
4087d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return true;
4097d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4107d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  if (getLexer().isNot(AsmToken::EndOfStatement))
4117d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return TokError("unexpected token in directive");
4127d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4137d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  Lex();
4147d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
4157d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return false;
4167d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
4177d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4187d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerbool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
4197d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  int64_t Type;
420cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(Type))
4217d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return true;
4227d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4237d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  if (getLexer().isNot(AsmToken::EndOfStatement))
4247d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer    return TokError("unexpected token in directive");
4257d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4267d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  Lex();
4277d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  getStreamer().EmitCOFFSymbolType(Type);
4287d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return false;
4297d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
4307d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4317d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencerbool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
4327d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  Lex();
4337d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  getStreamer().EndCOFFSymbolDef();
4347d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return false;
4357d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
4367d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
4378f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindolabool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
4388f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  StringRef SymbolID;
439cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseIdentifier(SymbolID))
44036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return TokError("expected identifier in directive");
4418f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola
4428f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  if (getLexer().isNot(AsmToken::EndOfStatement))
4438f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola    return TokError("unexpected token in directive");
4448f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola
4458f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
4468f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola
4478f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  Lex();
4488f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  getStreamer().EmitCOFFSecRel32(Symbol);
4498f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola  return false;
4508f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola}
4518f7d12ccfd8feb258bdf4e582592bc00beacc7c6Rafael Espindola
45236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
45336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  StringRef SymbolID;
45436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (getParser().parseIdentifier(SymbolID))
45536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return TokError("expected identifier in directive");
45636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
45736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  if (getLexer().isNot(AsmToken::EndOfStatement))
45836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return TokError("unexpected token in directive");
45936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
46036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
46136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
46236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  Lex();
46336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  getStreamer().EmitCOFFSectionIndex(Symbol);
46436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return false;
46536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
46636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
467cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines/// ::= [ identifier ]
468cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesbool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
4690ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  StringRef TypeId = getTok().getIdentifier();
47080646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
4710ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  Type = StringSwitch<COFF::COMDATType>(TypeId)
4720ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
4730ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
4740ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
4750ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
4760ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
4770ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
4780ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
4790ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    .Default((COFF::COMDATType)0);
48080646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
4810ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  if (Type == 0)
4820ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling    return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
48380646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
4840ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  Lex();
48580646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
4860ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  return false;
4870ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling}
4880ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
4890ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling/// ParseDirectiveLinkOnce
490cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines///  ::= .linkonce [ identifier ]
4910ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendlingbool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
4920ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
4930ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  if (getLexer().is(AsmToken::Identifier))
494cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (parseCOMDATType(Type))
4950ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling      return true;
4960ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
4970ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling  const MCSectionCOFF *Current = static_cast<const MCSectionCOFF*>(
4980ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling                                       getStreamer().getCurrentSection().first);
4990ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
500cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
501cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return Error(Loc, "cannot make section associative with .linkonce");
5020ae07098f7d2ad5a1868d448d0b1b4eef2a3b091Bill Wendling
50380646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck  if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
50480646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck    return Error(Loc, Twine("section '") + Current->getSectionName() +
50580646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck                                                       "' is already linkonce");
50680646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
507cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  Current->setSelection(Type);
50880646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
50980646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck  if (getLexer().isNot(AsmToken::EndOfStatement))
51080646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck    return TokError("unexpected token in directive");
51180646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
51280646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck  return false;
51380646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck}
51480646283796b20c6a1b7d8eb69ce6f0478d54383Nico Rieck
515fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) {
516309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  StringRef SymbolID;
517cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseIdentifier(SymbolID))
518fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return true;
519fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
520fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
521fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return TokError("unexpected token in directive");
522fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
523309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID);
524309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis
525fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
526cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIStartProc(Symbol);
527fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
528fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
529fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
530fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) {
531fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
532cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIEndProc();
533fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
534fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
535fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
536fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) {
537fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
538cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIStartChained();
539fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
540fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
541fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
542fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) {
543fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
544cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIEndChained();
545fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
546fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
547fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
548fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) {
549309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  StringRef SymbolID;
550cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseIdentifier(SymbolID))
551fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return true;
552fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
553309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  if (getLexer().isNot(AsmToken::Comma))
554309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis    return TokError("you must specify one or both of @unwind or @except");
555309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  Lex();
556fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  bool unwind = false, except = false;
557309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  if (ParseAtUnwindOrAtExcept(unwind, except))
558309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis    return true;
559fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  if (getLexer().is(AsmToken::Comma)) {
560fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    Lex();
561309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis    if (ParseAtUnwindOrAtExcept(unwind, except))
562fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis      return true;
563fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  }
564fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
565fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return TokError("unexpected token in directive");
566fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
567309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  MCSymbol *handler = getContext().GetOrCreateSymbol(SymbolID);
568309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis
569fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
570cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinEHHandler(handler, unwind, except);
571fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
572fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
573fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
574fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) {
575fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
576cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinEHHandlerData();
577fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
578fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
579fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
580fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) {
5813b32d0240c820a8aa829a950628586512a406ea0Charles Davis  unsigned Reg;
5823b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (ParseSEHRegisterNumber(Reg))
5833b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
5843b32d0240c820a8aa829a950628586512a406ea0Charles Davis
5853b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
5863b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return TokError("unexpected token in directive");
5873b32d0240c820a8aa829a950628586512a406ea0Charles Davis
5883b32d0240c820a8aa829a950628586512a406ea0Charles Davis  Lex();
589cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIPushReg(Reg);
5903b32d0240c820a8aa829a950628586512a406ea0Charles Davis  return false;
591fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
592fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
593fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) {
5943b32d0240c820a8aa829a950628586512a406ea0Charles Davis  unsigned Reg;
5953b32d0240c820a8aa829a950628586512a406ea0Charles Davis  int64_t Off;
5963b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (ParseSEHRegisterNumber(Reg))
5973b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
598410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis  if (getLexer().isNot(AsmToken::Comma))
599410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis    return TokError("you must specify a stack pointer offset");
600410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis
601410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis  Lex();
6023b32d0240c820a8aa829a950628586512a406ea0Charles Davis  SMLoc startLoc = getLexer().getLoc();
603cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(Off))
6043b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
6053b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6063b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (Off & 0x0F)
6073b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return Error(startLoc, "offset is not a multiple of 16");
6083b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6093b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
6103b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return TokError("unexpected token in directive");
6113b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6123b32d0240c820a8aa829a950628586512a406ea0Charles Davis  Lex();
613cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFISetFrame(Reg, Off);
6143b32d0240c820a8aa829a950628586512a406ea0Charles Davis  return false;
615fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
616fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
61716e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davisbool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) {
61816e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  int64_t Size;
6193b32d0240c820a8aa829a950628586512a406ea0Charles Davis  SMLoc startLoc = getLexer().getLoc();
620cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(Size))
62116e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis    return true;
62216e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis
6233b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (Size & 7)
6243b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return Error(startLoc, "size is not a multiple of 8");
6253b32d0240c820a8aa829a950628586512a406ea0Charles Davis
62616e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
62716e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis    return TokError("unexpected token in directive");
62816e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis
62916e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  Lex();
630cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIAllocStack(Size);
63116e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  return false;
632fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
633fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
634fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) {
6353b32d0240c820a8aa829a950628586512a406ea0Charles Davis  unsigned Reg;
6363b32d0240c820a8aa829a950628586512a406ea0Charles Davis  int64_t Off;
6373b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (ParseSEHRegisterNumber(Reg))
6383b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
639575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  if (getLexer().isNot(AsmToken::Comma))
640410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis    return TokError("you must specify an offset on the stack");
641575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis
642575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  Lex();
6433b32d0240c820a8aa829a950628586512a406ea0Charles Davis  SMLoc startLoc = getLexer().getLoc();
644cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(Off))
6453b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
6463b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6473b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (Off & 7)
6483b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return Error(startLoc, "size is not a multiple of 8");
6493b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6503b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
6513b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return TokError("unexpected token in directive");
6523b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6533b32d0240c820a8aa829a950628586512a406ea0Charles Davis  Lex();
6543b32d0240c820a8aa829a950628586512a406ea0Charles Davis  // FIXME: Err on %xmm* registers
655cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFISaveReg(Reg, Off);
6563b32d0240c820a8aa829a950628586512a406ea0Charles Davis  return false;
657fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
658fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
6593b32d0240c820a8aa829a950628586512a406ea0Charles Davis// FIXME: This method is inherently x86-specific. It should really be in the
6603b32d0240c820a8aa829a950628586512a406ea0Charles Davis// x86 backend.
661fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) {
6623b32d0240c820a8aa829a950628586512a406ea0Charles Davis  unsigned Reg;
6633b32d0240c820a8aa829a950628586512a406ea0Charles Davis  int64_t Off;
6643b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (ParseSEHRegisterNumber(Reg))
6653b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
666575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  if (getLexer().isNot(AsmToken::Comma))
667410ef2b263e92d3de1b2acff7437059400daed7dCharles Davis    return TokError("you must specify an offset on the stack");
668575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis
669575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  Lex();
6703b32d0240c820a8aa829a950628586512a406ea0Charles Davis  SMLoc startLoc = getLexer().getLoc();
671cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseAbsoluteExpression(Off))
6723b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return true;
6733b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6743b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
6753b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return TokError("unexpected token in directive");
6763b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6773b32d0240c820a8aa829a950628586512a406ea0Charles Davis  if (Off & 0x0F)
6783b32d0240c820a8aa829a950628586512a406ea0Charles Davis    return Error(startLoc, "offset is not a multiple of 16");
6793b32d0240c820a8aa829a950628586512a406ea0Charles Davis
6803b32d0240c820a8aa829a950628586512a406ea0Charles Davis  Lex();
6813b32d0240c820a8aa829a950628586512a406ea0Charles Davis  // FIXME: Err on non-%xmm* registers
682cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFISaveXMM(Reg, Off);
6833b32d0240c820a8aa829a950628586512a406ea0Charles Davis  return false;
684fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
685fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
68616e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davisbool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) {
68747268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis  bool Code = false;
68816e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  StringRef CodeID;
68947268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis  if (getLexer().is(AsmToken::At)) {
69047268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis    SMLoc startLoc = getLexer().getLoc();
69147268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis    Lex();
692cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    if (!getParser().parseIdentifier(CodeID)) {
69347268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis      if (CodeID != "code")
69447268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis        return Error(startLoc, "expected @code");
69547268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis      Code = true;
69647268164f3d660f6357cc3a59d510efe3bc9152fCharles Davis    }
69716e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  }
69816e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis
69916e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  if (getLexer().isNot(AsmToken::EndOfStatement))
70016e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis    return TokError("unexpected token in directive");
70116e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis
70216e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  Lex();
703cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIPushFrame(Code);
70416e1b3fcf6f389a6354b5e744730f25bfc0c04c2Charles Davis  return false;
705fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
706fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
707fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) {
708fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  Lex();
709cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines  getStreamer().EmitWinCFIEndProlog();
710fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
711fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
712fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
713fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davisbool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
714fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  StringRef identifier;
715309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  if (getLexer().isNot(AsmToken::At))
716309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis    return TokError("a handler attribute must begin with '@'");
717fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  SMLoc startLoc = getLexer().getLoc();
718309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  Lex();
719cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach  if (getParser().parseIdentifier(identifier))
720fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return Error(startLoc, "expected @unwind or @except");
721309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  if (identifier == "unwind")
722fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    unwind = true;
723309213279e5d95826d97b2ab2178db5ddea0ed80Charles Davis  else if (identifier == "except")
724fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    except = true;
725fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  else
726fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis    return Error(startLoc, "expected @unwind or @except");
727fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis  return false;
728fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis}
729fbc539ff37ddd08c2480be9185e7a40919ce8940Charles Davis
7303b32d0240c820a8aa829a950628586512a406ea0Charles Davisbool COFFAsmParser::ParseSEHRegisterNumber(unsigned &RegNo) {
7313b32d0240c820a8aa829a950628586512a406ea0Charles Davis  SMLoc startLoc = getLexer().getLoc();
732575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  if (getLexer().is(AsmToken::Percent)) {
73399cb622041a0839c7dfcf0263c5102a305a0fdb5Bill Wendling    const MCRegisterInfo *MRI = getContext().getRegisterInfo();
7343b32d0240c820a8aa829a950628586512a406ea0Charles Davis    SMLoc endLoc;
7353b32d0240c820a8aa829a950628586512a406ea0Charles Davis    unsigned LLVMRegNo;
7363b32d0240c820a8aa829a950628586512a406ea0Charles Davis    if (getParser().getTargetParser().ParseRegister(LLVMRegNo,startLoc,endLoc))
737575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis      return true;
7383b32d0240c820a8aa829a950628586512a406ea0Charles Davis
7390e6a052331f674dd70e28af41f654a7874405eabEvan Cheng#if 0
7400e6a052331f674dd70e28af41f654a7874405eabEvan Cheng    // FIXME: TargetAsmInfo::getCalleeSavedRegs() commits a serious layering
7410e6a052331f674dd70e28af41f654a7874405eabEvan Cheng    // violation so this validation code is disabled.
7420e6a052331f674dd70e28af41f654a7874405eabEvan Cheng
7433b32d0240c820a8aa829a950628586512a406ea0Charles Davis    // Check that this is a non-volatile register.
7441be0e271a07925b928ba89848934f1ea6f1854e2Evan Cheng    const unsigned *NVRegs = TAI.getCalleeSavedRegs();
7453b32d0240c820a8aa829a950628586512a406ea0Charles Davis    unsigned i;
7463b32d0240c820a8aa829a950628586512a406ea0Charles Davis    for (i = 0; NVRegs[i] != 0; ++i)
7473b32d0240c820a8aa829a950628586512a406ea0Charles Davis      if (NVRegs[i] == LLVMRegNo)
7483b32d0240c820a8aa829a950628586512a406ea0Charles Davis        break;
7493b32d0240c820a8aa829a950628586512a406ea0Charles Davis    if (NVRegs[i] == 0)
7503b32d0240c820a8aa829a950628586512a406ea0Charles Davis      return Error(startLoc, "expected non-volatile register");
7510e6a052331f674dd70e28af41f654a7874405eabEvan Cheng#endif
7523b32d0240c820a8aa829a950628586512a406ea0Charles Davis
75399cb622041a0839c7dfcf0263c5102a305a0fdb5Bill Wendling    int SEHRegNo = MRI->getSEHRegNum(LLVMRegNo);
7543b32d0240c820a8aa829a950628586512a406ea0Charles Davis    if (SEHRegNo < 0)
7553b32d0240c820a8aa829a950628586512a406ea0Charles Davis      return Error(startLoc,"register can't be represented in SEH unwind info");
7563b32d0240c820a8aa829a950628586512a406ea0Charles Davis    RegNo = SEHRegNo;
7573b32d0240c820a8aa829a950628586512a406ea0Charles Davis  }
758575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  else {
759575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis    int64_t n;
760cb2ae3d98e3bb36e5813f8f69b00d39efd026dcdJim Grosbach    if (getParser().parseAbsoluteExpression(n))
761575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis      return true;
762575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis    if (n > 15)
763575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis      return Error(startLoc, "register number is too high");
7643b32d0240c820a8aa829a950628586512a406ea0Charles Davis    RegNo = n;
765575630ccb8a267405146a0c14fba7a5b74e1e4c3Charles Davis  }
7663b32d0240c820a8aa829a950628586512a406ea0Charles Davis
7673b32d0240c820a8aa829a950628586512a406ea0Charles Davis  return false;
7683b32d0240c820a8aa829a950628586512a406ea0Charles Davis}
7693b32d0240c820a8aa829a950628586512a406ea0Charles Davis
7707d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencernamespace llvm {
7717d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
7727d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. SpencerMCAsmParserExtension *createCOFFAsmParser() {
7737d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer  return new COFFAsmParser;
7747d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
7757d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer
7767d4900416af3813aa9473e6ec2f0497ad5d208ddMichael J. Spencer}
777