66//
77// ===----------------------------------------------------------------------===//
88
9+ #include " third_party/llvm/llvm-project/llvm/include/llvm/MC/MCContext.h"
910#include " llvm/ADT/StringRef.h"
1011#include " llvm/ADT/Twine.h"
1112#include " llvm/BinaryFormat/COFF.h"
@@ -41,6 +42,7 @@ class COFFMasmParser : public MCAsmParserExtension {
4142 StringRef COMDATSymName, COFF::COMDATType Type,
4243 Align Alignment);
4344
45+ bool parseDirectiveModel (StringRef, SMLoc);
4446 bool parseDirectiveProc (StringRef, SMLoc);
4547 bool parseDirectiveEndProc (StringRef, SMLoc);
4648 bool parseDirectiveSegment (StringRef, SMLoc);
@@ -167,7 +169,7 @@ class COFFMasmParser : public MCAsmParserExtension {
167169 // .exit
168170 // .fardata
169171 // .fardata?
170- addDirectiveHandler<&COFFMasmParser::IgnoreDirective >(" .model" );
172+ addDirectiveHandler<&COFFMasmParser::parseDirectiveModel >(" .model" );
171173 // .stack
172174 // .startup
173175
@@ -201,8 +203,13 @@ class COFFMasmParser : public MCAsmParserExtension {
201203 }
202204
203205 // / Stack of active procedure definitions.
204- SmallVector<StringRef, 1 > CurrentProcedures;
205- SmallVector<bool , 1 > CurrentProceduresFramed;
206+ enum ProcDistance { PROC_DISTANCE_NEAR = 0 , PROC_DISTANCE_FAR = 1 };
207+ struct ProcInfo {
208+ StringRef Name;
209+ ProcDistance Distance = PROC_DISTANCE_NEAR;
210+ bool IsFramed = false ;
211+ };
212+ SmallVector<ProcInfo, 1 > CurrentProcedures;
206213
207214public:
208215 COFFMasmParser () = default ;
@@ -435,48 +442,75 @@ bool COFFMasmParser::parseDirectiveOption(StringRef Directive, SMLoc Loc) {
435442 return false ;
436443}
437444
445+ // / parseDirectiveModel
446+ // / ::= ".model" "flat"
447+ bool COFFMasmParser::parseDirectiveModel (StringRef Directive, SMLoc Loc) {
448+ if (!getLexer ().is (AsmToken::Identifier))
449+ return TokError (" expected identifier in directive" );
450+
451+ StringRef ModelType = getTok ().getIdentifier ();
452+ if (!ModelType.equals_insensitive (" flat" )) {
453+ return TokError (
454+ " expected 'flat' for memory model; no other models supported" );
455+ }
456+
457+ // Ignore; no action necessary.
458+ Lex ();
459+ return false ;
460+ }
461+
438462// / parseDirectiveProc
439463// / TODO(epastor): Implement parameters and other attributes.
440- // / ::= label "proc" [[distance]]
464+ // / ::= label "proc" [[distance]] [[frame]]
441465// / statements
442466// / label "endproc"
443467bool COFFMasmParser::parseDirectiveProc (StringRef Directive, SMLoc Loc) {
444468 if (!getStreamer ().getCurrentFragment ())
445469 return Error (getTok ().getLoc (), " expected section directive" );
446470
447- StringRef Label ;
448- if (getParser ().parseIdentifier (Label ))
471+ ProcInfo Proc ;
472+ if (getParser ().parseIdentifier (Proc. Name ))
449473 return Error (Loc, " expected identifier for procedure" );
450474 if (getLexer ().is (AsmToken::Identifier)) {
451475 StringRef nextVal = getTok ().getString ();
452476 SMLoc nextLoc = getTok ().getLoc ();
453477 if (nextVal.equals_insensitive (" far" )) {
454- // TODO(epastor): Handle far procedure definitions.
455478 Lex ();
456- return Error (nextLoc, " far procedure definitions not yet supported" );
479+ Proc.Distance = PROC_DISTANCE_FAR;
480+ nextVal = getTok ().getString ();
481+ nextLoc = getTok ().getLoc ();
457482 } else if (nextVal.equals_insensitive (" near" )) {
458483 Lex ();
484+ Proc.Distance = PROC_DISTANCE_NEAR;
459485 nextVal = getTok ().getString ();
460486 nextLoc = getTok ().getLoc ();
461487 }
462488 }
463- MCSymbolCOFF *Sym = cast<MCSymbolCOFF>(getContext ().getOrCreateSymbol (Label));
489+ MCSymbolCOFF *Sym =
490+ cast<MCSymbolCOFF>(getContext ().getOrCreateSymbol (Proc.Name ));
464491
465492 // Define symbol as simple external function
466493 Sym->setExternal (true );
467494 Sym->setType (COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT);
495+ if (Proc.Distance == PROC_DISTANCE_FAR)
496+ Sym->setIsFarProc ();
497+
498+ getContext ().setDefaultRetType (Proc.Distance == PROC_DISTANCE_NEAR
499+ ? MCContext::IsNear
500+ : MCContext::IsFar);
468501
469- bool Framed = false ;
470502 if (getLexer ().is (AsmToken::Identifier) &&
471503 getTok ().getString ().equals_insensitive (" frame" )) {
472504 Lex ();
473- Framed = true ;
505+ Proc.IsFramed = true ;
506+ getStreamer ().emitWinCFIStartProc (Sym, Loc);
507+ }
508+ if (Proc.IsFramed ) {
474509 getStreamer ().emitWinCFIStartProc (Sym, Loc);
475510 }
476511 getStreamer ().emitLabel (Sym, Loc);
477512
478- CurrentProcedures.push_back (Label);
479- CurrentProceduresFramed.push_back (Framed);
513+ CurrentProcedures.push_back (std::move (Proc));
480514 return false ;
481515}
482516bool COFFMasmParser::parseDirectiveEndProc (StringRef Directive, SMLoc Loc) {
@@ -487,15 +521,19 @@ bool COFFMasmParser::parseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
487521
488522 if (CurrentProcedures.empty ())
489523 return Error (Loc, " endp outside of procedure block" );
490- else if (!CurrentProcedures.back ().equals_insensitive (Label))
524+ else if (!CurrentProcedures.back ().Name . equals_insensitive (Label))
491525 return Error (LabelLoc, " endp does not match current procedure '" +
492- CurrentProcedures.back () + " '" );
526+ CurrentProcedures.back (). Name + " '" );
493527
494- if (CurrentProceduresFramed .back ()) {
528+ if (CurrentProcedures .back (). IsFramed ) {
495529 getStreamer ().emitWinCFIEndProc (Loc);
496530 }
497531 CurrentProcedures.pop_back ();
498- CurrentProceduresFramed.pop_back ();
532+ getContext ().setDefaultRetType (
533+ (CurrentProcedures.empty () ||
534+ CurrentProcedures.back ().Distance == PROC_DISTANCE_NEAR)
535+ ? MCContext::IsNear
536+ : MCContext::IsFar);
499537 return false ;
500538}
501539
0 commit comments