2929#include < optional>
3030#include < string>
3131#include < utility>
32+ #include < variant>
3233#include < vector>
3334
3435namespace llvm {
@@ -531,83 +532,63 @@ class MCCFIInstruction {
531532 OpValOffset,
532533 };
533534
535+ // Held in ExtraFields for most common OpTypes, exceptions follow.
536+ struct CommonFields {
537+ unsigned Register = std::numeric_limits<unsigned >::max();
538+ int64_t Offset = 0 ;
539+ unsigned Register2 = std::numeric_limits<unsigned >::max();
540+ unsigned AddressSpace = 0 ;
541+ };
542+ // Held in ExtraFields when OpEscape.
543+ struct EscapeFields {
544+ std::vector<char > Values;
545+ std::string Comment;
546+ };
547+ // Held in ExtraFields when OpLabel.
548+ struct LabelFields {
549+ MCSymbol *CfiLabel = nullptr ;
550+ };
551+
534552private:
535553 MCSymbol *Label;
536- union {
537- struct {
538- unsigned Register;
539- int64_t Offset;
540- } RI;
541- struct {
542- unsigned Register;
543- int64_t Offset;
544- unsigned AddressSpace;
545- } RIA;
546- struct {
547- unsigned Register;
548- unsigned Register2;
549- } RR;
550- MCSymbol *CfiLabel;
551- } U;
554+ std::variant<CommonFields, EscapeFields, LabelFields> ExtraFields;
552555 OpType Operation;
553556 SMLoc Loc;
554- std::vector<char > Values;
555- std::string Comment;
556557
557- MCCFIInstruction (OpType Op, MCSymbol *L, unsigned R, int64_t O, SMLoc Loc,
558- StringRef V = " " , StringRef Comment = " " )
559- : Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
560- Comment (Comment) {
561- assert (Op != OpRegister && Op != OpLLVMDefAspaceCfa);
562- U.RI = {R, O};
563- }
564- MCCFIInstruction (OpType Op, MCSymbol *L, unsigned R1, unsigned R2, SMLoc Loc)
565- : Label(L), Operation(Op), Loc(Loc) {
566- assert (Op == OpRegister);
567- U.RR = {R1, R2};
568- }
569- MCCFIInstruction (OpType Op, MCSymbol *L, unsigned R, int64_t O, unsigned AS,
570- SMLoc Loc)
571- : Label(L), Operation(Op), Loc(Loc) {
572- assert (Op == OpLLVMDefAspaceCfa);
573- U.RIA = {R, O, AS};
574- }
575-
576- MCCFIInstruction (OpType Op, MCSymbol *L, MCSymbol *CfiLabel, SMLoc Loc)
577- : Label(L), Operation(Op), Loc(Loc) {
578- assert (Op == OpLabel);
579- U.CfiLabel = CfiLabel;
580- }
558+ template <class FieldsType >
559+ MCCFIInstruction (OpType Op, MCSymbol *L, FieldsType &&EF, SMLoc Loc)
560+ : Label(L), ExtraFields(std::forward<FieldsType>(EF)), Operation(Op),
561+ Loc(Loc) {}
581562
582563public:
583564 // / .cfi_def_cfa defines a rule for computing CFA as: take address from
584565 // / Register and add Offset to it.
585566 static MCCFIInstruction cfiDefCfa (MCSymbol *L, unsigned Register,
586567 int64_t Offset, SMLoc Loc = {}) {
587- return MCCFIInstruction ( OpDefCfa, L, Register, Offset, Loc) ;
568+ return { OpDefCfa, L, CommonFields{ Register, Offset} , Loc} ;
588569 }
589570
590571 // / .cfi_def_cfa_register modifies a rule for computing CFA. From now
591572 // / on Register will be used instead of the old one. Offset remains the same.
592573 static MCCFIInstruction createDefCfaRegister (MCSymbol *L, unsigned Register,
593574 SMLoc Loc = {}) {
594- return MCCFIInstruction ( OpDefCfaRegister, L, Register, INT64_C ( 0 ), Loc) ;
575+ return { OpDefCfaRegister, L, CommonFields{ Register}, Loc} ;
595576 }
596577
597578 // / .cfi_def_cfa_offset modifies a rule for computing CFA. Register
598579 // / remains the same, but offset is new. Note that it is the absolute offset
599580 // / that will be added to a defined register to the compute CFA address.
600581 static MCCFIInstruction cfiDefCfaOffset (MCSymbol *L, int64_t Offset,
601582 SMLoc Loc = {}) {
602- return MCCFIInstruction ( OpDefCfaOffset, L, 0 , Offset, Loc) ;
583+ return { OpDefCfaOffset, L, CommonFields{ 0 , Offset} , Loc} ;
603584 }
604585
605586 // / .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
606587 // / Offset is a relative value that is added/subtracted from the previous
607588 // / offset.
608589 static MCCFIInstruction createAdjustCfaOffset (MCSymbol *L, int64_t Adjustment,
609590 SMLoc Loc = {}) {
610- return MCCFIInstruction ( OpAdjustCfaOffset, L, 0 , Adjustment, Loc) ;
591+ return { OpAdjustCfaOffset, L, CommonFields{ 0 , Adjustment} , Loc} ;
611592 }
612593
613594 // FIXME: Update the remaining docs to use the new proposal wording.
@@ -618,151 +599,153 @@ class MCCFIInstruction {
618599 int64_t Offset,
619600 unsigned AddressSpace,
620601 SMLoc Loc) {
621- return MCCFIInstruction ( OpLLVMDefAspaceCfa, L, Register, Offset ,
622- AddressSpace, Loc) ;
602+ return { OpLLVMDefAspaceCfa, L,
603+ CommonFields{Register, Offset, 0 , AddressSpace} , Loc} ;
623604 }
624605
625606 // / .cfi_offset Previous value of Register is saved at offset Offset
626607 // / from CFA.
627608 static MCCFIInstruction createOffset (MCSymbol *L, unsigned Register,
628609 int64_t Offset, SMLoc Loc = {}) {
629- return MCCFIInstruction ( OpOffset, L, Register, Offset, Loc) ;
610+ return { OpOffset, L, CommonFields{ Register, Offset} , Loc} ;
630611 }
631612
632613 // / .cfi_rel_offset Previous value of Register is saved at offset
633614 // / Offset from the current CFA register. This is transformed to .cfi_offset
634615 // / using the known displacement of the CFA register from the CFA.
635616 static MCCFIInstruction createRelOffset (MCSymbol *L, unsigned Register,
636617 int64_t Offset, SMLoc Loc = {}) {
637- return MCCFIInstruction ( OpRelOffset, L, Register, Offset, Loc) ;
618+ return { OpRelOffset, L, CommonFields{ Register, Offset} , Loc} ;
638619 }
639620
640621 // / .cfi_register Previous value of Register1 is saved in
641622 // / register Register2.
642623 static MCCFIInstruction createRegister (MCSymbol *L, unsigned Register1,
643624 unsigned Register2, SMLoc Loc = {}) {
644- return MCCFIInstruction ( OpRegister, L, Register1, Register2, Loc) ;
625+ return { OpRegister, L, CommonFields{ Register1, 0 , Register2} , Loc} ;
645626 }
646627
647628 // / .cfi_window_save SPARC register window is saved.
648629 static MCCFIInstruction createWindowSave (MCSymbol *L, SMLoc Loc = {}) {
649- return MCCFIInstruction ( OpWindowSave, L, 0 , INT64_C ( 0 ), Loc) ;
630+ return { OpWindowSave, L, CommonFields{}, Loc} ;
650631 }
651632
652633 // / .cfi_negate_ra_state AArch64 negate RA state.
653634 static MCCFIInstruction createNegateRAState (MCSymbol *L, SMLoc Loc = {}) {
654- return MCCFIInstruction ( OpNegateRAState, L, 0 , INT64_C ( 0 ), Loc) ;
635+ return { OpNegateRAState, L, CommonFields{}, Loc} ;
655636 }
656637
657638 // / .cfi_negate_ra_state_with_pc AArch64 negate RA state with PC.
658639 static MCCFIInstruction createNegateRAStateWithPC (MCSymbol *L,
659640 SMLoc Loc = {}) {
660- return MCCFIInstruction ( OpNegateRAStateWithPC, L, 0 , INT64_C ( 0 ), Loc) ;
641+ return { OpNegateRAStateWithPC, L, CommonFields{}, Loc} ;
661642 }
662643
663644 // / .cfi_restore says that the rule for Register is now the same as it
664645 // / was at the beginning of the function, after all initial instructions added
665646 // / by .cfi_startproc were executed.
666647 static MCCFIInstruction createRestore (MCSymbol *L, unsigned Register,
667648 SMLoc Loc = {}) {
668- return MCCFIInstruction ( OpRestore, L, Register, INT64_C ( 0 ), Loc) ;
649+ return { OpRestore, L, CommonFields{ Register}, Loc} ;
669650 }
670651
671652 // / .cfi_undefined From now on the previous value of Register can't be
672653 // / restored anymore.
673654 static MCCFIInstruction createUndefined (MCSymbol *L, unsigned Register,
674655 SMLoc Loc = {}) {
675- return MCCFIInstruction ( OpUndefined, L, Register, INT64_C ( 0 ), Loc) ;
656+ return { OpUndefined, L, CommonFields{ Register}, Loc} ;
676657 }
677658
678659 // / .cfi_same_value Current value of Register is the same as in the
679660 // / previous frame. I.e., no restoration is needed.
680661 static MCCFIInstruction createSameValue (MCSymbol *L, unsigned Register,
681662 SMLoc Loc = {}) {
682- return MCCFIInstruction ( OpSameValue, L, Register, INT64_C ( 0 ), Loc) ;
663+ return { OpSameValue, L, CommonFields{ Register}, Loc} ;
683664 }
684665
685666 // / .cfi_remember_state Save all current rules for all registers.
686667 static MCCFIInstruction createRememberState (MCSymbol *L, SMLoc Loc = {}) {
687- return MCCFIInstruction ( OpRememberState, L, 0 , INT64_C ( 0 ), Loc) ;
668+ return { OpRememberState, L, CommonFields{}, Loc} ;
688669 }
689670
690671 // / .cfi_restore_state Restore the previously saved state.
691672 static MCCFIInstruction createRestoreState (MCSymbol *L, SMLoc Loc = {}) {
692- return MCCFIInstruction ( OpRestoreState, L, 0 , INT64_C ( 0 ), Loc) ;
673+ return { OpRestoreState, L, CommonFields{}, Loc} ;
693674 }
694675
695676 // / .cfi_escape Allows the user to add arbitrary bytes to the unwind
696677 // / info.
697678 static MCCFIInstruction createEscape (MCSymbol *L, StringRef Vals,
698679 SMLoc Loc = {}, StringRef Comment = " " ) {
699- return MCCFIInstruction (OpEscape, L, 0 , 0 , Loc, Vals, Comment);
680+ return {OpEscape, L,
681+ EscapeFields{std::vector<char >(Vals.begin (), Vals.end ()),
682+ Comment.str ()},
683+ Loc};
700684 }
701685
702686 // / A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
703687 static MCCFIInstruction createGnuArgsSize (MCSymbol *L, int64_t Size,
704688 SMLoc Loc = {}) {
705- return MCCFIInstruction ( OpGnuArgsSize, L, 0 , Size, Loc) ;
689+ return { OpGnuArgsSize, L, CommonFields{ 0 , Size} , Loc} ;
706690 }
707691
708692 static MCCFIInstruction createLabel (MCSymbol *L, MCSymbol *CfiLabel,
709693 SMLoc Loc) {
710- return MCCFIInstruction ( OpLabel, L, CfiLabel, Loc) ;
694+ return { OpLabel, L, LabelFields{ CfiLabel} , Loc} ;
711695 }
712696
713697 // / .cfi_val_offset Previous value of Register is offset Offset from the
714698 // / current CFA register.
715699 static MCCFIInstruction createValOffset (MCSymbol *L, unsigned Register,
716700 int64_t Offset, SMLoc Loc = {}) {
717- return MCCFIInstruction ( OpValOffset, L, Register, Offset, Loc) ;
701+ return { OpValOffset, L, CommonFields{ Register, Offset} , Loc} ;
718702 }
719703
720704 OpType getOperation () const { return Operation; }
721705 MCSymbol *getLabel () const { return Label; }
722706
723707 unsigned getRegister () const {
724- if (Operation == OpRegister)
725- return U.RR .Register ;
726- if (Operation == OpLLVMDefAspaceCfa)
727- return U.RIA .Register ;
728708 assert (Operation == OpDefCfa || Operation == OpOffset ||
729709 Operation == OpRestore || Operation == OpUndefined ||
730710 Operation == OpSameValue || Operation == OpDefCfaRegister ||
731- Operation == OpRelOffset || Operation == OpValOffset);
732- return U.RI .Register ;
711+ Operation == OpRelOffset || Operation == OpValOffset ||
712+ Operation == OpRegister || Operation == OpLLVMDefAspaceCfa);
713+ return std::get<CommonFields>(ExtraFields).Register ;
733714 }
734715
735716 unsigned getRegister2 () const {
736717 assert (Operation == OpRegister);
737- return U. RR .Register2 ;
718+ return std::get<CommonFields>(ExtraFields) .Register2 ;
738719 }
739720
740721 unsigned getAddressSpace () const {
741722 assert (Operation == OpLLVMDefAspaceCfa);
742- return U. RIA .AddressSpace ;
723+ return std::get<CommonFields>(ExtraFields) .AddressSpace ;
743724 }
744725
745726 int64_t getOffset () const {
746- if (Operation == OpLLVMDefAspaceCfa)
747- return U.RIA .Offset ;
748727 assert (Operation == OpDefCfa || Operation == OpOffset ||
749728 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
750729 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
751- Operation == OpValOffset);
752- return U. RI .Offset ;
730+ Operation == OpValOffset || Operation == OpLLVMDefAspaceCfa );
731+ return std::get<CommonFields>(ExtraFields) .Offset ;
753732 }
754733
755734 MCSymbol *getCfiLabel () const {
756735 assert (Operation == OpLabel);
757- return U .CfiLabel ;
736+ return std::get<LabelFields>(ExtraFields) .CfiLabel ;
758737 }
759738
760739 StringRef getValues () const {
761740 assert (Operation == OpEscape);
741+ auto &Values = std::get<EscapeFields>(ExtraFields).Values ;
762742 return StringRef (&Values[0 ], Values.size ());
763743 }
764744
765- StringRef getComment () const { return Comment; }
745+ StringRef getComment () const {
746+ assert (Operation == OpEscape);
747+ return std::get<EscapeFields>(ExtraFields).Comment ;
748+ }
766749 SMLoc getLoc () const { return Loc; }
767750};
768751
0 commit comments