Skip to content

Commit 9b23df6

Browse files
committed
Implement DW_OP_convert
This patch adds basic support for DW_OP_convert[1] for integer types. Recent versions of LLVM's optimizer may insert this opcode into DWARF expressions. DW_OP_convert is effectively a type cast operation that takes a reference to a base type DIE (or zero) and then casts the value at the top of the DWARF stack to that type. Internally this works by changing the bit size of the APInt that is used as backing storage for LLDB's DWARF stack. I managed to write a unit test for this by implementing a mock YAML object file / module that takes debug info sections in yaml2obj format. [1] Typed DWARF stack. http://www.dwarfstd.org/ShowIssue.php?issue=140425.1 <rdar://problem/48167864> Differential Revision: https://reviews.llvm.org/D67369 llvm-svn: 371532
1 parent 6b877f6 commit 9b23df6

File tree

7 files changed

+423
-32
lines changed

7 files changed

+423
-32
lines changed

lldb/include/lldb/Core/Section.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ class SectionList {
4343
const_iterator begin() { return m_sections.begin(); }
4444
const_iterator end() { return m_sections.end(); }
4545

46-
SectionList();
47-
48-
~SectionList();
46+
/// Create an empty list.
47+
SectionList() = default;
4948

5049
SectionList &operator=(const SectionList &rhs);
5150

lldb/include/lldb/Utility/Scalar.h

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace lldb_private {
3838
// follows the ANSI C type promotion rules.
3939
class Scalar {
4040
public:
41+
// FIXME: These are host types which seems to be an odd choice.
4142
enum Type {
4243
e_void = 0,
4344
e_sint,
@@ -98,30 +99,14 @@ class Scalar {
9899
}
99100
Scalar(llvm::APInt v) : m_type(), m_float(static_cast<float>(0)) {
100101
m_integer = llvm::APInt(v);
101-
switch (m_integer.getBitWidth()) {
102-
case 8:
103-
case 16:
104-
case 32:
105-
m_type = e_sint;
106-
return;
107-
case 64:
108-
m_type = e_slonglong;
109-
return;
110-
case 128:
111-
m_type = e_sint128;
112-
return;
113-
case 256:
114-
m_type = e_sint256;
115-
return;
116-
case 512:
117-
m_type = e_sint512;
118-
return;
119-
}
120-
lldbassert(false && "unsupported bitwidth");
102+
m_type = GetBestTypeForBitSize(m_integer.getBitWidth(), true);
121103
}
122104
// Scalar(const RegisterValue& reg_value);
123105
virtual ~Scalar();
124106

107+
/// Return the most efficient Scalar::Type for the requested bit size.
108+
static Type GetBestTypeForBitSize(size_t bit_size, bool sign);
109+
125110
bool SignExtend(uint32_t bit_pos);
126111

127112
bool ExtractBitfield(uint32_t bit_size, uint32_t bit_offset);
@@ -154,6 +139,9 @@ class Scalar {
154139
return (m_type >= e_sint) && (m_type <= e_long_double);
155140
}
156141

142+
/// Convert integer to \p type, limited to \p bits size.
143+
void TruncOrExtendTo(Scalar::Type type, uint16_t bits);
144+
157145
bool Promote(Scalar::Type type);
158146

159147
bool MakeSigned();

lldb/source/Core/Section.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,6 @@ lldb::offset_t Section::GetSectionData(DataExtractor &section_data) {
417417

418418
#pragma mark SectionList
419419

420-
SectionList::SectionList() : m_sections() {}
421-
422-
SectionList::~SectionList() {}
423-
424420
SectionList &SectionList::operator=(const SectionList &rhs) {
425421
if (this != &rhs)
426422
m_sections = rhs.m_sections;

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,83 @@ bool DWARFExpression::Evaluate(
25592559
stack.back().SetValueType(Value::eValueTypeScalar);
25602560
break;
25612561

2562+
// OPCODE: DW_OP_convert
2563+
// OPERANDS: 1
2564+
// A ULEB128 that is either a DIE offset of a
2565+
// DW_TAG_base_type or 0 for the generic (pointer-sized) type.
2566+
//
2567+
// DESCRIPTION: Pop the top stack element, convert it to a
2568+
// different type, and push the result.
2569+
case DW_OP_convert: {
2570+
if (stack.size() < 1) {
2571+
if (error_ptr)
2572+
error_ptr->SetErrorString(
2573+
"Expression stack needs at least 1 item for DW_OP_convert.");
2574+
return false;
2575+
}
2576+
const uint64_t die_offset = opcodes.GetULEB128(&offset);
2577+
Scalar::Type type = Scalar::e_void;
2578+
uint64_t bit_size;
2579+
if (die_offset == 0) {
2580+
// The generic type has the size of an address on the target
2581+
// machine and an unspecified signedness. Scalar has no
2582+
// "unspecified signedness", so we use unsigned types.
2583+
if (!module_sp) {
2584+
if (error_ptr)
2585+
error_ptr->SetErrorString("No module");
2586+
return false;
2587+
}
2588+
bit_size = module_sp->GetArchitecture().GetAddressByteSize() * 8;
2589+
if (!bit_size) {
2590+
if (error_ptr)
2591+
error_ptr->SetErrorString("unspecified architecture");
2592+
return false;
2593+
}
2594+
type = Scalar::GetBestTypeForBitSize(bit_size, false);
2595+
} else {
2596+
// Retrieve the type DIE that the value is being converted to.
2597+
// FIXME: the constness has annoying ripple effects.
2598+
DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(die_offset);
2599+
if (!die) {
2600+
if (error_ptr)
2601+
error_ptr->SetErrorString("Cannot resolve DW_OP_convert type DIE");
2602+
return false;
2603+
}
2604+
uint64_t encoding =
2605+
die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
2606+
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
2607+
if (!bit_size)
2608+
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
2609+
if (!bit_size) {
2610+
if (error_ptr)
2611+
error_ptr->SetErrorString("Unsupported type size in DW_OP_convert");
2612+
return false;
2613+
}
2614+
switch (encoding) {
2615+
case DW_ATE_signed:
2616+
case DW_ATE_signed_char:
2617+
type = Scalar::GetBestTypeForBitSize(bit_size, true);
2618+
break;
2619+
case DW_ATE_unsigned:
2620+
case DW_ATE_unsigned_char:
2621+
type = Scalar::GetBestTypeForBitSize(bit_size, false);
2622+
break;
2623+
default:
2624+
if (error_ptr)
2625+
error_ptr->SetErrorString("Unsupported encoding in DW_OP_convert");
2626+
return false;
2627+
}
2628+
}
2629+
if (type == Scalar::e_void) {
2630+
if (error_ptr)
2631+
error_ptr->SetErrorString("Unsupported pointer size");
2632+
return false;
2633+
}
2634+
Scalar &top = stack.back().ResolveValue(exe_ctx);
2635+
top.TruncOrExtendTo(type, bit_size);
2636+
break;
2637+
}
2638+
25622639
// OPCODE: DW_OP_call_frame_cfa
25632640
// OPERANDS: None
25642641
// DESCRIPTION: Specifies a DWARF expression that pushes the value of

lldb/source/Utility/Scalar.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,51 @@ Scalar &Scalar::operator=(llvm::APInt rhs) {
416416

417417
Scalar::~Scalar() = default;
418418

419+
Scalar::Type Scalar::GetBestTypeForBitSize(size_t bit_size, bool sign) {
420+
// Scalar types are always host types, hence the sizeof().
421+
if (sign) {
422+
if (bit_size <= sizeof(int)*8) return Scalar::e_sint;
423+
if (bit_size <= sizeof(long)*8) return Scalar::e_slong;
424+
if (bit_size <= sizeof(long long)*8) return Scalar::e_slonglong;
425+
if (bit_size <= 128) return Scalar::e_sint128;
426+
if (bit_size <= 256) return Scalar::e_sint256;
427+
if (bit_size <= 512) return Scalar::e_sint512;
428+
} else {
429+
if (bit_size <= sizeof(unsigned int)*8) return Scalar::e_uint;
430+
if (bit_size <= sizeof(unsigned long)*8) return Scalar::e_ulong;
431+
if (bit_size <= sizeof(unsigned long long)*8) return Scalar::e_ulonglong;
432+
if (bit_size <= 128) return Scalar::e_uint128;
433+
if (bit_size <= 256) return Scalar::e_uint256;
434+
if (bit_size <= 512) return Scalar::e_uint512;
435+
}
436+
return Scalar::e_void;
437+
};
438+
439+
void Scalar::TruncOrExtendTo(Scalar::Type type, uint16_t bits) {
440+
switch (type) {
441+
case e_sint:
442+
case e_slong:
443+
case e_slonglong:
444+
case e_sint128:
445+
case e_sint256:
446+
case e_sint512:
447+
m_integer = m_integer.sextOrTrunc(bits);
448+
break;
449+
case e_uint:
450+
case e_ulong:
451+
case e_ulonglong:
452+
case e_uint128:
453+
case e_uint256:
454+
case e_uint512:
455+
m_integer = m_integer.zextOrTrunc(bits);
456+
break;
457+
default:
458+
llvm_unreachable("Promoting a Scalar to a specific number of bits is only "
459+
"supported for integer types.");
460+
}
461+
m_type = type;
462+
}
463+
419464
bool Scalar::Promote(Scalar::Type type) {
420465
bool success = false;
421466
switch (m_type) {

0 commit comments

Comments
 (0)