aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorJohn Brawn <john.brawn@arm.com>2024-06-07 10:38:23 +0100
committerGitHub <noreply@github.com>2024-06-07 10:38:23 +0100
commit1721c14e8e0d75cc611067b6f4e84028ea7c47d5 (patch)
tree36e3b7daa4327c02b7a0352310532c59ef258829 /llvm/lib/CodeGen
parent0d1b3671a91c3929fc3e3613491ff4b57f1adcc3 (diff)
downloadllvm-1721c14e8e0d75cc611067b6f4e84028ea7c47d5.zip
llvm-1721c14e8e0d75cc611067b6f4e84028ea7c47d5.tar.gz
llvm-1721c14e8e0d75cc611067b6f4e84028ea7c47d5.tar.bz2
[DebugInfo] Add DW_OP_LLVM_extract_bits (#93990)
This operation extracts a number of bits at a given offset and sign or zero extends them, which is done by emitting it as a left shift followed by a right shift. This is being added for use in clang for C++ structured bindings of bitfields that have offset or size that aren't a byte multiple. A new operation is being added, instead of shifts being used directly, as it makes correctly handling it in optimisations (which will be done in a later patch) much easier.
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index a74d438..cc96d3c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -546,6 +547,37 @@ bool DwarfExpression::addExpression(
LocationKind = Unknown;
return true;
}
+ case dwarf::DW_OP_LLVM_extract_bits_sext:
+ case dwarf::DW_OP_LLVM_extract_bits_zext: {
+ unsigned SizeInBits = Op->getArg(1);
+ unsigned BitOffset = Op->getArg(0);
+
+ // If we have a memory location then dereference to get the value
+ if (isMemoryLocation())
+ emitOp(dwarf::DW_OP_deref);
+
+ // Extract the bits by a shift left (to shift out the bits after what we
+ // want to extract) followed by shift right (to shift the bits to position
+ // 0 and also sign/zero extend). These operations are done in the DWARF
+ // "generic type" whose size is the size of a pointer.
+ unsigned PtrSizeInBytes = CU.getAsmPrinter()->MAI->getCodePointerSize();
+ unsigned LeftShift = PtrSizeInBytes * 8 - (SizeInBits + BitOffset);
+ unsigned RightShift = LeftShift + BitOffset;
+ if (LeftShift) {
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(LeftShift);
+ emitOp(dwarf::DW_OP_shl);
+ }
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(RightShift);
+ emitOp(OpNum == dwarf::DW_OP_LLVM_extract_bits_sext ? dwarf::DW_OP_shra
+ : dwarf::DW_OP_shr);
+
+ // The value is now at the top of the stack, so set the location to
+ // implicit so that we get a stack_value at the end.
+ LocationKind = Implicit;
+ break;
+ }
case dwarf::DW_OP_plus_uconst:
assert(!isRegisterLocation());
emitOp(dwarf::DW_OP_plus_uconst);