@@ -22,8 +22,7 @@ class MCSection;
2222
2323// / MCExpr that represents the epilog unwind code in an unwind table.
2424class MCUnwindV2EpilogTargetExpr final : public MCTargetExpr {
25- const MCSymbol *Function;
26- const MCSymbol *FunctionEnd;
25+ const WinEH::FrameInfo &FrameInfo;
2726 const MCSymbol *UnwindV2Start;
2827 const MCSymbol *EpilogEnd;
2928 uint8_t EpilogSize;
@@ -32,9 +31,11 @@ class MCUnwindV2EpilogTargetExpr final : public MCTargetExpr {
3231 MCUnwindV2EpilogTargetExpr (const WinEH::FrameInfo &FrameInfo,
3332 const WinEH::FrameInfo::Epilog &Epilog,
3433 uint8_t EpilogSize_)
35- : Function(FrameInfo.Function), FunctionEnd(FrameInfo.FuncletOrFuncEnd),
36- UnwindV2Start (Epilog.UnwindV2Start), EpilogEnd(Epilog.End),
37- EpilogSize(EpilogSize_), Loc(Epilog.Loc) {}
34+ : FrameInfo(FrameInfo), UnwindV2Start(Epilog.UnwindV2Start),
35+ EpilogEnd (Epilog.End), EpilogSize(EpilogSize_), Loc(Epilog.Loc) {
36+ assert (UnwindV2Start && " Epilog must have a start" );
37+ assert (EpilogEnd && " Epilog must have an end" );
38+ }
3839
3940public:
4041 static MCUnwindV2EpilogTargetExpr *
@@ -250,6 +251,10 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
250251 // so, although there are terminators that are large than 1 byte, the
251252 // starting address of the terminator instruction will always be considered
252253 // inside the epilog).
254+ assert (
255+ LastEpilog.UnwindV2Start &&
256+ " If unwind v2 is enabled, epilog must have a unwind v2 start marker" );
257+ assert (LastEpilog.End && " Epilog must have an end" );
253258 auto MaybeSize = GetOptionalAbsDifference (
254259 OS->getAssembler (), LastEpilog.End , LastEpilog.UnwindV2Start );
255260 if (!MaybeSize) {
@@ -270,9 +275,14 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
270275 // If the last epilog is at the end of the function, we can use a special
271276 // encoding for it. Because of our +1 trick for the size, this will only
272277 // work where that final terminator instruction is 1 byte long.
273- auto LastEpilogToFuncEnd = GetOptionalAbsDifference (
274- OS->getAssembler (), info->FuncletOrFuncEnd , LastEpilog.UnwindV2Start );
275- LastEpilogIsAtEnd = (LastEpilogToFuncEnd == EpilogSize);
278+ // NOTE: At the point where the unwind info is emitted, the function may not
279+ // have ended yet (e.g., if there is EH Handler Data), so assume that we
280+ // aren't at the end (since we can't calculate it).
281+ if (info->End ) {
282+ auto LastEpilogToFuncEnd = GetOptionalAbsDifference (
283+ OS->getAssembler (), info->End , LastEpilog.UnwindV2Start );
284+ LastEpilogIsAtEnd = (LastEpilogToFuncEnd == EpilogSize);
285+ }
276286
277287 // If we have an odd number of epilog codes, we need to add a padding code.
278288 size_t numEpilogCodes =
@@ -384,28 +394,28 @@ bool MCUnwindV2EpilogTargetExpr::evaluateAsRelocatableImpl(
384394 MCValue &Res, const MCAssembler *Asm) const {
385395 // Calculate the offset to this epilog, and validate it's within the allowed
386396 // range.
387- auto Offset = GetOptionalAbsDifference (*Asm, FunctionEnd , UnwindV2Start);
397+ auto Offset = GetOptionalAbsDifference (*Asm, FrameInfo. End , UnwindV2Start);
388398 if (!Offset) {
389399 Asm->getContext ().reportError (
390400 Loc, " Failed to evaluate epilog offset for Unwind v2 in " +
391- Function->getName ());
401+ FrameInfo. Function ->getName ());
392402 return false ;
393403 }
394404 assert (*Offset > 0 );
395405 constexpr uint16_t MaxEpilogOffset = 0x0fff ;
396406 if (*Offset > MaxEpilogOffset) {
397407 Asm->getContext ().reportError (
398- Loc,
399- " Epilog offset is too large for Unwind v2 in " + Function->getName ());
408+ Loc, " Epilog offset is too large for Unwind v2 in " +
409+ FrameInfo. Function ->getName ());
400410 return false ;
401411 }
402412
403- // Sanity check that all epilogs are the same size.
413+ // Validate that all epilogs are the same size.
404414 auto Size = GetOptionalAbsDifference (*Asm, EpilogEnd, UnwindV2Start);
405415 if (Size != (EpilogSize - 1 )) {
406416 Asm->getContext ().reportError (
407417 Loc, " Size of this epilog does not match size of last epilog in " +
408- Function->getName ());
418+ FrameInfo. Function ->getName ());
409419 return false ;
410420 }
411421
0 commit comments