1212#include " llvm/MC/MCAsmMacro.h"
1313#include " llvm/MC/MCContext.h"
1414#include " llvm/MC/MCParser/MCAsmLexer.h"
15+ #include " llvm/MC/MCParser/MCAsmParser.h"
1516#include " llvm/MC/MCParser/MCAsmParserExtension.h"
17+ #include " llvm/MC/MCParser/MCMasmParser.h"
1618#include " llvm/MC/MCParser/MCTargetAsmParser.h"
1719#include " llvm/MC/MCSectionCOFF.h"
1820#include " llvm/MC/MCStreamer.h"
@@ -41,6 +43,7 @@ class COFFMasmParser : public MCAsmParserExtension {
4143 StringRef COMDATSymName, COFF::COMDATType Type,
4244 Align Alignment);
4345
46+ bool parseDirectiveModel (StringRef, SMLoc);
4447 bool parseDirectiveProc (StringRef, SMLoc);
4548 bool parseDirectiveEndProc (StringRef, SMLoc);
4649 bool parseDirectiveSegment (StringRef, SMLoc);
@@ -167,7 +170,7 @@ class COFFMasmParser : public MCAsmParserExtension {
167170 // .exit
168171 // .fardata
169172 // .fardata?
170- addDirectiveHandler<&COFFMasmParser::IgnoreDirective >(" .model" );
173+ addDirectiveHandler<&COFFMasmParser::parseDirectiveModel >(" .model" );
171174 // .stack
172175 // .startup
173176
@@ -201,8 +204,13 @@ class COFFMasmParser : public MCAsmParserExtension {
201204 }
202205
203206 // / Stack of active procedure definitions.
204- SmallVector<StringRef, 1 > CurrentProcedures;
205- SmallVector<bool , 1 > CurrentProceduresFramed;
207+ enum ProcDistance { PROC_DISTANCE_NEAR = 0 , PROC_DISTANCE_FAR = 1 };
208+ struct ProcInfo {
209+ StringRef Name;
210+ ProcDistance Distance = PROC_DISTANCE_NEAR;
211+ bool IsFramed = false ;
212+ };
213+ SmallVector<ProcInfo, 1 > CurrentProcedures;
206214
207215public:
208216 COFFMasmParser () = default ;
@@ -435,48 +443,75 @@ bool COFFMasmParser::parseDirectiveOption(StringRef Directive, SMLoc Loc) {
435443 return false ;
436444}
437445
446+ // / parseDirectiveModel
447+ // / ::= ".model" "flat"
448+ bool COFFMasmParser::parseDirectiveModel (StringRef Directive, SMLoc Loc) {
449+ if (!getLexer ().is (AsmToken::Identifier))
450+ return TokError (" expected identifier in directive" );
451+
452+ StringRef ModelType = getTok ().getIdentifier ();
453+ if (!ModelType.equals_insensitive (" flat" )) {
454+ return TokError (
455+ " expected 'flat' for memory model; no other models supported" );
456+ }
457+
458+ // Ignore; no action necessary.
459+ Lex ();
460+ return false ;
461+ }
462+
438463// / parseDirectiveProc
439464// / TODO(epastor): Implement parameters and other attributes.
440- // / ::= label "proc" [[distance]]
465+ // / ::= label "proc" [[distance]] [[frame]]
441466// / statements
442467// / label "endproc"
443468bool COFFMasmParser::parseDirectiveProc (StringRef Directive, SMLoc Loc) {
444469 if (!getStreamer ().getCurrentFragment ())
445470 return Error (getTok ().getLoc (), " expected section directive" );
446471
447- StringRef Label ;
448- if (getParser ().parseIdentifier (Label ))
472+ ProcInfo Proc ;
473+ if (getParser ().parseIdentifier (Proc. Name ))
449474 return Error (Loc, " expected identifier for procedure" );
450- if (getLexer ().is (AsmToken::Identifier)) {
475+ while (getLexer ().is (AsmToken::Identifier)) {
451476 StringRef nextVal = getTok ().getString ();
452477 SMLoc nextLoc = getTok ().getLoc ();
453478 if (nextVal.equals_insensitive (" far" )) {
454- // TODO(epastor): Handle far procedure definitions.
455479 Lex ();
456- return Error (nextLoc, " far procedure definitions not yet supported" );
480+ Proc.Distance = PROC_DISTANCE_FAR;
481+ nextVal = getTok ().getString ();
482+ nextLoc = getTok ().getLoc ();
457483 } else if (nextVal.equals_insensitive (" near" )) {
458484 Lex ();
485+ Proc.Distance = PROC_DISTANCE_NEAR;
486+ nextVal = getTok ().getString ();
487+ nextLoc = getTok ().getLoc ();
488+ } else if (nextVal.equals_insensitive (" frame" )) {
489+ Lex ();
490+ Proc.IsFramed = true ;
459491 nextVal = getTok ().getString ();
460492 nextLoc = getTok ().getLoc ();
493+ } else {
494+ break ;
461495 }
462496 }
463- MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext ().getOrCreateSymbol (Label));
497+ MCSymbolCOFF *Sym =
498+ cast<MCSymbolCOFF>(getContext ().getOrCreateSymbol (Proc.Name ));
464499
465500 // Define symbol as simple external function
466501 Sym->setExternal (true );
467502 Sym->setType (COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT);
503+ if (Proc.Distance == PROC_DISTANCE_FAR)
504+ Sym->setIsFarProc ();
505+
506+ cast<MCMasmParser>(getParser ())
507+ .setDefaultRetIsFar (Proc.Distance == PROC_DISTANCE_FAR);
468508
469- bool Framed = false ;
470- if (getLexer ().is (AsmToken::Identifier) &&
471- getTok ().getString ().equals_insensitive (" frame" )) {
472- Lex ();
473- Framed = true ;
509+ if (Proc.IsFramed ) {
474510 getStreamer ().emitWinCFIStartProc (Sym, Loc);
475511 }
476512 getStreamer ().emitLabel (Sym, Loc);
477513
478- CurrentProcedures.push_back (Label);
479- CurrentProceduresFramed.push_back (Framed);
514+ CurrentProcedures.push_back (std::move (Proc));
480515 return false ;
481516}
482517bool COFFMasmParser::parseDirectiveEndProc (StringRef Directive, SMLoc Loc) {
@@ -487,15 +522,18 @@ bool COFFMasmParser::parseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
487522
488523 if (CurrentProcedures.empty ())
489524 return Error (Loc, " endp outside of procedure block" );
490- else if (!CurrentProcedures.back ().equals_insensitive (Label))
525+ else if (!CurrentProcedures.back ().Name . equals_insensitive (Label))
491526 return Error (LabelLoc, " endp does not match current procedure '" +
492- CurrentProcedures.back () + " '" );
527+ CurrentProcedures.back (). Name + " '" );
493528
494- if (CurrentProceduresFramed .back ()) {
529+ if (CurrentProcedures .back (). IsFramed ) {
495530 getStreamer ().emitWinCFIEndProc (Loc);
496531 }
497532 CurrentProcedures.pop_back ();
498- CurrentProceduresFramed.pop_back ();
533+ cast<MCMasmParser>(getParser ())
534+ .setDefaultRetIsFar (!CurrentProcedures.empty () &&
535+ CurrentProcedures.back ().Distance ==
536+ PROC_DISTANCE_FAR);
499537 return false ;
500538}
501539
0 commit comments