Skip to content

Commit 5c7f4e1

Browse files
author
Mikhail Gudim
committed
[MC][AsmPrinter] Introduce llvm_reg_offset pseudo cfi instruction.
Some targets which have scalable vectors (AArch64, RISCV) emit cfi escape expression of the form "deref(FrameReg + Offset)". Now instead of explicitly building up the expression, we can just emit the llvm_reg_offset. Also, we will need to handle such escape expressions in CFIInstrInserter. Without this pseudo, we would have to try to decode the escape expression inside the CFIInstrInserter. Now, when we have this pseudo, we can understand such escape expressions without decoding.
1 parent a774de8 commit 5c7f4e1

File tree

7 files changed

+80
-3
lines changed

7 files changed

+80
-3
lines changed

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_MC_MCDWARF_H
1616

1717
#include "llvm/ADT/MapVector.h"
18+
#include "llvm/ADT/SmallString.h"
1819
#include "llvm/ADT/SmallVector.h"
1920
#include "llvm/ADT/StringMap.h"
2021
#include "llvm/ADT/StringRef.h"
@@ -504,6 +505,7 @@ class MCCFIInstruction {
504505
OpRestoreState,
505506
OpOffset,
506507
OpLLVMDefAspaceCfa,
508+
OpLLVMRegOffset,
507509
OpDefCfaRegister,
508510
OpDefCfaOffset,
509511
OpDefCfa,
@@ -537,6 +539,11 @@ class MCCFIInstruction {
537539
unsigned Register;
538540
unsigned Register2;
539541
} RR;
542+
struct {
543+
unsigned Register;
544+
unsigned Register2;
545+
int64_t Offset;
546+
} RRO;
540547
MCSymbol *CfiLabel;
541548
} U;
542549
OpType Operation;
@@ -569,6 +576,14 @@ class MCCFIInstruction {
569576
U.CfiLabel = CfiLabel;
570577
}
571578

579+
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, unsigned R2, int64_t O,
580+
SMLoc Loc, StringRef V, StringRef Comment = "")
581+
: Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
582+
Comment(Comment) {
583+
assert(Op == OpLLVMRegOffset);
584+
U.RRO = {R, R2, O};
585+
}
586+
572587
public:
573588
/// .cfi_def_cfa defines a rule for computing CFA as: take address from
574589
/// Register and add Offset to it.
@@ -634,6 +649,22 @@ class MCCFIInstruction {
634649
return MCCFIInstruction(OpRegister, L, Register1, Register2, Loc);
635650
}
636651

652+
/// This is a "pseudo CFI" instruction which generates the escape expression
653+
/// deref(FrameReg + Offset) for the register Reg.
654+
static void createRegOffsetExpression(unsigned Reg, unsigned FrameReg,
655+
int64_t Offset,
656+
SmallString<64> &CFAExpr);
657+
static MCCFIInstruction createLLVMRegOffset(MCSymbol *L, unsigned Reg,
658+
unsigned FrameReg, int64_t Offset,
659+
SMLoc Loc = {},
660+
StringRef Comment = "") {
661+
// Build up the expression (FrameRegister + Offset)
662+
SmallString<64> CFAExpr;
663+
createRegOffsetExpression(Reg, FrameReg, Offset, CFAExpr);
664+
return MCCFIInstruction(OpLLVMRegOffset, L, Reg, FrameReg, Offset, Loc,
665+
CFAExpr, Comment);
666+
}
667+
637668
/// .cfi_window_save SPARC register window is saved.
638669
static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) {
639670
return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc);
@@ -715,6 +746,8 @@ class MCCFIInstruction {
715746
return U.RR.Register;
716747
if (Operation == OpLLVMDefAspaceCfa)
717748
return U.RIA.Register;
749+
if (Operation == OpLLVMRegOffset)
750+
return U.RRO.Register;
718751
assert(Operation == OpDefCfa || Operation == OpOffset ||
719752
Operation == OpRestore || Operation == OpUndefined ||
720753
Operation == OpSameValue || Operation == OpDefCfaRegister ||
@@ -723,8 +756,10 @@ class MCCFIInstruction {
723756
}
724757

725758
unsigned getRegister2() const {
726-
assert(Operation == OpRegister);
727-
return U.RR.Register2;
759+
if (Operation == OpRegister)
760+
return U.RR.Register2;
761+
assert(Operation == OpLLVMRegOffset);
762+
return U.RRO.Register2;
728763
}
729764

730765
unsigned getAddressSpace() const {
@@ -735,6 +770,8 @@ class MCCFIInstruction {
735770
int64_t getOffset() const {
736771
if (Operation == OpLLVMDefAspaceCfa)
737772
return U.RIA.Offset;
773+
if (Operation == OpLLVMRegOffset)
774+
return U.RRO.Offset;
738775
assert(Operation == OpDefCfa || Operation == OpOffset ||
739776
Operation == OpRelOffset || Operation == OpDefCfaOffset ||
740777
Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
@@ -748,7 +785,7 @@ class MCCFIInstruction {
748785
}
749786

750787
StringRef getValues() const {
751-
assert(Operation == OpEscape);
788+
assert(Operation == OpEscape || Operation == OpLLVMRegOffset);
752789
return StringRef(&Values[0], Values.size());
753790
}
754791

llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
223223
OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(),
224224
Inst.getAddressSpace(), Loc);
225225
break;
226+
case MCCFIInstruction::OpLLVMRegOffset:
227+
OutStreamer->AddComment(Inst.getComment());
228+
OutStreamer->emitCFIEscape(Inst.getValues(), Loc);
229+
break;
226230
case MCCFIInstruction::OpOffset:
227231
OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc);
228232
break;

llvm/lib/CodeGen/CFIInstrInserter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
265265
case MCCFIInstruction::OpLabel:
266266
case MCCFIInstruction::OpValOffset:
267267
break;
268+
case MCCFIInstruction::OpLLVMRegOffset:
269+
llvm_unreachable("Can't handle llvm_reg_offset yet!");
268270
}
269271
if (CSRReg || CSROffset) {
270272
auto It = CSRLocMap.find(CFI.getRegister());

llvm/lib/CodeGen/MIRParser/MILexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
231231
.Case("escape", MIToken::kw_cfi_escape)
232232
.Case("def_cfa", MIToken::kw_cfi_def_cfa)
233233
.Case("llvm_def_aspace_cfa", MIToken::kw_cfi_llvm_def_aspace_cfa)
234+
.Case("llvm_reg_offset", MIToken::kw_cfi_llvm_reg_offset)
234235
.Case("remember_state", MIToken::kw_cfi_remember_state)
235236
.Case("restore", MIToken::kw_cfi_restore)
236237
.Case("restore_state", MIToken::kw_cfi_restore_state)

llvm/lib/CodeGen/MIRParser/MILexer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct MIToken {
9090
kw_cfi_escape,
9191
kw_cfi_def_cfa,
9292
kw_cfi_llvm_def_aspace_cfa,
93+
kw_cfi_llvm_reg_offset,
9394
kw_cfi_register,
9495
kw_cfi_remember_state,
9596
kw_cfi_restore,

llvm/lib/CodeGen/MIRParser/MIParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,16 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
25472547
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMDefAspaceCfa(
25482548
nullptr, Reg, Offset, AddressSpace, SMLoc()));
25492549
break;
2550+
case MIToken::kw_cfi_llvm_reg_offset: {
2551+
Register FrameReg;
2552+
if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
2553+
parseCFIRegister(FrameReg) || expectAndConsume(MIToken::comma) ||
2554+
parseCFIOffset(Offset))
2555+
return true;
2556+
CFIIndex = MF.addFrameInst(
2557+
MCCFIInstruction::createLLVMRegOffset(nullptr, Reg, FrameReg, Offset));
2558+
break;
2559+
}
25502560
case MIToken::kw_cfi_remember_state:
25512561
CFIIndex = MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
25522562
break;

llvm/lib/MC/MCDwarf.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@
4141

4242
using namespace llvm;
4343

44+
void MCCFIInstruction::createRegOffsetExpression(unsigned Reg,
45+
unsigned FrameReg,
46+
int64_t Offset,
47+
SmallString<64> &CFAExpr) {
48+
SmallString<64> Expr;
49+
uint8_t Buffer[16];
50+
Expr.push_back(dwarf::DW_OP_consts);
51+
Expr.append(Buffer, Buffer + encodeSLEB128(Offset, Buffer));
52+
Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
53+
Expr.append(Buffer, Buffer + encodeULEB128(FrameReg, Buffer));
54+
Expr.push_back(0);
55+
Expr.push_back((uint8_t)dwarf::DW_OP_plus);
56+
// Wrap this into DW_CFA_expression.
57+
CFAExpr.push_back(dwarf::DW_CFA_expression);
58+
CFAExpr.append(Buffer, Buffer + encodeULEB128(Reg, Buffer));
59+
CFAExpr.append(Buffer, Buffer + encodeULEB128(Expr.size(), Buffer));
60+
CFAExpr.append(Expr.str());
61+
return;
62+
}
63+
4464
MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
4565
MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");
4666
MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");
@@ -1518,6 +1538,8 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
15181538
}
15191539
return;
15201540
}
1541+
case MCCFIInstruction::OpLLVMRegOffset:
1542+
llvm_unreachable("Should emit llvm_reg_offset as escape");
15211543
}
15221544
llvm_unreachable("Unhandled case in switch");
15231545
}

0 commit comments

Comments
 (0)