forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			713 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			713 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- COFFAsmParser.cpp - COFF Assembly Parser ---------------------------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/ADT/StringSwitch.h"
 | 
						|
#include "llvm/ADT/Triple.h"
 | 
						|
#include "llvm/ADT/Twine.h"
 | 
						|
#include "llvm/BinaryFormat/COFF.h"
 | 
						|
#include "llvm/MC/MCContext.h"
 | 
						|
#include "llvm/MC/MCDirectives.h"
 | 
						|
#include "llvm/MC/MCObjectFileInfo.h"
 | 
						|
#include "llvm/MC/MCParser/MCAsmLexer.h"
 | 
						|
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
 | 
						|
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
 | 
						|
#include "llvm/MC/MCRegisterInfo.h"
 | 
						|
#include "llvm/MC/MCSectionCOFF.h"
 | 
						|
#include "llvm/MC/MCStreamer.h"
 | 
						|
#include "llvm/MC/SectionKind.h"
 | 
						|
#include "llvm/Support/SMLoc.h"
 | 
						|
#include <cassert>
 | 
						|
#include <cstdint>
 | 
						|
#include <limits>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
class COFFAsmParser : public MCAsmParserExtension {
 | 
						|
  template<bool (COFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
 | 
						|
  void addDirectiveHandler(StringRef Directive) {
 | 
						|
    MCAsmParser::ExtensionDirectiveHandler Handler = std::make_pair(
 | 
						|
        this, HandleDirective<COFFAsmParser, HandlerMethod>);
 | 
						|
    getParser().addDirectiveHandler(Directive, Handler);
 | 
						|
  }
 | 
						|
 | 
						|
  bool ParseSectionSwitch(StringRef Section,
 | 
						|
                          unsigned Characteristics,
 | 
						|
                          SectionKind Kind);
 | 
						|
 | 
						|
  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
 | 
						|
                          SectionKind Kind, StringRef COMDATSymName,
 | 
						|
                          COFF::COMDATType Type);
 | 
						|
 | 
						|
  bool ParseSectionName(StringRef &SectionName);
 | 
						|
  bool ParseSectionFlags(StringRef SectionName, StringRef FlagsString,
 | 
						|
                         unsigned *Flags);
 | 
						|
 | 
						|
  void Initialize(MCAsmParser &Parser) override {
 | 
						|
    // Call the base implementation.
 | 
						|
    MCAsmParserExtension::Initialize(Parser);
 | 
						|
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveText>(".text");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveData>(".data");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSectionDirectiveBSS>(".bss");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSection>(".section");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveDef>(".def");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymIdx>(".symidx");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSafeSEH>(".safeseh");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSecIdx>(".secidx");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
 | 
						|
 | 
						|
    // Win64 EH directives.
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
 | 
						|
                                                                   ".seh_proc");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProc>(
 | 
						|
                                                                ".seh_endproc");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartChained>(
 | 
						|
                                                           ".seh_startchained");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndChained>(
 | 
						|
                                                             ".seh_endchained");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandler>(
 | 
						|
                                                                ".seh_handler");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveHandlerData>(
 | 
						|
                                                            ".seh_handlerdata");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveAllocStack>(
 | 
						|
                                                             ".seh_stackalloc");
 | 
						|
    addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
 | 
						|
                                                            ".seh_endprologue");
 | 
						|
  }
 | 
						|
 | 
						|
  bool ParseSectionDirectiveText(StringRef, SMLoc) {
 | 
						|
    return ParseSectionSwitch(".text",
 | 
						|
                              COFF::IMAGE_SCN_CNT_CODE
 | 
						|
                            | COFF::IMAGE_SCN_MEM_EXECUTE
 | 
						|
                            | COFF::IMAGE_SCN_MEM_READ,
 | 
						|
                              SectionKind::getText());
 | 
						|
  }
 | 
						|
 | 
						|
  bool ParseSectionDirectiveData(StringRef, SMLoc) {
 | 
						|
    return ParseSectionSwitch(".data", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
 | 
						|
                                           COFF::IMAGE_SCN_MEM_READ |
 | 
						|
                                           COFF::IMAGE_SCN_MEM_WRITE,
 | 
						|
                              SectionKind::getData());
 | 
						|
  }
 | 
						|
 | 
						|
  bool ParseSectionDirectiveBSS(StringRef, SMLoc) {
 | 
						|
    return ParseSectionSwitch(".bss",
 | 
						|
                              COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
 | 
						|
                            | COFF::IMAGE_SCN_MEM_READ
 | 
						|
                            | COFF::IMAGE_SCN_MEM_WRITE,
 | 
						|
                              SectionKind::getBSS());
 | 
						|
  }
 | 
						|
 | 
						|
  bool ParseDirectiveSection(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveDef(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveScl(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveType(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveEndef(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveSecRel32(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveSecIdx(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveSafeSEH(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveSymIdx(StringRef, SMLoc);
 | 
						|
  bool parseCOMDATType(COFF::COMDATType &Type);
 | 
						|
  bool ParseDirectiveLinkOnce(StringRef, SMLoc);
 | 
						|
  bool ParseDirectiveRVA(StringRef, SMLoc);
 | 
						|
 | 
						|
  // Win64 EH directives.
 | 
						|
  bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveEndProc(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveStartChained(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveEndChained(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveHandler(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
 | 
						|
  bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
 | 
						|
 | 
						|
  bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
 | 
						|
  bool ParseSEHRegisterNumber(unsigned &RegNo);
 | 
						|
  bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
 | 
						|
 | 
						|
public:
 | 
						|
  COFFAsmParser() = default;
 | 
						|
};
 | 
						|
 | 
						|
} // end anonymous namespace.
 | 
						|
 | 
						|
static SectionKind computeSectionKind(unsigned Flags) {
 | 
						|
  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
 | 
						|
    return SectionKind::getText();
 | 
						|
  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
 | 
						|
      (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
 | 
						|
    return SectionKind::getReadOnly();
 | 
						|
  return SectionKind::getData();
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSectionFlags(StringRef SectionName,
 | 
						|
                                      StringRef FlagsString, unsigned *Flags) {
 | 
						|
  enum {
 | 
						|
    None        = 0,
 | 
						|
    Alloc       = 1 << 0,
 | 
						|
    Code        = 1 << 1,
 | 
						|
    Load        = 1 << 2,
 | 
						|
    InitData    = 1 << 3,
 | 
						|
    Shared      = 1 << 4,
 | 
						|
    NoLoad      = 1 << 5,
 | 
						|
    NoRead      = 1 << 6,
 | 
						|
    NoWrite     = 1 << 7,
 | 
						|
    Discardable = 1 << 8,
 | 
						|
  };
 | 
						|
 | 
						|
  bool ReadOnlyRemoved = false;
 | 
						|
  unsigned SecFlags = None;
 | 
						|
 | 
						|
  for (char FlagChar : FlagsString) {
 | 
						|
    switch (FlagChar) {
 | 
						|
    case 'a':
 | 
						|
      // Ignored.
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'b': // bss section
 | 
						|
      SecFlags |= Alloc;
 | 
						|
      if (SecFlags & InitData)
 | 
						|
        return TokError("conflicting section flags 'b' and 'd'.");
 | 
						|
      SecFlags &= ~Load;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'd': // data section
 | 
						|
      SecFlags |= InitData;
 | 
						|
      if (SecFlags & Alloc)
 | 
						|
        return TokError("conflicting section flags 'b' and 'd'.");
 | 
						|
      SecFlags &= ~NoWrite;
 | 
						|
      if ((SecFlags & NoLoad) == 0)
 | 
						|
        SecFlags |= Load;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'n': // section is not loaded
 | 
						|
      SecFlags |= NoLoad;
 | 
						|
      SecFlags &= ~Load;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'D': // discardable
 | 
						|
      SecFlags |= Discardable;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'r': // read-only
 | 
						|
      ReadOnlyRemoved = false;
 | 
						|
      SecFlags |= NoWrite;
 | 
						|
      if ((SecFlags & Code) == 0)
 | 
						|
        SecFlags |= InitData;
 | 
						|
      if ((SecFlags & NoLoad) == 0)
 | 
						|
        SecFlags |= Load;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 's': // shared section
 | 
						|
      SecFlags |= Shared | InitData;
 | 
						|
      SecFlags &= ~NoWrite;
 | 
						|
      if ((SecFlags & NoLoad) == 0)
 | 
						|
        SecFlags |= Load;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'w': // writable
 | 
						|
      SecFlags &= ~NoWrite;
 | 
						|
      ReadOnlyRemoved = true;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'x': // executable section
 | 
						|
      SecFlags |= Code;
 | 
						|
      if ((SecFlags & NoLoad) == 0)
 | 
						|
        SecFlags |= Load;
 | 
						|
      if (!ReadOnlyRemoved)
 | 
						|
        SecFlags |= NoWrite;
 | 
						|
      break;
 | 
						|
 | 
						|
    case 'y': // not readable
 | 
						|
      SecFlags |= NoRead | NoWrite;
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return TokError("unknown flag");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  *Flags = 0;
 | 
						|
 | 
						|
  if (SecFlags == None)
 | 
						|
    SecFlags = InitData;
 | 
						|
 | 
						|
  if (SecFlags & Code)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
 | 
						|
  if (SecFlags & InitData)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
 | 
						|
  if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
 | 
						|
  if (SecFlags & NoLoad)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
 | 
						|
  if ((SecFlags & Discardable) ||
 | 
						|
      MCSectionCOFF::isImplicitlyDiscardable(SectionName))
 | 
						|
    *Flags |= COFF::IMAGE_SCN_MEM_DISCARDABLE;
 | 
						|
  if ((SecFlags & NoRead) == 0)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_MEM_READ;
 | 
						|
  if ((SecFlags & NoWrite) == 0)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
 | 
						|
  if (SecFlags & Shared)
 | 
						|
    *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// ParseDirectiveSymbolAttribute
 | 
						|
///  ::= { ".weak", ... } [ identifier ( , identifier )* ]
 | 
						|
bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
 | 
						|
  MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
 | 
						|
    .Case(".weak", MCSA_Weak)
 | 
						|
    .Default(MCSA_Invalid);
 | 
						|
  assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement)) {
 | 
						|
    while (true) {
 | 
						|
      StringRef Name;
 | 
						|
 | 
						|
      if (getParser().parseIdentifier(Name))
 | 
						|
        return TokError("expected identifier in directive");
 | 
						|
 | 
						|
      MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
 | 
						|
 | 
						|
      getStreamer().emitSymbolAttribute(Sym, Attr);
 | 
						|
 | 
						|
      if (getLexer().is(AsmToken::EndOfStatement))
 | 
						|
        break;
 | 
						|
 | 
						|
      if (getLexer().isNot(AsmToken::Comma))
 | 
						|
        return TokError("unexpected token in directive");
 | 
						|
      Lex();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Lex();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
 | 
						|
                                       unsigned Characteristics,
 | 
						|
                                       SectionKind Kind) {
 | 
						|
  return ParseSectionSwitch(Section, Characteristics, Kind, "", (COFF::COMDATType)0);
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
 | 
						|
                                       unsigned Characteristics,
 | 
						|
                                       SectionKind Kind,
 | 
						|
                                       StringRef COMDATSymName,
 | 
						|
                                       COFF::COMDATType Type) {
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in section switching directive");
 | 
						|
  Lex();
 | 
						|
 | 
						|
  getStreamer().SwitchSection(getContext().getCOFFSection(
 | 
						|
      Section, Characteristics, Kind, COMDATSymName, Type));
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSectionName(StringRef &SectionName) {
 | 
						|
  if (!getLexer().is(AsmToken::Identifier))
 | 
						|
    return true;
 | 
						|
 | 
						|
  SectionName = getTok().getIdentifier();
 | 
						|
  Lex();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
// .section name [, "flags"] [, identifier [ identifier ], identifier]
 | 
						|
//
 | 
						|
// Supported flags:
 | 
						|
//   a: Ignored.
 | 
						|
//   b: BSS section (uninitialized data)
 | 
						|
//   d: data section (initialized data)
 | 
						|
//   n: "noload" section (removed by linker)
 | 
						|
//   D: Discardable section
 | 
						|
//   r: Readable section
 | 
						|
//   s: Shared section
 | 
						|
//   w: Writable section
 | 
						|
//   x: Executable section
 | 
						|
//   y: Not-readable section (clears 'r')
 | 
						|
//
 | 
						|
// Subsections are not supported.
 | 
						|
bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) {
 | 
						|
  StringRef SectionName;
 | 
						|
 | 
						|
  if (ParseSectionName(SectionName))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
 | 
						|
                   COFF::IMAGE_SCN_MEM_READ |
 | 
						|
                   COFF::IMAGE_SCN_MEM_WRITE;
 | 
						|
 | 
						|
  if (getLexer().is(AsmToken::Comma)) {
 | 
						|
    Lex();
 | 
						|
 | 
						|
    if (getLexer().isNot(AsmToken::String))
 | 
						|
      return TokError("expected string in directive");
 | 
						|
 | 
						|
    StringRef FlagsStr = getTok().getStringContents();
 | 
						|
    Lex();
 | 
						|
 | 
						|
    if (ParseSectionFlags(SectionName, FlagsStr, &Flags))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  COFF::COMDATType Type = (COFF::COMDATType)0;
 | 
						|
  StringRef COMDATSymName;
 | 
						|
  if (getLexer().is(AsmToken::Comma)) {
 | 
						|
    Type = COFF::IMAGE_COMDAT_SELECT_ANY;
 | 
						|
    Lex();
 | 
						|
 | 
						|
    Flags |= COFF::IMAGE_SCN_LNK_COMDAT;
 | 
						|
 | 
						|
    if (!getLexer().is(AsmToken::Identifier))
 | 
						|
      return TokError("expected comdat type such as 'discard' or 'largest' "
 | 
						|
                      "after protection bits");
 | 
						|
 | 
						|
    if (parseCOMDATType(Type))
 | 
						|
      return true;
 | 
						|
 | 
						|
    if (getLexer().isNot(AsmToken::Comma))
 | 
						|
      return TokError("expected comma in directive");
 | 
						|
    Lex();
 | 
						|
 | 
						|
    if (getParser().parseIdentifier(COMDATSymName))
 | 
						|
      return TokError("expected identifier in directive");
 | 
						|
  }
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  SectionKind Kind = computeSectionKind(Flags);
 | 
						|
  if (Kind.isText()) {
 | 
						|
    const Triple &T = getContext().getObjectFileInfo()->getTargetTriple();
 | 
						|
    if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
 | 
						|
      Flags |= COFF::IMAGE_SCN_MEM_16BIT;
 | 
						|
  }
 | 
						|
  ParseSectionSwitch(SectionName, Flags, Kind, COMDATSymName, Type);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveDef(StringRef, SMLoc) {
 | 
						|
  StringRef SymbolName;
 | 
						|
 | 
						|
  if (getParser().parseIdentifier(SymbolName))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName);
 | 
						|
 | 
						|
  getStreamer().BeginCOFFSymbolDef(Sym);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveScl(StringRef, SMLoc) {
 | 
						|
  int64_t SymbolStorageClass;
 | 
						|
  if (getParser().parseAbsoluteExpression(SymbolStorageClass))
 | 
						|
    return true;
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSymbolStorageClass(SymbolStorageClass);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveType(StringRef, SMLoc) {
 | 
						|
  int64_t Type;
 | 
						|
  if (getParser().parseAbsoluteExpression(Type))
 | 
						|
    return true;
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSymbolType(Type);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EndCOFFSymbolDef();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  int64_t Offset = 0;
 | 
						|
  SMLoc OffsetLoc;
 | 
						|
  if (getLexer().is(AsmToken::Plus)) {
 | 
						|
    OffsetLoc = getLexer().getLoc();
 | 
						|
    if (getParser().parseAbsoluteExpression(Offset))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  if (Offset < 0 || Offset > std::numeric_limits<uint32_t>::max())
 | 
						|
    return Error(
 | 
						|
        OffsetLoc,
 | 
						|
        "invalid '.secrel32' directive offset, can't be less "
 | 
						|
        "than zero or greater than std::numeric_limits<uint32_t>::max()");
 | 
						|
 | 
						|
  MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSecRel32(Symbol, Offset);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveRVA(StringRef, SMLoc) {
 | 
						|
  auto parseOp = [&]() -> bool {
 | 
						|
    StringRef SymbolID;
 | 
						|
    if (getParser().parseIdentifier(SymbolID))
 | 
						|
      return TokError("expected identifier in directive");
 | 
						|
 | 
						|
    int64_t Offset = 0;
 | 
						|
    SMLoc OffsetLoc;
 | 
						|
    if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) {
 | 
						|
      OffsetLoc = getLexer().getLoc();
 | 
						|
      if (getParser().parseAbsoluteExpression(Offset))
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Offset < std::numeric_limits<int32_t>::min() ||
 | 
						|
        Offset > std::numeric_limits<int32_t>::max())
 | 
						|
      return Error(OffsetLoc, "invalid '.rva' directive offset, can't be less "
 | 
						|
                              "than -2147483648 or greater than "
 | 
						|
                              "2147483647");
 | 
						|
 | 
						|
    MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
    getStreamer().EmitCOFFImgRel32(Symbol, Offset);
 | 
						|
    return false;
 | 
						|
  };
 | 
						|
 | 
						|
  if (getParser().parseMany(parseOp))
 | 
						|
    return addErrorSuffix(" in directive");
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveSafeSEH(StringRef, SMLoc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSafeSEH(Symbol);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveSecIdx(StringRef, SMLoc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSectionIndex(Symbol);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseDirectiveSymIdx(StringRef, SMLoc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return TokError("expected identifier in directive");
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitCOFFSymbolIndex(Symbol);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// ::= [ identifier ]
 | 
						|
bool COFFAsmParser::parseCOMDATType(COFF::COMDATType &Type) {
 | 
						|
  StringRef TypeId = getTok().getIdentifier();
 | 
						|
 | 
						|
  Type = StringSwitch<COFF::COMDATType>(TypeId)
 | 
						|
    .Case("one_only", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES)
 | 
						|
    .Case("discard", COFF::IMAGE_COMDAT_SELECT_ANY)
 | 
						|
    .Case("same_size", COFF::IMAGE_COMDAT_SELECT_SAME_SIZE)
 | 
						|
    .Case("same_contents", COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH)
 | 
						|
    .Case("associative", COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
 | 
						|
    .Case("largest", COFF::IMAGE_COMDAT_SELECT_LARGEST)
 | 
						|
    .Case("newest", COFF::IMAGE_COMDAT_SELECT_NEWEST)
 | 
						|
    .Default((COFF::COMDATType)0);
 | 
						|
 | 
						|
  if (Type == 0)
 | 
						|
    return TokError(Twine("unrecognized COMDAT type '" + TypeId + "'"));
 | 
						|
 | 
						|
  Lex();
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// ParseDirectiveLinkOnce
 | 
						|
///  ::= .linkonce [ identifier ]
 | 
						|
bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) {
 | 
						|
  COFF::COMDATType Type = COFF::IMAGE_COMDAT_SELECT_ANY;
 | 
						|
  if (getLexer().is(AsmToken::Identifier))
 | 
						|
    if (parseCOMDATType(Type))
 | 
						|
      return true;
 | 
						|
 | 
						|
  const MCSectionCOFF *Current =
 | 
						|
      static_cast<const MCSectionCOFF *>(getStreamer().getCurrentSectionOnly());
 | 
						|
 | 
						|
  if (Type == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
 | 
						|
    return Error(Loc, "cannot make section associative with .linkonce");
 | 
						|
 | 
						|
  if (Current->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT)
 | 
						|
    return Error(Loc, Twine("section '") + Current->getSectionName() +
 | 
						|
                                                       "' is already linkonce");
 | 
						|
 | 
						|
  Current->setSelection(Type);
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return true;
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIStartProc(Symbol, Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIEndProc(Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIStartChained(Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIEndChained(Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) {
 | 
						|
  StringRef SymbolID;
 | 
						|
  if (getParser().parseIdentifier(SymbolID))
 | 
						|
    return true;
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::Comma))
 | 
						|
    return TokError("you must specify one or both of @unwind or @except");
 | 
						|
  Lex();
 | 
						|
  bool unwind = false, except = false;
 | 
						|
  if (ParseAtUnwindOrAtExcept(unwind, except))
 | 
						|
    return true;
 | 
						|
  if (getLexer().is(AsmToken::Comma)) {
 | 
						|
    Lex();
 | 
						|
    if (ParseAtUnwindOrAtExcept(unwind, except))
 | 
						|
      return true;
 | 
						|
  }
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID);
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinEHHandler(handler, unwind, except, Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinEHHandlerData();
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) {
 | 
						|
  int64_t Size;
 | 
						|
  if (getParser().parseAbsoluteExpression(Size))
 | 
						|
    return true;
 | 
						|
 | 
						|
  if (getLexer().isNot(AsmToken::EndOfStatement))
 | 
						|
    return TokError("unexpected token in directive");
 | 
						|
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIAllocStack(Size, Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
 | 
						|
  Lex();
 | 
						|
  getStreamer().EmitWinCFIEndProlog(Loc);
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
 | 
						|
  StringRef identifier;
 | 
						|
  if (getLexer().isNot(AsmToken::At))
 | 
						|
    return TokError("a handler attribute must begin with '@'");
 | 
						|
  SMLoc startLoc = getLexer().getLoc();
 | 
						|
  Lex();
 | 
						|
  if (getParser().parseIdentifier(identifier))
 | 
						|
    return Error(startLoc, "expected @unwind or @except");
 | 
						|
  if (identifier == "unwind")
 | 
						|
    unwind = true;
 | 
						|
  else if (identifier == "except")
 | 
						|
    except = true;
 | 
						|
  else
 | 
						|
    return Error(startLoc, "expected @unwind or @except");
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
 | 
						|
MCAsmParserExtension *createCOFFAsmParser() {
 | 
						|
  return new COFFAsmParser;
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace llvm
 |