Skip to content

Commit b3d52d3

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 15a73c6 commit b3d52d3

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);
@@ -2475,6 +2476,13 @@ bool MIParser::parseCFIOffset(int &Offset) {
24752476
return false;
24762477
}
24772478

2479+
bool MIParser::parseCFIUnsigned(unsigned &Value) {
2480+
if (getUnsigned(Value))
2481+
return true;
2482+
lex();
2483+
return false;
2484+
}
2485+
24782486
bool MIParser::parseCFIRegister(unsigned &Reg) {
24792487
if (Token.isNot(MIToken::NamedRegister))
24802488
return error("expected a cfi register");
@@ -2608,6 +2616,69 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
26082616
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
26092617
CFIIndex = MF.addFrameInst(MCCFIInstruction::createNegateRAState(nullptr));
26102618
break;
2619+
case MIToken::kw_cfi_llvm_register_pair: {
2620+
unsigned Reg, R1, R2;
2621+
unsigned R1Size, R2Size;
2622+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2623+
parseCFIRegister(R1) || expectAndConsume(MIToken::comma) ||
2624+
parseCFIUnsigned(R1Size) || expectAndConsume(MIToken::comma) ||
2625+
parseCFIRegister(R2) || expectAndConsume(MIToken::comma) ||
2626+
parseCFIUnsigned(R2Size))
2627+
return true;
2628+
2629+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMRegisterPair(
2630+
nullptr, Reg, R1, R1Size, R2, R2Size));
2631+
break;
2632+
}
2633+
case MIToken::kw_cfi_llvm_vector_registers: {
2634+
std::vector<MCCFIInstruction::VectorRegisterWithLane> VectorRegisters;
2635+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma))
2636+
return true;
2637+
do {
2638+
unsigned VR;
2639+
unsigned Lane, Size;
2640+
if (parseCFIRegister(VR) || expectAndConsume(MIToken::comma) ||
2641+
parseCFIUnsigned(Lane) || expectAndConsume(MIToken::comma) ||
2642+
parseCFIUnsigned(Size))
2643+
return true;
2644+
VectorRegisters.push_back({VR, Lane, Size});
2645+
} while (consumeIfPresent(MIToken::comma));
2646+
2647+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorRegisters(
2648+
nullptr, Reg, std::move(VectorRegisters)));
2649+
break;
2650+
}
2651+
case MIToken::kw_cfi_llvm_vector_offset: {
2652+
unsigned Reg, MaskReg;
2653+
unsigned RegSize, MaskRegSize;
2654+
int Offset = 0;
2655+
2656+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2657+
parseCFIUnsigned(RegSize) || expectAndConsume(MIToken::comma) ||
2658+
parseCFIRegister(MaskReg) || expectAndConsume(MIToken::comma) ||
2659+
parseCFIUnsigned(MaskRegSize) || expectAndConsume(MIToken::comma) ||
2660+
parseCFIOffset(Offset))
2661+
return true;
2662+
2663+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorOffset(
2664+
nullptr, Reg, RegSize, MaskReg, MaskRegSize, Offset));
2665+
break;
2666+
}
2667+
case MIToken::kw_cfi_llvm_vector_register_mask: {
2668+
unsigned Reg, SpillReg, MaskReg;
2669+
unsigned SpillRegLaneSize, MaskRegSize;
2670+
2671+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2672+
parseCFIRegister(SpillReg) || expectAndConsume(MIToken::comma) ||
2673+
parseCFIUnsigned(SpillRegLaneSize) ||
2674+
expectAndConsume(MIToken::comma) || parseCFIRegister(MaskReg) ||
2675+
expectAndConsume(MIToken::comma) || parseCFIUnsigned(MaskRegSize))
2676+
return true;
2677+
2678+
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMVectorRegisterMask(
2679+
nullptr, Reg, SpillReg, SpillRegLaneSize, MaskReg, MaskRegSize));
2680+
break;
2681+
}
26112682
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
26122683
CFIIndex =
26132684
MF.addFrameInst(MCCFIInstruction::createNegateRAStateWithPC(nullptr));
@@ -2962,6 +3033,10 @@ bool MIParser::parseMachineOperand(const unsigned OpCode, const unsigned OpIdx,
29623033
case MIToken::kw_cfi_undefined:
29633034
case MIToken::kw_cfi_window_save:
29643035
case MIToken::kw_cfi_aarch64_negate_ra_sign_state:
3036+
case MIToken::kw_cfi_llvm_register_pair:
3037+
case MIToken::kw_cfi_llvm_vector_registers:
3038+
case MIToken::kw_cfi_llvm_vector_offset:
3039+
case MIToken::kw_cfi_llvm_vector_register_mask:
29653040
case MIToken::kw_cfi_aarch64_negate_ra_sign_state_with_pc:
29663041
return parseCFIOperand(Dest);
29673042
case MIToken::kw_blockaddress:

llvm/lib/CodeGen/MachineOperand.cpp

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

llvm/lib/DWARFCFIChecker/DWARFCFIState.cpp

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

166176
return CFIP;

0 commit comments

Comments
 (0)