[llvm] [MC][AsmPrinter] Introduce llvm_reg_offset pseudo cfi instruction. (PR #125104)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 30 10:21:54 PST 2025
https://github.com/mgudim created https://github.com/llvm/llvm-project/pull/125104
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.
>From 5c7f4e12754676fc24ba67f6f18748742895d6d4 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at ventanamicro.com>
Date: Thu, 30 Jan 2025 09:58:58 -0800
Subject: [PATCH] [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.
---
llvm/include/llvm/MC/MCDwarf.h | 43 +++++++++++++++++--
.../CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 4 ++
llvm/lib/CodeGen/CFIInstrInserter.cpp | 2 +
llvm/lib/CodeGen/MIRParser/MILexer.cpp | 1 +
llvm/lib/CodeGen/MIRParser/MILexer.h | 1 +
llvm/lib/CodeGen/MIRParser/MIParser.cpp | 10 +++++
llvm/lib/MC/MCDwarf.cpp | 22 ++++++++++
7 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/MC/MCDwarf.h b/llvm/include/llvm/MC/MCDwarf.h
index 2fa7d73e1fa25a..72e77866f69c90 100644
--- a/llvm/include/llvm/MC/MCDwarf.h
+++ b/llvm/include/llvm/MC/MCDwarf.h
@@ -15,6 +15,7 @@
#define LLVM_MC_MCDWARF_H
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -504,6 +505,7 @@ class MCCFIInstruction {
OpRestoreState,
OpOffset,
OpLLVMDefAspaceCfa,
+ OpLLVMRegOffset,
OpDefCfaRegister,
OpDefCfaOffset,
OpDefCfa,
@@ -537,6 +539,11 @@ class MCCFIInstruction {
unsigned Register;
unsigned Register2;
} RR;
+ struct {
+ unsigned Register;
+ unsigned Register2;
+ int64_t Offset;
+ } RRO;
MCSymbol *CfiLabel;
} U;
OpType Operation;
@@ -569,6 +576,14 @@ class MCCFIInstruction {
U.CfiLabel = CfiLabel;
}
+ MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, unsigned R2, int64_t O,
+ SMLoc Loc, StringRef V, StringRef Comment = "")
+ : Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
+ Comment(Comment) {
+ assert(Op == OpLLVMRegOffset);
+ U.RRO = {R, R2, O};
+ }
+
public:
/// .cfi_def_cfa defines a rule for computing CFA as: take address from
/// Register and add Offset to it.
@@ -634,6 +649,22 @@ class MCCFIInstruction {
return MCCFIInstruction(OpRegister, L, Register1, Register2, Loc);
}
+ /// This is a "pseudo CFI" instruction which generates the escape expression
+ /// deref(FrameReg + Offset) for the register Reg.
+ static void createRegOffsetExpression(unsigned Reg, unsigned FrameReg,
+ int64_t Offset,
+ SmallString<64> &CFAExpr);
+ static MCCFIInstruction createLLVMRegOffset(MCSymbol *L, unsigned Reg,
+ unsigned FrameReg, int64_t Offset,
+ SMLoc Loc = {},
+ StringRef Comment = "") {
+ // Build up the expression (FrameRegister + Offset)
+ SmallString<64> CFAExpr;
+ createRegOffsetExpression(Reg, FrameReg, Offset, CFAExpr);
+ return MCCFIInstruction(OpLLVMRegOffset, L, Reg, FrameReg, Offset, Loc,
+ CFAExpr, Comment);
+ }
+
/// .cfi_window_save SPARC register window is saved.
static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) {
return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc);
@@ -715,6 +746,8 @@ class MCCFIInstruction {
return U.RR.Register;
if (Operation == OpLLVMDefAspaceCfa)
return U.RIA.Register;
+ if (Operation == OpLLVMRegOffset)
+ return U.RRO.Register;
assert(Operation == OpDefCfa || Operation == OpOffset ||
Operation == OpRestore || Operation == OpUndefined ||
Operation == OpSameValue || Operation == OpDefCfaRegister ||
@@ -723,8 +756,10 @@ class MCCFIInstruction {
}
unsigned getRegister2() const {
- assert(Operation == OpRegister);
- return U.RR.Register2;
+ if (Operation == OpRegister)
+ return U.RR.Register2;
+ assert(Operation == OpLLVMRegOffset);
+ return U.RRO.Register2;
}
unsigned getAddressSpace() const {
@@ -735,6 +770,8 @@ class MCCFIInstruction {
int64_t getOffset() const {
if (Operation == OpLLVMDefAspaceCfa)
return U.RIA.Offset;
+ if (Operation == OpLLVMRegOffset)
+ return U.RRO.Offset;
assert(Operation == OpDefCfa || Operation == OpOffset ||
Operation == OpRelOffset || Operation == OpDefCfaOffset ||
Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize ||
@@ -748,7 +785,7 @@ class MCCFIInstruction {
}
StringRef getValues() const {
- assert(Operation == OpEscape);
+ assert(Operation == OpEscape || Operation == OpLLVMRegOffset);
return StringRef(&Values[0], Values.size());
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index 2a146eb15f709d..46db960e7bd289 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -223,6 +223,10 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
OutStreamer->emitCFILLVMDefAspaceCfa(Inst.getRegister(), Inst.getOffset(),
Inst.getAddressSpace(), Loc);
break;
+ case MCCFIInstruction::OpLLVMRegOffset:
+ OutStreamer->AddComment(Inst.getComment());
+ OutStreamer->emitCFIEscape(Inst.getValues(), Loc);
+ break;
case MCCFIInstruction::OpOffset:
OutStreamer->emitCFIOffset(Inst.getRegister(), Inst.getOffset(), Loc);
break;
diff --git a/llvm/lib/CodeGen/CFIInstrInserter.cpp b/llvm/lib/CodeGen/CFIInstrInserter.cpp
index be8393cd386746..5fbd5b535f724a 100644
--- a/llvm/lib/CodeGen/CFIInstrInserter.cpp
+++ b/llvm/lib/CodeGen/CFIInstrInserter.cpp
@@ -265,6 +265,8 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
case MCCFIInstruction::OpLabel:
case MCCFIInstruction::OpValOffset:
break;
+ case MCCFIInstruction::OpLLVMRegOffset:
+ llvm_unreachable("Can't handle llvm_reg_offset yet!");
}
if (CSRReg || CSROffset) {
auto It = CSRLocMap.find(CFI.getRegister());
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
index 7153902fe2e7a6..9d964155f8564a 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp
@@ -231,6 +231,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
.Case("escape", MIToken::kw_cfi_escape)
.Case("def_cfa", MIToken::kw_cfi_def_cfa)
.Case("llvm_def_aspace_cfa", MIToken::kw_cfi_llvm_def_aspace_cfa)
+ .Case("llvm_reg_offset", MIToken::kw_cfi_llvm_reg_offset)
.Case("remember_state", MIToken::kw_cfi_remember_state)
.Case("restore", MIToken::kw_cfi_restore)
.Case("restore_state", MIToken::kw_cfi_restore_state)
diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h
index d7cd06759cfbb8..b7ddab9afa385a 100644
--- a/llvm/lib/CodeGen/MIRParser/MILexer.h
+++ b/llvm/lib/CodeGen/MIRParser/MILexer.h
@@ -90,6 +90,7 @@ struct MIToken {
kw_cfi_escape,
kw_cfi_def_cfa,
kw_cfi_llvm_def_aspace_cfa,
+ kw_cfi_llvm_reg_offset,
kw_cfi_register,
kw_cfi_remember_state,
kw_cfi_restore,
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 19c73374c3703d..d1ebaf391432f0 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -2547,6 +2547,16 @@ bool MIParser::parseCFIOperand(MachineOperand &Dest) {
CFIIndex = MF.addFrameInst(MCCFIInstruction::createLLVMDefAspaceCfa(
nullptr, Reg, Offset, AddressSpace, SMLoc()));
break;
+ case MIToken::kw_cfi_llvm_reg_offset: {
+ Register FrameReg;
+ if (parseCFIRegister(Reg) || expectAndConsume(MIToken::comma) ||
+ parseCFIRegister(FrameReg) || expectAndConsume(MIToken::comma) ||
+ parseCFIOffset(Offset))
+ return true;
+ CFIIndex = MF.addFrameInst(
+ MCCFIInstruction::createLLVMRegOffset(nullptr, Reg, FrameReg, Offset));
+ break;
+ }
case MIToken::kw_cfi_remember_state:
CFIIndex = MF.addFrameInst(MCCFIInstruction::createRememberState(nullptr));
break;
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index c17e9151ee487e..b66521c73172d5 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -41,6 +41,26 @@
using namespace llvm;
+void MCCFIInstruction::createRegOffsetExpression(unsigned Reg,
+ unsigned FrameReg,
+ int64_t Offset,
+ SmallString<64> &CFAExpr) {
+ SmallString<64> Expr;
+ uint8_t Buffer[16];
+ Expr.push_back(dwarf::DW_OP_consts);
+ Expr.append(Buffer, Buffer + encodeSLEB128(Offset, Buffer));
+ Expr.push_back((uint8_t)dwarf::DW_OP_bregx);
+ Expr.append(Buffer, Buffer + encodeULEB128(FrameReg, Buffer));
+ Expr.push_back(0);
+ Expr.push_back((uint8_t)dwarf::DW_OP_plus);
+ // Wrap this into DW_CFA_expression.
+ CFAExpr.push_back(dwarf::DW_CFA_expression);
+ CFAExpr.append(Buffer, Buffer + encodeULEB128(Reg, Buffer));
+ CFAExpr.append(Buffer, Buffer + encodeULEB128(Expr.size(), Buffer));
+ CFAExpr.append(Expr.str());
+ return;
+}
+
MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
MCSymbol *Start = S.getContext().createTempSymbol("debug_list_header_start");
MCSymbol *End = S.getContext().createTempSymbol("debug_list_header_end");
@@ -1518,6 +1538,8 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
}
return;
}
+ case MCCFIInstruction::OpLLVMRegOffset:
+ llvm_unreachable("Should emit llvm_reg_offset as escape");
}
llvm_unreachable("Unhandled case in switch");
}
More information about the llvm-commits
mailing list