Skip to content

Commit 04d8928

Browse files
epilkslinder1
authored andcommitted
[MC][Dwarf] Add custom CFI pseudo-ops for use in AMDGPU
While these can be represented with .cfi_escape, using these pseudo-cfi instructions makes .s/.mir files more readable, and it is necessary to support updating registers in CFI instructions (something that the AMDGPU backend requires).
1 parent 6210fba commit 04d8928

File tree

18 files changed

+949
-1
lines changed

18 files changed

+949
-1
lines changed

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,10 @@ class MCCFIInstruction {
530530
OpGnuArgsSize,
531531
OpLabel,
532532
OpValOffset,
533+
OpLLVMRegisterPair,
534+
OpLLVMVectorRegisters,
535+
OpLLVMVectorOffset,
536+
OpLLVMVectorRegisterMask,
533537
};
534538

535539
// Held in ExtraFields for most common OpTypes, exceptions follow.
@@ -548,10 +552,45 @@ class MCCFIInstruction {
548552
struct LabelFields {
549553
MCSymbol *CfiLabel = nullptr;
550554
};
555+
/// Held in ExtraFields when OpLLVMRegisterPair.
556+
struct RegisterPairFields {
557+
unsigned Register;
558+
unsigned Reg1, Reg2;
559+
unsigned Reg1SizeInBits, Reg2SizeInBits;
560+
};
561+
struct VectorRegisterWithLane {
562+
unsigned Register;
563+
unsigned Lane;
564+
unsigned SizeInBits;
565+
};
566+
/// Held in ExtraFields when OpLLVMVectorRegisters.
567+
struct VectorRegistersFields {
568+
unsigned Register;
569+
std::vector<VectorRegisterWithLane> VectorRegisters;
570+
};
571+
/// Held in ExtraFields when OpLLVMVectorOffset.
572+
struct VectorOffsetFields {
573+
unsigned Register;
574+
unsigned RegisterSizeInBits;
575+
int64_t Offset;
576+
unsigned MaskRegister;
577+
unsigned MaskRegisterSizeInBits;
578+
};
579+
/// Held in ExtraFields when OpLLVMVectorRegisterMask.
580+
struct VectorRegisterMaskFields {
581+
unsigned Register;
582+
unsigned SpillRegister;
583+
unsigned SpillRegisterLaneSizeInBits;
584+
unsigned MaskRegister;
585+
unsigned MaskRegisterSizeInBits;
586+
};
551587

552588
private:
553589
MCSymbol *Label;
554-
std::variant<CommonFields, EscapeFields, LabelFields> ExtraFields;
590+
std::variant<CommonFields, EscapeFields, LabelFields, RegisterPairFields,
591+
VectorRegistersFields, VectorOffsetFields,
592+
VectorRegisterMaskFields>
593+
ExtraFields;
555594
OpType Operation;
556595
SMLoc Loc;
557596

@@ -694,6 +733,57 @@ class MCCFIInstruction {
694733
return {OpLabel, L, LabelFields{CfiLabel}, Loc};
695734
}
696735

736+
/// .cfi_llvm_register_pair Previous value of Register is saved in R1:R2.
737+
static MCCFIInstruction
738+
createLLVMRegisterPair(MCSymbol *L, unsigned Register, unsigned R1,
739+
unsigned R1SizeInBits, unsigned R2,
740+
unsigned R2SizeInBits, SMLoc Loc = {}) {
741+
RegisterPairFields Extra{Register, R1, R2, R1SizeInBits, R2SizeInBits};
742+
return {OpLLVMRegisterPair, L, Extra, Loc};
743+
}
744+
745+
/// .cfi_llvm_vector_registers Previous value of Register is saved in lanes of
746+
/// vector registers.
747+
static MCCFIInstruction
748+
createLLVMVectorRegisters(MCSymbol *L, unsigned Register,
749+
std::vector<VectorRegisterWithLane> VectorRegisters,
750+
SMLoc Loc = {}) {
751+
VectorRegistersFields Extra{Register, std::move(VectorRegisters)};
752+
return {OpLLVMVectorRegisters, L, std::move(Extra), Loc};
753+
}
754+
755+
/// .cfi_llvm_vector_offset Previous value of Register is saved at Offset from
756+
/// CFA. MaskRegister specifies the active lanes of register.
757+
static MCCFIInstruction
758+
createLLVMVectorOffset(MCSymbol *L, unsigned Register,
759+
unsigned RegisterSizeInBits, unsigned MaskRegister,
760+
unsigned MaskRegisterSizeInBits, int64_t Offset,
761+
SMLoc Loc = {}) {
762+
VectorOffsetFields Extra{Register, RegisterSizeInBits, Offset, MaskRegister,
763+
MaskRegisterSizeInBits};
764+
return MCCFIInstruction(OpLLVMVectorOffset, L, Extra, Loc);
765+
}
766+
767+
/// .cfi_llvm_vector_register_mask Previous value of Register is saved in
768+
/// SpillRegister, predicated on the value of MaskRegister.
769+
static MCCFIInstruction createLLVMVectorRegisterMask(
770+
MCSymbol *L, unsigned Register, unsigned SpillRegister,
771+
unsigned SpillRegisterLaneSizeInBits, unsigned MaskRegister,
772+
unsigned MaskRegisterSizeInBits, SMLoc Loc = {}) {
773+
VectorRegisterMaskFields Extra{
774+
Register, SpillRegister, SpillRegisterLaneSizeInBits,
775+
MaskRegister, MaskRegisterSizeInBits,
776+
};
777+
return MCCFIInstruction(OpLLVMVectorRegisterMask, L, Extra, Loc);
778+
}
779+
780+
template <class ExtraFieldsTy> ExtraFieldsTy &getExtraFields() {
781+
return std::get<ExtraFieldsTy>(ExtraFields);
782+
}
783+
784+
template <class ExtraFieldsTy> const ExtraFieldsTy &getExtraFields() const {
785+
return std::get<ExtraFieldsTy>(ExtraFields);
786+
}
697787
/// .cfi_val_offset Previous value of Register is offset Offset from the
698788
/// current CFA register.
699789
static MCCFIInstruction createValOffset(MCSymbol *L, unsigned Register,

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,24 @@ class LLVM_ABI MCStreamer {
10121012
SMLoc Loc = {});
10131013
virtual void emitCFIWindowSave(SMLoc Loc = {});
10141014
virtual void emitCFINegateRAState(SMLoc Loc = {});
1015+
virtual void emitCFILLVMRegisterPair(int64_t Register, int64_t R1,
1016+
int64_t R1SizeInBits, int64_t R2,
1017+
int64_t R2SizeInBits, SMLoc Loc = {});
1018+
virtual void emitCFILLVMVectorRegisters(
1019+
int64_t Register,
1020+
std::vector<MCCFIInstruction::VectorRegisterWithLane> VRs,
1021+
SMLoc Loc = {});
1022+
virtual void emitCFILLVMVectorOffset(int64_t Register,
1023+
int64_t RegisterSizeInBits,
1024+
int64_t MaskRegister,
1025+
int64_t MaskRegisterSizeInBits,
1026+
int64_t Offset, SMLoc Loc = {});
1027+
virtual void
1028+
emitCFILLVMVectorRegisterMask(int64_t Register, int64_t SpillRegister,
1029+
int64_t SpillRegisterLaneSizeInBits,
1030+
int64_t MaskRegister,
1031+
int64_t MaskRegisterSizeInBits, SMLoc Loc = {});
1032+
10151033
virtual void emitCFINegateRAStateWithPC(SMLoc Loc = {});
10161034
virtual void emitCFILabelDirective(SMLoc Loc, StringRef Name);
10171035
virtual void emitCFIValOffset(int64_t Register, int64_t Offset,

llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,39 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
260260
case MCCFIInstruction::OpRestoreState:
261261
OutStreamer->emitCFIRestoreState(Loc);
262262
break;
263+
case MCCFIInstruction::OpLLVMRegisterPair: {
264+
const auto &Fields =
265+
Inst.getExtraFields<MCCFIInstruction::RegisterPairFields>();
266+
OutStreamer->emitCFILLVMRegisterPair(Fields.Register, Fields.Reg1,
267+
Fields.Reg1SizeInBits, Fields.Reg2,
268+
Fields.Reg2SizeInBits, Loc);
269+
break;
270+
}
271+
case MCCFIInstruction::OpLLVMVectorRegisters: {
272+
const auto &Fields =
273+
Inst.getExtraFields<MCCFIInstruction::VectorRegistersFields>();
274+
OutStreamer->emitCFILLVMVectorRegisters(Fields.Register,
275+
Fields.VectorRegisters, Loc);
276+
break;
277+
}
278+
case MCCFIInstruction::OpLLVMVectorOffset: {
279+
const auto &Fields =
280+
Inst.getExtraFields<MCCFIInstruction::VectorOffsetFields>();
281+
OutStreamer->emitCFILLVMVectorOffset(
282+
Fields.Register, Fields.RegisterSizeInBits, Fields.MaskRegister,
283+
Fields.MaskRegisterSizeInBits, Fields.Offset, Loc);
284+
break;
285+
}
286+
case MCCFIInstruction::OpLLVMVectorRegisterMask: {
287+
const auto &Fields =
288+
Inst.getExtraFields<MCCFIInstruction::VectorRegisterMaskFields>();
289+
OutStreamer->emitCFILLVMVectorRegisterMask(
290+
Fields.Register, Fields.SpillRegister,
291+
Fields.SpillRegisterLaneSizeInBits, Fields.MaskRegister,
292+
Fields.MaskRegisterSizeInBits);
293+
break;
294+
}
295+
263296
case MCCFIInstruction::OpValOffset:
264297
OutStreamer->emitCFIValOffset(Inst.getRegister(), Inst.getOffset(), Loc);
265298
break;

llvm/lib/CodeGen/CFIInstrInserter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,10 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
262262
case MCCFIInstruction::OpNegateRAState:
263263
case MCCFIInstruction::OpNegateRAStateWithPC:
264264
case MCCFIInstruction::OpGnuArgsSize:
265+
case MCCFIInstruction::OpLLVMRegisterPair:
266+
case MCCFIInstruction::OpLLVMVectorRegisters:
267+
case MCCFIInstruction::OpLLVMVectorOffset:
268+
case MCCFIInstruction::OpLLVMVectorRegisterMask:
265269
case MCCFIInstruction::OpLabel:
266270
case MCCFIInstruction::OpValOffset:
267271
break;

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,11 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
240240
.Case("window_save", MIToken::kw_cfi_window_save)
241241
.Case("negate_ra_sign_state",
242242
MIToken::kw_cfi_aarch64_negate_ra_sign_state)
243+
.Case("llvm_register_pair", MIToken::kw_cfi_llvm_register_pair)
244+
.Case("llvm_vector_registers", MIToken::kw_cfi_llvm_vector_registers)
245+
.Case("llvm_vector_offset", MIToken::kw_cfi_llvm_vector_offset)
246+
.Case("llvm_vector_register_mask",
247+
MIToken::kw_cfi_llvm_vector_register_mask)
243248
.Case("negate_ra_sign_state_with_pc",
244249
MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc)
245250
.Case("blockaddress", MIToken::kw_blockaddress)

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ struct MIToken {
9898
kw_cfi_undefined,
9999
kw_cfi_window_save,
100100
kw_cfi_aarch64_negate_ra_sign_state,
101+
kw_cfi_llvm_register_pair,
102+
kw_cfi_llvm_vector_registers,
103+
kw_cfi_llvm_vector_offset,
104+
kw_cfi_llvm_vector_register_mask,
101105
kw_cfi_aarch64_negate_ra_sign_state_with_pc,
102106
kw_blockaddress,
103107
kw_intrinsic,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ class MIParser {
484484
bool parseDILocation(MDNode *&Expr);
485485
bool parseMetadataOperand(MachineOperand &Dest);
486486
bool parseCFIOffset(int &Offset);
487+
bool parseCFIUnsigned(unsigned &Value);
487488
bool parseCFIRegister(unsigned &Reg);
488489
bool parseCFIAddressSpace(unsigned &AddressSpace);
489490
bool parseCFIEscapeValues(std::string& Values);
@@ -2477,6 +2478,13 @@ bool MIParser::parseCFIOffset(int &Offset) {
24772478
return false;
24782479
}
24792480

2481+
bool MIParser::parseCFIUnsigned(unsigned &Value) {
2482+
if (getUnsigned(Value))
2483+
return true;
2484+
lex();
2485+
return false;
2486+
}
2487+
24802488
bool MIParser::parseCFIRegister(unsigned &Reg) {
24812489
if (Token.isNot(MIToken::NamedRegister))
24822490
return error("expected a cfi register");
@@ -2610,6 +2618,69 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
26102618
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
26112619
CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
26122620
break;
2621+
case MIToken::kw_cfi_llvm_register_pair: {
2622+
unsigned Reg, R1, R2;
2623+
unsigned R1Size, R2Size;
2624+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2625+
parseCFIRegister(R1) || expectAndConsume(MIToken::comma) ||
2626+
parseCFIUnsigned(R1Size) || expectAndConsume(MIToken::comma) ||
2627+
parseCFIRegister(R2) || expectAndConsume(MIToken::comma) ||
2628+
parseCFIUnsigned(R2Size))
2629+
return true;
2630+
2631+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMRegisterPair(
2632+
nullptr, Reg, R1, R1Size, R2, R2Size));
2633+
break;
2634+
}
2635+
case MIToken::kw_cfi_llvm_vector_registers: {
2636+
std::vector<MCCFIInstruction::VectorRegisterWithLane> VectorRegisters;
2637+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma))
2638+
return true;
2639+
do {
2640+
unsigned VR;
2641+
unsigned Lane, Size;
2642+
if (parseCFIRegister(VR) || expectAndConsume(MIToken::comma) ||
2643+
parseCFIUnsigned(Lane) || expectAndConsume(MIToken::comma) ||
2644+
parseCFIUnsigned(Size))
2645+
return true;
2646+
VectorRegisters.push_back({VR, Lane, Size});
2647+
} while (consumeIfPresent(MIToken::comma));
2648+
2649+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorRegisters(
2650+
nullptr, Reg, std::move(VectorRegisters)));
2651+
break;
2652+
}
2653+
case MIToken::kw_cfi_llvm_vector_offset: {
2654+
unsigned Reg, MaskReg;
2655+
unsigned RegSize, MaskRegSize;
2656+
int Offset = 0;
2657+
2658+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2659+
parseCFIUnsigned(RegSize) || expectAndConsume(MIToken::comma) ||
2660+
parseCFIRegister(MaskReg) || expectAndConsume(MIToken::comma) ||
2661+
parseCFIUnsigned(MaskRegSize) || expectAndConsume(MIToken::comma) ||
2662+
parseCFIOffset(Offset))
2663+
return true;
2664+
2665+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorOffset(
2666+
nullptr, Reg, RegSize, MaskReg, MaskRegSize, Offset));
2667+
break;
2668+
}
2669+
case MIToken::kw_cfi_llvm_vector_register_mask: {
2670+
unsigned Reg, SpillReg, MaskReg;
2671+
unsigned SpillRegLaneSize, MaskRegSize;
2672+
2673+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2674+
parseCFIRegister(SpillReg) || expectAndConsume(MIToken::comma) ||
2675+
parseCFIUnsigned(SpillRegLaneSize) ||
2676+
expectAndConsume(MIToken::comma) || parseCFIRegister(MaskReg) ||
2677+
expectAndConsume(MIToken::comma) || parseCFIUnsigned(MaskRegSize))
2678+
return true;
2679+
2680+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorRegisterMask(
2681+
nullptr, Reg, SpillReg, SpillRegLaneSize, MaskReg, MaskRegSize));
2682+
break;
2683+
}
26132684
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
26142685
CFIIndex =
26152686
MF.addFrameInst(MCCFIInstruction::createNegateRAStateWithPC(nullptr));
@@ -2967,6 +3038,10 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
29673038
case MIToken::kw_cfi_undefined:
29683039
case MIToken::kw_cfi_window_save:
29693040
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
3041+
case MIToken::kw_cfi_llvm_register_pair:
3042+
case MIToken::kw_cfi_llvm_vector_registers:
3043+
case MIToken::kw_cfi_llvm_vector_offset:
3044+
case MIToken::kw_cfi_llvm_vector_register_mask:
29703045
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
29713046
return parseCFIOperand(Dest);
29723047
case MIToken::kw_blockaddress:

llvm/lib/CodeGen/MachineOperand.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,64 @@ static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI,
780780
if (MCSymbol *Label = CFI.getLabel())
781781
MachineOperand::printSymbol(OS, *Label);
782782
break;
783+
case MCCFIInstruction::OpLLVMRegisterPair: {
784+
const auto &Fields =
785+
CFI.getExtraFields<MCCFIInstruction::RegisterPairFields>();
786+
787+
OS << "llvm_register_pair ";
788+
if (MCSymbol *Label = CFI.getLabel())
789+
MachineOperand::printSymbol(OS, *Label);
790+
printCFIRegister(Fields.Register, OS, TRI);
791+
OS << ", ";
792+
printCFIRegister(Fields.Reg1, OS, TRI);
793+
OS << ", " << Fields.Reg1SizeInBits << ", ";
794+
printCFIRegister(Fields.Reg2, OS, TRI);
795+
OS << ", " << Fields.Reg2SizeInBits;
796+
break;
797+
}
798+
case MCCFIInstruction::OpLLVMVectorRegisters: {
799+
const auto &Fields =
800+
CFI.getExtraFields<MCCFIInstruction::VectorRegistersFields>();
801+
802+
OS << "llvm_vector_registers ";
803+
if (MCSymbol *Label = CFI.getLabel())
804+
MachineOperand::printSymbol(OS, *Label);
805+
printCFIRegister(Fields.Register, OS, TRI);
806+
for (auto [Reg, Lane, Size] : Fields.VectorRegisters) {
807+
OS << ", ";
808+
printCFIRegister(Reg, OS, TRI);
809+
OS << ", " << Lane << ", " << Size;
810+
}
811+
break;
812+
}
813+
case MCCFIInstruction::OpLLVMVectorOffset: {
814+
const auto &Fields =
815+
CFI.getExtraFields<MCCFIInstruction::VectorOffsetFields>();
816+
817+
OS << "llvm_vector_offset ";
818+
if (MCSymbol *Label = CFI.getLabel())
819+
MachineOperand::printSymbol(OS, *Label);
820+
printCFIRegister(Fields.Register, OS, TRI);
821+
OS << ", " << Fields.RegisterSizeInBits << ", ";
822+
printCFIRegister(Fields.MaskRegister, OS, TRI);
823+
OS << ", " << Fields.MaskRegisterSizeInBits << ", " << Fields.Offset;
824+
break;
825+
}
826+
case MCCFIInstruction::OpLLVMVectorRegisterMask: {
827+
const auto &Fields =
828+
CFI.getExtraFields<MCCFIInstruction::VectorRegisterMaskFields>();
829+
830+
OS << "llvm_vector_register_mask ";
831+
if (MCSymbol *Label = CFI.getLabel())
832+
MachineOperand::printSymbol(OS, *Label);
833+
printCFIRegister(Fields.Register, OS, TRI);
834+
OS << ", ";
835+
printCFIRegister(Fields.SpillRegister, OS, TRI);
836+
OS << ", " << Fields.SpillRegisterLaneSizeInBits << ", ";
837+
printCFIRegister(Fields.MaskRegister, OS, TRI);
838+
OS << ", " << Fields.MaskRegisterSizeInBits;
839+
break;
840+
}
783841
case MCCFIInstruction::OpNegateRAStateWithPC:
784842
OS << "negate_ra_sign_state_with_pc ";
785843
if (MCSymbol *Label = CFI.getLabel())

llvm/lib/DWARFCFIChecker/DWARFCFIState.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ dwarf::CFIProgram DWARFCFIState::convert(MCCFIInstruction Directive) {
160160
CFIP.addInstruction(dwarf::DW_CFA_val_offset, Directive.getRegister(),
161161
Directive.getOffset());
162162
break;
163+
case MCCFIInstruction::OpLLVMRegisterPair:
164+
case MCCFIInstruction::OpLLVMVectorRegisters:
165+
case MCCFIInstruction::OpLLVMVectorOffset:
166+
case MCCFIInstruction::OpLLVMVectorRegisterMask:
167+
// TODO: These should be pretty straightforward to support, but is low
168+
// priority. Similarly the implementation of OpLLVMDefAspaceCfa above
169+
// seem incomplete and should be fixed.
170+
Context->reportWarning(Directive.getLoc(),
171+
"this directive is not supported, ignoring it");
172+
break;
163173
}
164174

165175
return CFIP;

0 commit comments

Comments
 (0)