From: Reid Kleckner <rnk@google.com> Date: Tue, 10 Oct 2017 01:26:25 +0000 (+0000) Subject: [SEH] Use reportError instead of report_fatal_error for bad directives X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=be1ef6a68c7295e1443899e29a24ed0ce2995470;p=llvm [SEH] Use reportError instead of report_fatal_error for bad directives This makes the .seh_ directives slightly more usable from standalone assembly files. This removes a large number of report_fatal_errors and recovers from the error by ignoring the directive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315262 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index e54526c344c..e43bc608f0b 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -180,7 +180,10 @@ class MCStreamer { std::vector<std::unique_ptr<WinEH::FrameInfo>> WinFrameInfos; WinEH::FrameInfo *CurrentWinFrameInfo; - void EnsureValidWinFrameInfo(); + + /// Retreive the current frame info if one is available and it is not yet + /// closed. Otherwise, issue an error and return null. + WinEH::FrameInfo *EnsureValidWinFrameInfo(SMLoc Loc); /// \brief Tracks an index to represent the order a symbol was emitted in. /// Zero means we did not emit that symbol. @@ -820,20 +823,23 @@ public: virtual void EmitCFIRegister(int64_t Register1, int64_t Register2); virtual void EmitCFIWindowSave(); - virtual void EmitWinCFIStartProc(const MCSymbol *Symbol); - virtual void EmitWinCFIEndProc(); - virtual void EmitWinCFIStartChained(); - virtual void EmitWinCFIEndChained(); - virtual void EmitWinCFIPushReg(unsigned Register); - virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset); - virtual void EmitWinCFIAllocStack(unsigned Size); - virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset); - virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset); - virtual void EmitWinCFIPushFrame(bool Code); - virtual void EmitWinCFIEndProlog(); - - virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); - virtual void EmitWinEHHandlerData(); + virtual void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndProc(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIStartChained(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndChained(SMLoc Loc = SMLoc()); + virtual void EmitWinCFIPushReg(unsigned Register, SMLoc Loc = SMLoc()); + virtual void EmitWinCFISetFrame(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc = SMLoc()); + virtual void EmitWinCFISaveReg(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + SMLoc Loc = SMLoc()); + virtual void EmitWinCFIPushFrame(bool Code, SMLoc Loc = SMLoc()); + virtual void EmitWinCFIEndProlog(SMLoc Loc = SMLoc()); + virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, + SMLoc Loc = SMLoc()); + virtual void EmitWinEHHandlerData(SMLoc Loc = SMLoc()); /// Get the .pdata section used for the given section. Typically the given /// section is either the main .text section or some other COMDAT .text diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 84e60b85be6..3ab4d345054 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -61,7 +61,7 @@ public: void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitIdent(StringRef IdentString) override; - void EmitWinEHHandlerData() override; + void EmitWinEHHandlerData(SMLoc Loc) override; void FinishImpl() override; /// \} diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index b1c928950cb..08b02d0f85b 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -270,20 +270,24 @@ public: void EmitCFIWindowSave() override; void EmitCFIReturnColumn(int64_t Register) override; - void EmitWinCFIStartProc(const MCSymbol *Symbol) override; - void EmitWinCFIEndProc() override; - void EmitWinCFIStartChained() override; - void EmitWinCFIEndChained() override; - void EmitWinCFIPushReg(unsigned Register) override; - void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; - void EmitWinCFIAllocStack(unsigned Size) override; - void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; - void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; - void EmitWinCFIPushFrame(bool Code) override; - void EmitWinCFIEndProlog() override; - - void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; - void EmitWinEHHandlerData() override; + void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; + void EmitWinCFIEndProc(SMLoc Loc) override; + void EmitWinCFIStartChained(SMLoc Loc) override; + void EmitWinCFIEndChained(SMLoc Loc) override; + void EmitWinCFIPushReg(unsigned Register, SMLoc Loc) override; + void EmitWinCFISetFrame(unsigned Register, unsigned Offset, + SMLoc Loc) override; + void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override; + void EmitWinCFISaveReg(unsigned Register, unsigned Offset, + SMLoc Loc) override; + void EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + SMLoc Loc) override; + void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override; + void EmitWinCFIEndProlog(SMLoc Loc) override; + + void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, + SMLoc Loc) override; + void EmitWinEHHandlerData(SMLoc Loc) override; void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, bool PrintSchedInfo) override; @@ -1425,38 +1429,38 @@ void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) { EmitEOL(); } -void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { - MCStreamer::EmitWinCFIStartProc(Symbol); +void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { + MCStreamer::EmitWinCFIStartProc(Symbol, Loc); OS << ".seh_proc "; Symbol->print(OS, MAI); EmitEOL(); } -void MCAsmStreamer::EmitWinCFIEndProc() { - MCStreamer::EmitWinCFIEndProc(); +void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) { + MCStreamer::EmitWinCFIEndProc(Loc); OS << "\t.seh_endproc"; EmitEOL(); } -void MCAsmStreamer::EmitWinCFIStartChained() { - MCStreamer::EmitWinCFIStartChained(); +void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) { + MCStreamer::EmitWinCFIStartChained(Loc); OS << "\t.seh_startchained"; EmitEOL(); } -void MCAsmStreamer::EmitWinCFIEndChained() { - MCStreamer::EmitWinCFIEndChained(); +void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) { + MCStreamer::EmitWinCFIEndChained(Loc); OS << "\t.seh_endchained"; EmitEOL(); } void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { - MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); + bool Except, SMLoc Loc) { + MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc); OS << "\t.seh_handler "; Sym->print(OS, MAI); @@ -1467,8 +1471,8 @@ void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, EmitEOL(); } -void MCAsmStreamer::EmitWinEHHandlerData() { - MCStreamer::EmitWinEHHandlerData(); +void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) { + MCStreamer::EmitWinEHHandlerData(Loc); // Switch sections. Don't call SwitchSection directly, because that will // cause the section switch to be visible in the emitted assembly. @@ -1483,43 +1487,46 @@ void MCAsmStreamer::EmitWinEHHandlerData() { EmitEOL(); } -void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { - MCStreamer::EmitWinCFIPushReg(Register); +void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) { + MCStreamer::EmitWinCFIPushReg(Register, Loc); OS << "\t.seh_pushreg " << Register; EmitEOL(); } -void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { - MCStreamer::EmitWinCFISetFrame(Register, Offset); +void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset, + SMLoc Loc) { + MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc); OS << "\t.seh_setframe " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { - MCStreamer::EmitWinCFIAllocStack(Size); +void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) { + MCStreamer::EmitWinCFIAllocStack(Size, Loc); OS << "\t.seh_stackalloc " << Size; EmitEOL(); } -void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { - MCStreamer::EmitWinCFISaveReg(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset, + SMLoc Loc) { + MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc); OS << "\t.seh_savereg " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { - MCStreamer::EmitWinCFISaveXMM(Register, Offset); +void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + SMLoc Loc) { + MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc); OS << "\t.seh_savexmm " << Register << ", " << Offset; EmitEOL(); } -void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { - MCStreamer::EmitWinCFIPushFrame(Code); +void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) { + MCStreamer::EmitWinCFIPushFrame(Code, Loc); OS << "\t.seh_pushframe"; if (Code) @@ -1527,8 +1534,8 @@ void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { EmitEOL(); } -void MCAsmStreamer::EmitWinCFIEndProlog() { - MCStreamer::EmitWinCFIEndProlog(); +void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) { + MCStreamer::EmitWinCFIEndProlog(Loc); OS << "\t.seh_endprologue"; EmitEOL(); diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index b83d68d4fe2..687e0cc1faa 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -568,7 +568,7 @@ bool COFFAsmParser::ParseDirectiveLinkOnce(StringRef, SMLoc Loc) { return false; } -bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc Loc) { StringRef SymbolID; if (getParser().parseIdentifier(SymbolID)) return true; @@ -579,29 +579,29 @@ bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWinCFIStartProc(Symbol); + getStreamer().EmitWinCFIStartProc(Symbol, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveEndProc(StringRef, SMLoc Loc) { Lex(); - getStreamer().EmitWinCFIEndProc(); + getStreamer().EmitWinCFIEndProc(Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveStartChained(StringRef, SMLoc Loc) { Lex(); - getStreamer().EmitWinCFIStartChained(); + getStreamer().EmitWinCFIStartChained(Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveEndChained(StringRef, SMLoc Loc) { Lex(); - getStreamer().EmitWinCFIEndChained(); + getStreamer().EmitWinCFIEndChained(Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc Loc) { StringRef SymbolID; if (getParser().parseIdentifier(SymbolID)) return true; @@ -623,17 +623,17 @@ bool COFFAsmParser::ParseSEHDirectiveHandler(StringRef, SMLoc) { MCSymbol *handler = getContext().getOrCreateSymbol(SymbolID); Lex(); - getStreamer().EmitWinEHHandler(handler, unwind, except); + getStreamer().EmitWinEHHandler(handler, unwind, except, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc Loc) { Lex(); getStreamer().EmitWinEHHandlerData(); return false; } -bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { +bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc Loc) { unsigned Reg = 0; if (ParseSEHRegisterNumber(Reg)) return true; @@ -642,11 +642,11 @@ bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWinCFIPushReg(Reg); + getStreamer().EmitWinCFIPushReg(Reg, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { +bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc Loc) { unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) @@ -655,39 +655,31 @@ bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { return TokError("you must specify a stack pointer offset"); Lex(); - SMLoc startLoc = getLexer().getLoc(); if (getParser().parseAbsoluteExpression(Off)) return true; - if (Off & 0x0F) - return Error(startLoc, "offset is not a multiple of 16"); - if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWinCFISetFrame(Reg, Off); + getStreamer().EmitWinCFISetFrame(Reg, Off, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc Loc) { int64_t Size; - SMLoc startLoc = getLexer().getLoc(); if (getParser().parseAbsoluteExpression(Size)) return true; - if (Size & 7) - return Error(startLoc, "size is not a multiple of 8"); - if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWinCFIAllocStack(Size); + getStreamer().EmitWinCFIAllocStack(Size, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { +bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc Loc) { unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) @@ -696,25 +688,21 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { return TokError("you must specify an offset on the stack"); Lex(); - SMLoc startLoc = getLexer().getLoc(); if (getParser().parseAbsoluteExpression(Off)) return true; - if (Off & 7) - return Error(startLoc, "size is not a multiple of 8"); - if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); Lex(); // FIXME: Err on %xmm* registers - getStreamer().EmitWinCFISaveReg(Reg, Off); + getStreamer().EmitWinCFISaveReg(Reg, Off, Loc); return false; } // FIXME: This method is inherently x86-specific. It should really be in the // x86 backend. -bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { +bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc Loc) { unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) @@ -723,23 +711,19 @@ bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { return TokError("you must specify an offset on the stack"); Lex(); - SMLoc startLoc = getLexer().getLoc(); if (getParser().parseAbsoluteExpression(Off)) return true; if (getLexer().isNot(AsmToken::EndOfStatement)) return TokError("unexpected token in directive"); - if (Off & 0x0F) - return Error(startLoc, "offset is not a multiple of 16"); - Lex(); // FIXME: Err on non-%xmm* registers - getStreamer().EmitWinCFISaveXMM(Reg, Off); + getStreamer().EmitWinCFISaveXMM(Reg, Off, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc Loc) { bool Code = false; StringRef CodeID; if (getLexer().is(AsmToken::At)) { @@ -756,13 +740,13 @@ bool COFFAsmParser::ParseSEHDirectivePushFrame(StringRef, SMLoc) { return TokError("unexpected token in directive"); Lex(); - getStreamer().EmitWinCFIPushFrame(Code); + getStreamer().EmitWinCFIPushFrame(Code, Loc); return false; } -bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc) { +bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) { Lex(); - getStreamer().EmitWinCFIEndProlog(); + getStreamer().EmitWinCFIEndProlog(Loc); return false; } diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 866bad9515e..d414c01fa16 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -516,20 +516,29 @@ void MCStreamer::EmitCFIReturnColumn(int64_t Register) { CurFrame->RAReg = Register; } -void MCStreamer::EnsureValidWinFrameInfo() { +WinEH::FrameInfo *MCStreamer::EnsureValidWinFrameInfo(SMLoc Loc) { const MCAsmInfo *MAI = Context.getAsmInfo(); - if (!MAI->usesWindowsCFI()) - report_fatal_error(".seh_* directives are not supported on this target"); - if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) - report_fatal_error("No open Win64 EH frame function!"); + if (!MAI->usesWindowsCFI()) { + getContext().reportError( + Loc, ".seh_* directives are not supported on this target"); + return nullptr; + } + if (!CurrentWinFrameInfo || CurrentWinFrameInfo->End) { + getContext().reportError( + Loc, ".seh_ directive must appear within an active frame"); + return nullptr; + } + return CurrentWinFrameInfo; } -void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { +void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { const MCAsmInfo *MAI = Context.getAsmInfo(); if (!MAI->usesWindowsCFI()) - report_fatal_error(".seh_* directives are not supported on this target"); + return getContext().reportError( + Loc, ".seh_* directives are not supported on this target"); if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End) - report_fatal_error("Starting a function before ending the previous one!"); + getContext().reportError( + Loc, "Starting a function before ending the previous one!"); MCSymbol *StartProc = EmitCFILabel(); @@ -539,56 +548,67 @@ void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } -void MCStreamer::EmitWinCFIEndProc() { - EnsureValidWinFrameInfo(); - if (CurrentWinFrameInfo->ChainedParent) - report_fatal_error("Not all chained regions terminated!"); +void MCStreamer::EmitWinCFIEndProc(SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (CurFrame->ChainedParent) + getContext().reportError(Loc, "Not all chained regions terminated!"); MCSymbol *Label = EmitCFILabel(); - CurrentWinFrameInfo->End = Label; + CurFrame->End = Label; } -void MCStreamer::EmitWinCFIStartChained() { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFIStartChained(SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; MCSymbol *StartProc = EmitCFILabel(); WinFrameInfos.emplace_back(llvm::make_unique<WinEH::FrameInfo>( - CurrentWinFrameInfo->Function, StartProc, CurrentWinFrameInfo)); + CurFrame->Function, StartProc, CurFrame)); CurrentWinFrameInfo = WinFrameInfos.back().get(); CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } -void MCStreamer::EmitWinCFIEndChained() { - EnsureValidWinFrameInfo(); - if (!CurrentWinFrameInfo->ChainedParent) - report_fatal_error("End of a chained region outside a chained region!"); +void MCStreamer::EmitWinCFIEndChained(SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (!CurFrame->ChainedParent) + return getContext().reportError( + Loc, "End of a chained region outside a chained region!"); MCSymbol *Label = EmitCFILabel(); - CurrentWinFrameInfo->End = Label; - CurrentWinFrameInfo = - const_cast<WinEH::FrameInfo *>(CurrentWinFrameInfo->ChainedParent); + CurFrame->End = Label; + CurrentWinFrameInfo = const_cast<WinEH::FrameInfo *>(CurFrame->ChainedParent); } -void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, - bool Except) { - EnsureValidWinFrameInfo(); - if (CurrentWinFrameInfo->ChainedParent) - report_fatal_error("Chained unwind areas can't have handlers!"); - CurrentWinFrameInfo->ExceptionHandler = Sym; +void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, + SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (CurFrame->ChainedParent) + return getContext().reportError( + Loc, "Chained unwind areas can't have handlers!"); + CurFrame->ExceptionHandler = Sym; if (!Except && !Unwind) - report_fatal_error("Don't know what kind of handler this is!"); + getContext().reportError(Loc, "Don't know what kind of handler this is!"); if (Unwind) - CurrentWinFrameInfo->HandlesUnwind = true; + CurFrame->HandlesUnwind = true; if (Except) - CurrentWinFrameInfo->HandlesExceptions = true; + CurFrame->HandlesExceptions = true; } -void MCStreamer::EmitWinEHHandlerData() { - EnsureValidWinFrameInfo(); - if (CurrentWinFrameInfo->ChainedParent) - report_fatal_error("Chained unwind areas can't have handlers!"); +void MCStreamer::EmitWinEHHandlerData(SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (CurFrame->ChainedParent) + getContext().reportError(Loc, "Chained unwind areas can't have handlers!"); } static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID, @@ -625,86 +645,110 @@ MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) { void MCStreamer::EmitSyntaxDirective() {} -void MCStreamer::EmitWinCFIPushReg(unsigned Register) { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFIPushReg(unsigned Register, SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::PushNonVol(Label, Register); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { - EnsureValidWinFrameInfo(); - if (CurrentWinFrameInfo->LastFrameInst >= 0) - report_fatal_error("Frame register and offset already specified!"); +void MCStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset, + SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (CurFrame->LastFrameInst >= 0) + return getContext().reportError( + Loc, "frame register and offset can be set at most once"); if (Offset & 0x0F) - report_fatal_error("Misaligned frame pointer offset!"); + return getContext().reportError(Loc, "offset is not a multiple of 16"); if (Offset > 240) - report_fatal_error("Frame offset must be less than or equal to 240!"); + return getContext().reportError( + Loc, "frame offset must be less than or equal to 240"); MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::SetFPReg(Label, Register, Offset); - CurrentWinFrameInfo->LastFrameInst = CurrentWinFrameInfo->Instructions.size(); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->LastFrameInst = CurFrame->Instructions.size(); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFIAllocStack(unsigned Size) { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; if (Size == 0) - report_fatal_error("Allocation size must be non-zero!"); + return getContext().reportError(Loc, + "stack allocation size must be non-zero"); if (Size & 7) - report_fatal_error("Misaligned stack allocation!"); + return getContext().reportError( + Loc, "stack allocation size is not a multiple of 8"); MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::Alloc(Label, Size); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset, + SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (Offset & 7) - report_fatal_error("Misaligned saved register offset!"); + return getContext().reportError( + Loc, "register save offset is not 8 byte aligned"); MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::SaveNonVol(Label, Register, Offset); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset, + SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; if (Offset & 0x0F) - report_fatal_error("Misaligned saved vector register offset!"); + return getContext().reportError(Loc, "offset is not a multiple of 16"); MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::SaveXMM(Label, Register, Offset); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFIPushFrame(bool Code) { - EnsureValidWinFrameInfo(); - if (!CurrentWinFrameInfo->Instructions.empty()) - report_fatal_error("If present, PushMachFrame must be the first UOP"); +void MCStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; + if (!CurFrame->Instructions.empty()) + return getContext().reportError( + Loc, "If present, PushMachFrame must be the first UOP"); MCSymbol *Label = EmitCFILabel(); WinEH::Instruction Inst = Win64EH::Instruction::PushMachFrame(Label, Code); - CurrentWinFrameInfo->Instructions.push_back(Inst); + CurFrame->Instructions.push_back(Inst); } -void MCStreamer::EmitWinCFIEndProlog() { - EnsureValidWinFrameInfo(); +void MCStreamer::EmitWinCFIEndProlog(SMLoc Loc) { + WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc); + if (!CurFrame) + return; MCSymbol *Label = EmitCFILabel(); - CurrentWinFrameInfo->PrologEnd = Label; + CurFrame->PrologEnd = Label; } void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { @@ -734,9 +778,9 @@ void MCStreamer::EmitWindowsUnwindTables() { void MCStreamer::Finish() { if (!DwarfFrameInfos.empty() && !DwarfFrameInfos.back().End) - report_fatal_error("Unfinished frame!"); + getContext().reportError(SMLoc(), "Unfinished frame!"); if (!WinFrameInfos.empty() && !WinFrameInfos.back()->End) - report_fatal_error("Unfinished frame!"); + getContext().reportError(SMLoc(), "Unfinished frame!"); MCTargetStreamer *TS = getTargetStreamer(); if (TS) diff --git a/lib/MC/MCWinCOFFStreamer.cpp b/lib/MC/MCWinCOFFStreamer.cpp index bf341bb1f45..dddafb9691c 100644 --- a/lib/MC/MCWinCOFFStreamer.cpp +++ b/lib/MC/MCWinCOFFStreamer.cpp @@ -285,7 +285,7 @@ void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { llvm_unreachable("not implemented"); } -void MCWinCOFFStreamer::EmitWinEHHandlerData() { +void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) { llvm_unreachable("not implemented"); } diff --git a/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp b/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp index d04511873b4..cec0f9244c9 100644 --- a/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp +++ b/lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp @@ -21,13 +21,13 @@ public: raw_pwrite_stream &OS) : MCWinCOFFStreamer(C, AB, *CE, OS) {} - void EmitWinEHHandlerData() override; + void EmitWinEHHandlerData(SMLoc Loc) override; void EmitWindowsUnwindTables() override; void FinishImpl() override; }; -void X86WinCOFFStreamer::EmitWinEHHandlerData() { - MCStreamer::EmitWinEHHandlerData(); +void X86WinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) { + MCStreamer::EmitWinEHHandlerData(Loc); // We have to emit the unwind info now, because this directive // actually switches to the .xdata section! diff --git a/test/MC/AsmParser/seh-directive-errors.s b/test/MC/AsmParser/seh-directive-errors.s new file mode 100644 index 00000000000..5fa6c7846e7 --- /dev/null +++ b/test/MC/AsmParser/seh-directive-errors.s @@ -0,0 +1,96 @@ +# RUN: not llvm-mc %s -filetype=obj -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=error: + .text + + .seh_pushreg 6 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: .seh_ directive must appear within an active frame + + .seh_stackalloc 32 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: .seh_ directive must appear within an active frame + + .def f; + .scl 2; + .type 32; + .endef + .globl f # -- Begin function f + .p2align 4, 0x90 +f: # @f +.seh_proc f + pushq %rsi + .seh_pushreg 6 + pushq %rdi + .seh_pushreg 7 + pushq %rbx + .seh_pushreg 3 + subq $32, %rsp + .seh_stackalloc 0 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: stack allocation size must be non-zero + .seh_stackalloc 7 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: stack allocation size is not a multiple of 8 + .seh_stackalloc 32 + .seh_endprologue + nop + addq $32, %rsp + popq %rbx + popq %rdi + popq %rsi + retq + .seh_handlerdata + .text + .seh_endproc + + + .seh_pushreg 6 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: .seh_ directive must appear within an active frame + +g: + .seh_proc g + pushq %rbp + .seh_pushreg 3 + pushq %rsi + .seh_pushreg 6 + .seh_endprologue + .seh_setframe 3 255 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: you must specify a stack pointer offset + .seh_setframe 3, 255 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: offset is not a multiple of 16 + .seh_setframe 3, 256 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: frame offset must be less than or equal to 240 + .seh_setframe 3, 128 + .seh_setframe 3, 128 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: frame register and offset can be set at most once + nop + popq %rsi + popq %rbp + retq + .seh_endproc + + .globl h # -- Begin function h + .p2align 4, 0x90 +h: # @h +.seh_proc h +# BB#0: # %entry + subq $72, %rsp + .seh_stackalloc 72 + movaps %xmm7, 48(%rsp) # 16-byte Spill + .seh_savexmm 7 44 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: you must specify an offset on the stack + .seh_savexmm 7, 44 + # CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: offset is not a multiple of 16 + .seh_savexmm 7, 48 + movaps %xmm6, 32(%rsp) # 16-byte Spill + .seh_savexmm 6, 32 + .seh_endprologue + movapd %xmm0, %xmm6 + callq getdbl + movapd %xmm0, %xmm7 + addsd %xmm6, %xmm7 + callq getdbl + addsd %xmm7, %xmm0 + movaps 32(%rsp), %xmm6 # 16-byte Reload + movaps 48(%rsp), %xmm7 # 16-byte Reload + addq $72, %rsp + retq + .seh_handlerdata + .text + .seh_endproc + # -- End function diff --git a/test/MC/COFF/seh-stackalloc-zero.s b/test/MC/COFF/seh-stackalloc-zero.s index 898ac844417..c03af42131b 100644 --- a/test/MC/COFF/seh-stackalloc-zero.s +++ b/test/MC/COFF/seh-stackalloc-zero.s @@ -1,11 +1,10 @@ // RUN: not llvm-mc -triple x86_64-pc-win32 -filetype=obj %s -o %t.o 2>&1 | FileCheck %s -// CHECK: Allocation size must be non-zero! - .globl smallFunc .def smallFunc; .scl 2; .type 32; .endef .seh_proc smallFunc .seh_stackalloc 0 +// CHECK: :[[@LINE-1]]:{{[0-9]+}}: error: stack allocation size must be non-zero smallFunc: ret .seh_endproc