1*5ffd83dbSDimitry Andric //===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric 9*5ffd83dbSDimitry Andric #include "llvm/ADT/StringRef.h" 10*5ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 11*5ffd83dbSDimitry Andric #include "llvm/ADT/Triple.h" 12*5ffd83dbSDimitry Andric #include "llvm/ADT/Twine.h" 13*5ffd83dbSDimitry Andric #include "llvm/BinaryFormat/COFF.h" 14*5ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 15*5ffd83dbSDimitry Andric #include "llvm/MC/MCDirectives.h" 16*5ffd83dbSDimitry Andric #include "llvm/MC/MCObjectFileInfo.h" 17*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h" 18*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserExtension.h" 19*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCAsmParserUtils.h" 20*5ffd83dbSDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h" 21*5ffd83dbSDimitry Andric #include "llvm/MC/MCRegisterInfo.h" 22*5ffd83dbSDimitry Andric #include "llvm/MC/MCSectionCOFF.h" 23*5ffd83dbSDimitry Andric #include "llvm/MC/MCStreamer.h" 24*5ffd83dbSDimitry Andric #include "llvm/MC/SectionKind.h" 25*5ffd83dbSDimitry Andric #include "llvm/Support/SMLoc.h" 26*5ffd83dbSDimitry Andric #include <cassert> 27*5ffd83dbSDimitry Andric #include <cstdint> 28*5ffd83dbSDimitry Andric #include <limits> 29*5ffd83dbSDimitry Andric #include <utility> 30*5ffd83dbSDimitry Andric 31*5ffd83dbSDimitry Andric using namespace llvm; 32*5ffd83dbSDimitry Andric 33*5ffd83dbSDimitry Andric namespace { 34*5ffd83dbSDimitry Andric 35*5ffd83dbSDimitry Andric class COFFMasmParser : public MCAsmParserExtension { 36*5ffd83dbSDimitry Andric template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)> 37*5ffd83dbSDimitry Andric void addDirectiveHandler(StringRef Directive) { 38*5ffd83dbSDimitry Andric MCAsmParser::ExtensionDirectiveHandler Handler = 39*5ffd83dbSDimitry Andric std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>); 40*5ffd83dbSDimitry Andric getParser().addDirectiveHandler(Directive, Handler); 41*5ffd83dbSDimitry Andric } 42*5ffd83dbSDimitry Andric 43*5ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 44*5ffd83dbSDimitry Andric SectionKind Kind); 45*5ffd83dbSDimitry Andric 46*5ffd83dbSDimitry Andric bool ParseSectionSwitch(StringRef Section, unsigned Characteristics, 47*5ffd83dbSDimitry Andric SectionKind Kind, StringRef COMDATSymName, 48*5ffd83dbSDimitry Andric COFF::COMDATType Type); 49*5ffd83dbSDimitry Andric 50*5ffd83dbSDimitry Andric bool ParseDirectiveProc(StringRef, SMLoc); 51*5ffd83dbSDimitry Andric bool ParseDirectiveEndProc(StringRef, SMLoc); 52*5ffd83dbSDimitry Andric bool ParseDirectiveSegment(StringRef, SMLoc); 53*5ffd83dbSDimitry Andric bool ParseDirectiveSegmentEnd(StringRef, SMLoc); 54*5ffd83dbSDimitry Andric bool ParseDirectiveIncludelib(StringRef, SMLoc); 55*5ffd83dbSDimitry Andric 56*5ffd83dbSDimitry Andric bool IgnoreDirective(StringRef, SMLoc) { 57*5ffd83dbSDimitry Andric while (!getLexer().is(AsmToken::EndOfStatement)) { 58*5ffd83dbSDimitry Andric Lex(); 59*5ffd83dbSDimitry Andric } 60*5ffd83dbSDimitry Andric return false; 61*5ffd83dbSDimitry Andric } 62*5ffd83dbSDimitry Andric 63*5ffd83dbSDimitry Andric void Initialize(MCAsmParser &Parser) override { 64*5ffd83dbSDimitry Andric // Call the base implementation. 65*5ffd83dbSDimitry Andric MCAsmParserExtension::Initialize(Parser); 66*5ffd83dbSDimitry Andric 67*5ffd83dbSDimitry Andric // x64 directives 68*5ffd83dbSDimitry Andric // .allocstack 69*5ffd83dbSDimitry Andric // .endprolog 70*5ffd83dbSDimitry Andric // .pushframe 71*5ffd83dbSDimitry Andric // .pushreg 72*5ffd83dbSDimitry Andric // .savereg 73*5ffd83dbSDimitry Andric // .savexmm128 74*5ffd83dbSDimitry Andric // .setframe 75*5ffd83dbSDimitry Andric 76*5ffd83dbSDimitry Andric // Code label directives 77*5ffd83dbSDimitry Andric // label 78*5ffd83dbSDimitry Andric // org 79*5ffd83dbSDimitry Andric 80*5ffd83dbSDimitry Andric // Conditional control flow directives 81*5ffd83dbSDimitry Andric // .break 82*5ffd83dbSDimitry Andric // .continue 83*5ffd83dbSDimitry Andric // .else 84*5ffd83dbSDimitry Andric // .elseif 85*5ffd83dbSDimitry Andric // .endif 86*5ffd83dbSDimitry Andric // .endw 87*5ffd83dbSDimitry Andric // .if 88*5ffd83dbSDimitry Andric // .repeat 89*5ffd83dbSDimitry Andric // .until 90*5ffd83dbSDimitry Andric // .untilcxz 91*5ffd83dbSDimitry Andric // .while 92*5ffd83dbSDimitry Andric 93*5ffd83dbSDimitry Andric // Data allocation directives 94*5ffd83dbSDimitry Andric // align 95*5ffd83dbSDimitry Andric // byte/sbyte 96*5ffd83dbSDimitry Andric // dword/sdword 97*5ffd83dbSDimitry Andric // even 98*5ffd83dbSDimitry Andric // fword 99*5ffd83dbSDimitry Andric // qword 100*5ffd83dbSDimitry Andric // real4 101*5ffd83dbSDimitry Andric // real8 102*5ffd83dbSDimitry Andric // real10 103*5ffd83dbSDimitry Andric // tbyte 104*5ffd83dbSDimitry Andric // word/sword 105*5ffd83dbSDimitry Andric 106*5ffd83dbSDimitry Andric // Listing control directives 107*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref"); 108*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list"); 109*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall"); 110*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif"); 111*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro"); 112*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall"); 113*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref"); 114*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist"); 115*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif"); 116*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro"); 117*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page"); 118*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle"); 119*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond"); 120*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title"); 121*5ffd83dbSDimitry Andric 122*5ffd83dbSDimitry Andric // Macro directives 123*5ffd83dbSDimitry Andric // endm 124*5ffd83dbSDimitry Andric // exitm 125*5ffd83dbSDimitry Andric // goto 126*5ffd83dbSDimitry Andric // local 127*5ffd83dbSDimitry Andric // macro 128*5ffd83dbSDimitry Andric // purge 129*5ffd83dbSDimitry Andric 130*5ffd83dbSDimitry Andric // Miscellaneous directives 131*5ffd83dbSDimitry Andric // alias 132*5ffd83dbSDimitry Andric // assume 133*5ffd83dbSDimitry Andric // .fpo 134*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>( 135*5ffd83dbSDimitry Andric "includelib"); 136*5ffd83dbSDimitry Andric // mmword 137*5ffd83dbSDimitry Andric // option 138*5ffd83dbSDimitry Andric // popcontext 139*5ffd83dbSDimitry Andric // pushcontext 140*5ffd83dbSDimitry Andric // .radix 141*5ffd83dbSDimitry Andric // .safeseh 142*5ffd83dbSDimitry Andric // xmmword 143*5ffd83dbSDimitry Andric // ymmword 144*5ffd83dbSDimitry Andric 145*5ffd83dbSDimitry Andric // Procedure directives 146*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp"); 147*5ffd83dbSDimitry Andric // invoke (32-bit only) 148*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc"); 149*5ffd83dbSDimitry Andric // proto 150*5ffd83dbSDimitry Andric 151*5ffd83dbSDimitry Andric // Processor directives 152*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386"); 153*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P"); 154*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387"); 155*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486"); 156*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P"); 157*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586"); 158*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P"); 159*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686"); 160*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P"); 161*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d"); 162*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx"); 163*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm"); 164*5ffd83dbSDimitry Andric 165*5ffd83dbSDimitry Andric // Repeat blocks directives 166*5ffd83dbSDimitry Andric // for 167*5ffd83dbSDimitry Andric // forc 168*5ffd83dbSDimitry Andric // goto 169*5ffd83dbSDimitry Andric // repeat 170*5ffd83dbSDimitry Andric // while 171*5ffd83dbSDimitry Andric 172*5ffd83dbSDimitry Andric // Scope directives 173*5ffd83dbSDimitry Andric // comm 174*5ffd83dbSDimitry Andric // externdef 175*5ffd83dbSDimitry Andric 176*5ffd83dbSDimitry Andric // Segment directives 177*5ffd83dbSDimitry Andric // .alpha (32-bit only, order segments alphabetically) 178*5ffd83dbSDimitry Andric // .dosseg (32-bit only, order segments in DOS convention) 179*5ffd83dbSDimitry Andric // .seq (32-bit only, order segments sequentially) 180*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends"); 181*5ffd83dbSDimitry Andric // group (32-bit only) 182*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment"); 183*5ffd83dbSDimitry Andric 184*5ffd83dbSDimitry Andric // Simplified segment directives 185*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code"); 186*5ffd83dbSDimitry Andric // .const 187*5ffd83dbSDimitry Andric addDirectiveHandler< 188*5ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveInitializedData>(".data"); 189*5ffd83dbSDimitry Andric addDirectiveHandler< 190*5ffd83dbSDimitry Andric &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?"); 191*5ffd83dbSDimitry Andric // .exit 192*5ffd83dbSDimitry Andric // .fardata 193*5ffd83dbSDimitry Andric // .fardata? 194*5ffd83dbSDimitry Andric addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model"); 195*5ffd83dbSDimitry Andric // .stack 196*5ffd83dbSDimitry Andric // .startup 197*5ffd83dbSDimitry Andric 198*5ffd83dbSDimitry Andric // String directives, written <name> <directive> <params> 199*5ffd83dbSDimitry Andric // catstr (equivalent to <name> TEXTEQU <params>) 200*5ffd83dbSDimitry Andric // instr (equivalent to <name> = @InStr(<params>)) 201*5ffd83dbSDimitry Andric // sizestr (equivalent to <name> = @SizeStr(<params>)) 202*5ffd83dbSDimitry Andric // substr (equivalent to <name> TEXTEQU @SubStr(<params>)) 203*5ffd83dbSDimitry Andric 204*5ffd83dbSDimitry Andric // Structure and record directives 205*5ffd83dbSDimitry Andric // ends 206*5ffd83dbSDimitry Andric // record 207*5ffd83dbSDimitry Andric // struct 208*5ffd83dbSDimitry Andric // typedef 209*5ffd83dbSDimitry Andric // union 210*5ffd83dbSDimitry Andric } 211*5ffd83dbSDimitry Andric 212*5ffd83dbSDimitry Andric bool ParseSectionDirectiveCode(StringRef, SMLoc) { 213*5ffd83dbSDimitry Andric return ParseSectionSwitch(".text", 214*5ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_CODE 215*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_EXECUTE 216*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ, 217*5ffd83dbSDimitry Andric SectionKind::getText()); 218*5ffd83dbSDimitry Andric } 219*5ffd83dbSDimitry Andric 220*5ffd83dbSDimitry Andric bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) { 221*5ffd83dbSDimitry Andric return ParseSectionSwitch(".data", 222*5ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_INITIALIZED_DATA 223*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 224*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 225*5ffd83dbSDimitry Andric SectionKind::getData()); 226*5ffd83dbSDimitry Andric } 227*5ffd83dbSDimitry Andric 228*5ffd83dbSDimitry Andric bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) { 229*5ffd83dbSDimitry Andric return ParseSectionSwitch(".bss", 230*5ffd83dbSDimitry Andric COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA 231*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_READ 232*5ffd83dbSDimitry Andric | COFF::IMAGE_SCN_MEM_WRITE, 233*5ffd83dbSDimitry Andric SectionKind::getBSS()); 234*5ffd83dbSDimitry Andric } 235*5ffd83dbSDimitry Andric 236*5ffd83dbSDimitry Andric StringRef CurrentProcedure; 237*5ffd83dbSDimitry Andric 238*5ffd83dbSDimitry Andric public: 239*5ffd83dbSDimitry Andric COFFMasmParser() = default; 240*5ffd83dbSDimitry Andric }; 241*5ffd83dbSDimitry Andric 242*5ffd83dbSDimitry Andric } // end anonymous namespace. 243*5ffd83dbSDimitry Andric 244*5ffd83dbSDimitry Andric static SectionKind computeSectionKind(unsigned Flags) { 245*5ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE) 246*5ffd83dbSDimitry Andric return SectionKind::getText(); 247*5ffd83dbSDimitry Andric if (Flags & COFF::IMAGE_SCN_MEM_READ && 248*5ffd83dbSDimitry Andric (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0) 249*5ffd83dbSDimitry Andric return SectionKind::getReadOnly(); 250*5ffd83dbSDimitry Andric return SectionKind::getData(); 251*5ffd83dbSDimitry Andric } 252*5ffd83dbSDimitry Andric 253*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 254*5ffd83dbSDimitry Andric unsigned Characteristics, 255*5ffd83dbSDimitry Andric SectionKind Kind) { 256*5ffd83dbSDimitry Andric return ParseSectionSwitch(Section, Characteristics, Kind, "", 257*5ffd83dbSDimitry Andric (COFF::COMDATType)0); 258*5ffd83dbSDimitry Andric } 259*5ffd83dbSDimitry Andric 260*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseSectionSwitch(StringRef Section, 261*5ffd83dbSDimitry Andric unsigned Characteristics, 262*5ffd83dbSDimitry Andric SectionKind Kind, 263*5ffd83dbSDimitry Andric StringRef COMDATSymName, 264*5ffd83dbSDimitry Andric COFF::COMDATType Type) { 265*5ffd83dbSDimitry Andric if (getLexer().isNot(AsmToken::EndOfStatement)) 266*5ffd83dbSDimitry Andric return TokError("unexpected token in section switching directive"); 267*5ffd83dbSDimitry Andric Lex(); 268*5ffd83dbSDimitry Andric 269*5ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 270*5ffd83dbSDimitry Andric Section, Characteristics, Kind, COMDATSymName, Type)); 271*5ffd83dbSDimitry Andric 272*5ffd83dbSDimitry Andric return false; 273*5ffd83dbSDimitry Andric } 274*5ffd83dbSDimitry Andric 275*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) { 276*5ffd83dbSDimitry Andric StringRef SegmentName; 277*5ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 278*5ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 279*5ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 280*5ffd83dbSDimitry Andric Lex(); 281*5ffd83dbSDimitry Andric 282*5ffd83dbSDimitry Andric StringRef SectionName = SegmentName; 283*5ffd83dbSDimitry Andric SmallVector<char, 247> SectionNameVector; 284*5ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | 285*5ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE; 286*5ffd83dbSDimitry Andric if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) { 287*5ffd83dbSDimitry Andric if (SegmentName.size() == 5) { 288*5ffd83dbSDimitry Andric SectionName = ".text"; 289*5ffd83dbSDimitry Andric } else { 290*5ffd83dbSDimitry Andric SectionName = 291*5ffd83dbSDimitry Andric (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector); 292*5ffd83dbSDimitry Andric } 293*5ffd83dbSDimitry Andric Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE | 294*5ffd83dbSDimitry Andric COFF::IMAGE_SCN_MEM_READ; 295*5ffd83dbSDimitry Andric } 296*5ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 297*5ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 298*5ffd83dbSDimitry Andric SectionName, Flags, Kind, "", (COFF::COMDATType)(0))); 299*5ffd83dbSDimitry Andric return false; 300*5ffd83dbSDimitry Andric } 301*5ffd83dbSDimitry Andric 302*5ffd83dbSDimitry Andric /// ParseDirectiveSegmentEnd 303*5ffd83dbSDimitry Andric /// ::= identifier "ends" 304*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) { 305*5ffd83dbSDimitry Andric StringRef SegmentName; 306*5ffd83dbSDimitry Andric if (!getLexer().is(AsmToken::Identifier)) 307*5ffd83dbSDimitry Andric return TokError("expected identifier in directive"); 308*5ffd83dbSDimitry Andric SegmentName = getTok().getIdentifier(); 309*5ffd83dbSDimitry Andric 310*5ffd83dbSDimitry Andric // Ignore; no action necessary. 311*5ffd83dbSDimitry Andric Lex(); 312*5ffd83dbSDimitry Andric return false; 313*5ffd83dbSDimitry Andric } 314*5ffd83dbSDimitry Andric 315*5ffd83dbSDimitry Andric /// ParseDirectiveIncludelib 316*5ffd83dbSDimitry Andric /// ::= "includelib" identifier 317*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) { 318*5ffd83dbSDimitry Andric StringRef Lib; 319*5ffd83dbSDimitry Andric if (getParser().parseIdentifier(Lib)) 320*5ffd83dbSDimitry Andric return TokError("expected identifier in includelib directive"); 321*5ffd83dbSDimitry Andric 322*5ffd83dbSDimitry Andric unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT; 323*5ffd83dbSDimitry Andric SectionKind Kind = computeSectionKind(Flags); 324*5ffd83dbSDimitry Andric getStreamer().PushSection(); 325*5ffd83dbSDimitry Andric getStreamer().SwitchSection(getContext().getCOFFSection( 326*5ffd83dbSDimitry Andric ".drectve", Flags, Kind, "", (COFF::COMDATType)(0))); 327*5ffd83dbSDimitry Andric getStreamer().emitBytes("/DEFAULTLIB:"); 328*5ffd83dbSDimitry Andric getStreamer().emitBytes(Lib); 329*5ffd83dbSDimitry Andric getStreamer().emitBytes(" "); 330*5ffd83dbSDimitry Andric getStreamer().PopSection(); 331*5ffd83dbSDimitry Andric return false; 332*5ffd83dbSDimitry Andric } 333*5ffd83dbSDimitry Andric 334*5ffd83dbSDimitry Andric /// ParseDirectiveProc 335*5ffd83dbSDimitry Andric /// TODO(epastor): Implement parameters and other attributes. 336*5ffd83dbSDimitry Andric /// ::= label "proc" [[distance]] 337*5ffd83dbSDimitry Andric /// statements 338*5ffd83dbSDimitry Andric /// label "endproc" 339*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) { 340*5ffd83dbSDimitry Andric StringRef Label; 341*5ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 342*5ffd83dbSDimitry Andric return Error(Loc, "expected identifier for procedure"); 343*5ffd83dbSDimitry Andric if (getLexer().is(AsmToken::Identifier)) { 344*5ffd83dbSDimitry Andric StringRef nextVal = getTok().getString(); 345*5ffd83dbSDimitry Andric SMLoc nextLoc = getTok().getLoc(); 346*5ffd83dbSDimitry Andric if (nextVal.equals_lower("far")) { 347*5ffd83dbSDimitry Andric // TODO(epastor): Handle far procedure definitions. 348*5ffd83dbSDimitry Andric Lex(); 349*5ffd83dbSDimitry Andric return Error(nextLoc, "far procedure definitions not yet supported"); 350*5ffd83dbSDimitry Andric } else if (nextVal.equals_lower("near")) { 351*5ffd83dbSDimitry Andric Lex(); 352*5ffd83dbSDimitry Andric nextVal = getTok().getString(); 353*5ffd83dbSDimitry Andric nextLoc = getTok().getLoc(); 354*5ffd83dbSDimitry Andric } 355*5ffd83dbSDimitry Andric } 356*5ffd83dbSDimitry Andric MCSymbol *Sym = getContext().getOrCreateSymbol(Label); 357*5ffd83dbSDimitry Andric 358*5ffd83dbSDimitry Andric // Define symbol as simple function 359*5ffd83dbSDimitry Andric getStreamer().BeginCOFFSymbolDef(Sym); 360*5ffd83dbSDimitry Andric getStreamer().EmitCOFFSymbolStorageClass(2); 361*5ffd83dbSDimitry Andric getStreamer().EmitCOFFSymbolType(0x20); 362*5ffd83dbSDimitry Andric getStreamer().EndCOFFSymbolDef(); 363*5ffd83dbSDimitry Andric 364*5ffd83dbSDimitry Andric getStreamer().emitLabel(Sym, Loc); 365*5ffd83dbSDimitry Andric CurrentProcedure = Label; 366*5ffd83dbSDimitry Andric return false; 367*5ffd83dbSDimitry Andric } 368*5ffd83dbSDimitry Andric bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) { 369*5ffd83dbSDimitry Andric StringRef Label; 370*5ffd83dbSDimitry Andric SMLoc LabelLoc = getTok().getLoc(); 371*5ffd83dbSDimitry Andric if (getParser().parseIdentifier(Label)) 372*5ffd83dbSDimitry Andric return Error(LabelLoc, "expected identifier for procedure end"); 373*5ffd83dbSDimitry Andric 374*5ffd83dbSDimitry Andric if (CurrentProcedure.empty()) 375*5ffd83dbSDimitry Andric return Error(Loc, "endp outside of procedure block"); 376*5ffd83dbSDimitry Andric else if (CurrentProcedure != Label) 377*5ffd83dbSDimitry Andric return Error(LabelLoc, "endp does not match current procedure '" + 378*5ffd83dbSDimitry Andric CurrentProcedure + "'"); 379*5ffd83dbSDimitry Andric return false; 380*5ffd83dbSDimitry Andric } 381*5ffd83dbSDimitry Andric 382*5ffd83dbSDimitry Andric namespace llvm { 383*5ffd83dbSDimitry Andric 384*5ffd83dbSDimitry Andric MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; } 385*5ffd83dbSDimitry Andric 386*5ffd83dbSDimitry Andric } // end namespace llvm 387