type_graph: Add reference type

Our existing drgn parser emits pointers, regardless of whether the type in the
DWARF is really a reference. Newer parsers like the LLDB/Clang parsers can
differentiate between a pointer and a reference. We should do this as
references can be safely followed according to the language rules with
`ChaseRawPointers` disabled, while pointers cannot.

Test Plan:
- TBD
This commit is contained in:
Jake Hillion 2023-12-14 13:34:32 +00:00
parent 8193d271a8
commit 6f5091c953
8 changed files with 89 additions and 0 deletions

View File

@ -194,6 +194,14 @@ void NameGen::visit(Pointer& p) {
p.setInputName(inputName);
}
void NameGen::visit(Reference& p) {
RecursiveVisitor::visit(p);
p.regenerateName();
std::string inputName{p.pointeeType().inputName()};
inputName += '*';
p.setInputName(inputName);
}
void NameGen::visit(DummyAllocator& d) {
RecursiveVisitor::visit(d);
d.regenerateName();

View File

@ -46,6 +46,7 @@ class NameGen final : public RecursiveVisitor {
void visit(Array& a) override;
void visit(Typedef& td) override;
void visit(Pointer& p) override;
void visit(Reference& p) override;
void visit(DummyAllocator& d) override;
void visit(CaptureKeys& d) override;

View File

@ -147,6 +147,17 @@ void Printer::visit(const Pointer& p) {
print(p.pointeeType());
}
void Printer::visit(const Reference& p) {
if (prefix(p))
return;
out_ << "Reference";
if (auto inp = p.inputName(); !inp.empty())
out_ << " [" << inp << "]";
out_ << std::endl;
print(p.pointeeType());
}
void Printer::visit(const Dummy& d) {
if (prefix(d))
return;

View File

@ -40,6 +40,7 @@ class Printer : public ConstVisitor {
void visit(const Array& a) override;
void visit(const Typedef& td) override;
void visit(const Pointer& p) override;
void visit(const Reference& p) override;
void visit(const Dummy& d) override;
void visit(const DummyAllocator& d) override;
void visit(const CaptureKeys& d) override;

View File

@ -42,4 +42,8 @@ void RemoveTopLevelPointer::visit(Pointer& p) {
topLevelType_ = &p.pointeeType();
}
void RemoveTopLevelPointer::visit(Reference& p) {
topLevelType_ = &p.pointeeType();
}
} // namespace oi::detail::type_graph

View File

@ -36,6 +36,7 @@ class RemoveTopLevelPointer : public LazyVisitor {
void removeTopLevelPointers(std::vector<std::reference_wrapper<Type>>& types);
void visit(Pointer& p) override;
void visit(Reference& p) override;
private:
Type* topLevelType_ = nullptr;

View File

@ -49,6 +49,7 @@
X(Array) \
X(Typedef) \
X(Pointer) \
X(Reference) \
X(Dummy) \
X(DummyAllocator) \
X(CaptureKeys)
@ -715,6 +716,61 @@ class Pointer : public Type {
std::string name_;
};
class Reference : public Type {
public:
explicit Reference(NodeId id, Type& pointeeType)
: pointeeType_(pointeeType), id_(id) {
regenerateName();
}
static inline constexpr bool has_node_id = true;
DECLARE_ACCEPT
virtual const std::string& name() const override {
return name_;
}
void regenerateName() {
name_ = pointeeType_.get().name() + "&";
}
virtual std::string_view inputName() const override {
return inputName_;
}
void setInputName(std::string name) {
inputName_ = std::move(name);
}
virtual size_t size() const override {
return sizeof(uintptr_t);
}
virtual uint64_t align() const override {
return size();
}
virtual NodeId id() const override {
return id_;
}
Type& pointeeType() const {
return pointeeType_;
}
void setPointeeType(Type& type) {
pointeeType_ = type;
}
private:
std::reference_wrapper<Type> pointeeType_;
std::string inputName_;
NodeId id_ = -1;
std::string name_;
};
/*
* Dummy
*

View File

@ -121,6 +121,9 @@ class RecursiveVisitor : public Visitor {
virtual void visit(Pointer& p) {
accept(p.pointeeType());
}
virtual void visit(Reference& r) {
accept(r.pointeeType());
}
virtual void visit(Dummy&) {
}
virtual void visit(DummyAllocator& d) {
@ -182,6 +185,10 @@ class RecursiveMutator : public Mutator {
p.setPointeeType(mutate(p.pointeeType()));
return p;
}
virtual Type& visit(Reference& p) {
p.setPointeeType(mutate(p.pointeeType()));
return p;
}
virtual Type& visit(Dummy& d) {
return d;
}