Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Flattener: Attempt to take params from parent allocator in case of ba…
Browse files Browse the repository at this point in the history
…d DWARF
ajor committed Jun 26, 2023
1 parent 4bfa932 commit 5a9d58a
Showing 9 changed files with 237 additions and 27 deletions.
10 changes: 10 additions & 0 deletions oi/EnumBitset.h
Original file line number Diff line number Diff line change
@@ -37,6 +37,16 @@ class EnumBitset {
return bitset[static_cast<size_t>(v)];
}

bool all() const noexcept {
return bitset.all();
}
bool any() const noexcept {
return bitset.any();
}
bool none() const noexcept {
return bitset.none();
}

private:
BitsetType bitset;
};
42 changes: 42 additions & 0 deletions oi/type_graph/Flattener.cpp
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
#include "Flattener.h"

#include "TypeGraph.h"
#include "TypeIdentifier.h"

namespace type_graph {

@@ -75,6 +76,44 @@ void flattenParent(const Parent& parent,
throw std::runtime_error("Invalid type for parent");
}
}

/*
* Some compilers generate bad DWARF for allocators, such that they are missing
* their template parameter (which represents the type to be allocated).
*
* Try to add this missing parameter back in by pulling it from the allocator's
* parent class.
*/
void fixAllocatorParams(Class& alloc) {
if (!TypeIdentifier::isAllocator(alloc)) {
return;
}

if (!alloc.templateParams.empty()) {
// The DWARF looks ok
return;
}

if (alloc.parents.empty()) {
// Nothing we can do
return;
}

Type& parent = stripTypedefs(*alloc.parents[0].type);
Class* parentClass = dynamic_cast<Class*>(&parent);
if (!parentClass) {
// Not handled
return;
}

if (parentClass->templateParams.empty()) {
// Nothing we can do
return;
}

Type& typeToAllocate = stripTypedefs(*parentClass->templateParams[0].type);
alloc.templateParams.push_back(TemplateParam{&typeToAllocate});
}
} // namespace

void Flattener::visit(Class& c) {
@@ -152,6 +191,9 @@ void Flattener::visit(Class& c) {
flattenParent(parent, flattenedMembers);
}

// Perform fixups for bad DWARF
fixAllocatorParams(c);

c.parents.clear();
c.members = std::move(flattenedMembers);

15 changes: 15 additions & 0 deletions oi/type_graph/Printer.cpp
Original file line number Diff line number Diff line change
@@ -159,6 +159,7 @@ void Printer::print_param(const TemplateParam& param) {
} else {
print(*param.type);
}
print_qualifiers(param.qualifiers);
depth_--;
}

@@ -204,6 +205,20 @@ void Printer::print_value(const std::string& value) {
depth_--;
}

void Printer::print_qualifiers(const QualifierSet& qualifiers) {
if (qualifiers.none()) {
return;
}
depth_++;
prefix();
out_ << "Qualifiers:";
if (qualifiers[Qualifier::Const]) {
out_ << " const";
}
out_ << std::endl;
depth_--;
}

std::string Printer::align_str(uint64_t align) {
if (align == 0)
return "";
1 change: 1 addition & 0 deletions oi/type_graph/Printer.h
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@ class Printer : public ConstVisitor {
void print_function(const Function& function);
void print_child(const Type& child);
void print_value(const std::string& value);
void print_qualifiers(const QualifierSet& qualifiers);
static std::string align_str(uint64_t align);

std::ostream& out_;
37 changes: 14 additions & 23 deletions oi/type_graph/TypeIdentifier.cpp
Original file line number Diff line number Diff line change
@@ -31,17 +31,8 @@ Pass TypeIdentifier::createPass() {
return Pass("TypeIdentifier", fn);
}

void TypeIdentifier::visit(Type& type) {
if (visited_.count(&type) != 0)
return;

visited_.insert(&type);
type.accept(*this);
}

namespace {
bool isAllocator(Type* t) {
auto* c = dynamic_cast<Class*>(t);
bool TypeIdentifier::isAllocator(Type& t) {
auto* c = dynamic_cast<Class*>(&t);
if (!c)
return false;

@@ -54,7 +45,14 @@ bool isAllocator(Type* t) {
}
return false;
}
} // namespace

void TypeIdentifier::visit(Type& type) {
if (visited_.count(&type) != 0)
return;

visited_.insert(&type);
type.accept(*this);
}

void TypeIdentifier::visit(Container& c) {
const auto& stubParams = c.containerInfo_.stubTemplateParams;
@@ -78,19 +76,12 @@ void TypeIdentifier::visit(Container& c) {
size = 0;
}

if (isAllocator(param.type)) {
if (isAllocator(*param.type)) {
auto* allocator =
dynamic_cast<Class*>(param.type); // TODO please don't do this...
Type* typeToAllocate;
if (!allocator->templateParams.empty()) {
typeToAllocate = allocator->templateParams.at(0).type;
} else {
// We've encountered some bad DWARF. Let's guess that the type to
// allocate is the first parameter of the container.
typeToAllocate = c.templateParams[0].type;
}
auto* dummy = typeGraph_.make_type<DummyAllocator>(
*typeToAllocate, size, param.type->align());
Type& typeToAllocate = *allocator->templateParams.at(0).type;
auto* dummy = typeGraph_.make_type<DummyAllocator>(typeToAllocate, size,
param.type->align());
c.templateParams[i] = dummy;
} else {
auto* dummy = typeGraph_.make_type<Dummy>(size, param.type->align());
1 change: 1 addition & 0 deletions oi/type_graph/TypeIdentifier.h
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ class TypeGraph;
class TypeIdentifier : public RecursiveVisitor {
public:
static Pass createPass();
static bool isAllocator(Type& t);

TypeIdentifier(TypeGraph& typeGraph) : typeGraph_(typeGraph) {
}
70 changes: 70 additions & 0 deletions test/test_codegen.cpp
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ TEST(CodeGenTest, TransformContainerAllocator) {
auto myint = Primitive{Primitive::Kind::Int32};

auto myalloc = Class{Class::Kind::Struct, "MyAlloc", 8};
myalloc.templateParams.push_back(TemplateParam{&myint});
myalloc.functions.push_back(Function{"allocate"});
myalloc.functions.push_back(Function{"deallocate"});

@@ -52,6 +53,8 @@ TEST(CodeGenTest, TransformContainerAllocator) {
Primitive: int32_t
Param
[1] Struct: MyAlloc (size: 8)
Param
Primitive: int32_t
Function: allocate
Function: deallocate
)",
@@ -64,3 +67,70 @@ TEST(CodeGenTest, TransformContainerAllocator) {
Primitive: int32_t
)");
}

TEST(CodeGenTest, TransformContainerAllocatorParamInParent) {
ContainerInfo pairInfo{"std::pair", SEQ_TYPE, "utility"};

ContainerInfo mapInfo{"std::map", STD_MAP_TYPE, "utility"};
mapInfo.stubTemplateParams = {2, 3};

Primitive myint{Primitive::Kind::Int32};

Container pair{pairInfo, 8};
pair.templateParams.push_back(TemplateParam{&myint, {Qualifier::Const}});
pair.templateParams.push_back(TemplateParam{&myint});

Class myallocBase{Class::Kind::Struct,
"MyAllocBase<std::pair<const int, int>>", 1};
myallocBase.templateParams.push_back(TemplateParam{&pair});
myallocBase.functions.push_back(Function{"allocate"});
myallocBase.functions.push_back(Function{"deallocate"});

Class myalloc{Class::Kind::Struct, "MyAlloc<std::pair<const int, int>>", 1};
myalloc.parents.push_back(Parent{&myallocBase, 0});
myalloc.functions.push_back(Function{"allocate"});
myalloc.functions.push_back(Function{"deallocate"});

Container map{mapInfo, 24};
map.templateParams.push_back(TemplateParam{&myint});
map.templateParams.push_back(TemplateParam{&myint});
map.templateParams.push_back(TemplateParam{&myalloc});

testTransform(map, R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t
Param
Primitive: int32_t
Param
[1] Struct: MyAlloc<std::pair<const int, int>> (size: 1)
Parent (offset: 0)
[2] Struct: MyAllocBase<std::pair<const int, int>> (size: 1)
Param
[3] Container: std::pair (size: 8)
Param
Primitive: int32_t
Qualifiers: const
Param
Primitive: int32_t
Function: allocate
Function: deallocate
Function: allocate
Function: deallocate
)",
R"(
[0] Container: std::map<int32_t, int32_t, DummyAllocator<std::pair<const int32_t, int32_t>, 0, 0>> (size: 24)
Param
Primitive: int32_t
Param
Primitive: int32_t
Param
DummyAllocator (size: 0)
[1] Container: std::pair<const int32_t, int32_t> (size: 8)
Param
Primitive: int32_t
Qualifiers: const
Param
Primitive: int32_t
)");
}
72 changes: 72 additions & 0 deletions test/test_flattener.cpp
Original file line number Diff line number Diff line change
@@ -762,3 +762,75 @@ TEST(FlattenerTest, ParentClassAndContainer) {
Primitive: int32_t
)");
}

TEST(FlattenerTest, AllocatorParamInParent) {
ContainerInfo pairInfo{"std::pair", SEQ_TYPE, "utility"};

ContainerInfo mapInfo{"std::map", STD_MAP_TYPE, "utility"};
mapInfo.stubTemplateParams = {2, 3};

Primitive myint{Primitive::Kind::Int32};

Container pair{pairInfo, 8};
pair.templateParams.push_back(TemplateParam{&myint, {Qualifier::Const}});
pair.templateParams.push_back(TemplateParam{&myint});

Class myallocBase{Class::Kind::Struct,
"MyAllocBase<std::pair<const int, int>>", 1};
myallocBase.templateParams.push_back(TemplateParam{&pair});
myallocBase.functions.push_back(Function{"allocate"});
myallocBase.functions.push_back(Function{"deallocate"});

Class myalloc{Class::Kind::Struct, "MyAlloc<std::pair<const int, int>>", 1};
myalloc.parents.push_back(Parent{&myallocBase, 0});
myalloc.functions.push_back(Function{"allocate"});
myalloc.functions.push_back(Function{"deallocate"});

Container map{mapInfo, 24};
map.templateParams.push_back(TemplateParam{&myint});
map.templateParams.push_back(TemplateParam{&myint});
map.templateParams.push_back(TemplateParam{&myalloc});

test(Flattener::createPass(), {map}, R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t
Param
Primitive: int32_t
Param
[1] Struct: MyAlloc<std::pair<const int, int>> (size: 1)
Parent (offset: 0)
[2] Struct: MyAllocBase<std::pair<const int, int>> (size: 1)
Param
[3] Container: std::pair (size: 8)
Param
Primitive: int32_t
Qualifiers: const
Param
Primitive: int32_t
Function: allocate
Function: deallocate
Function: allocate
Function: deallocate
)",
R"(
[0] Container: std::map (size: 24)
Param
Primitive: int32_t
Param
Primitive: int32_t
Param
[1] Struct: MyAlloc<std::pair<const int, int>> (size: 1)
Param
[2] Container: std::pair (size: 8)
Param
Primitive: int32_t
Qualifiers: const
Param
Primitive: int32_t
Function: allocate
Function: deallocate
Function: allocate
Function: deallocate
)");
}
16 changes: 12 additions & 4 deletions test/test_type_identifier.cpp
Original file line number Diff line number Diff line change
@@ -77,32 +77,40 @@ TEST(TypeIdentifierTest, Allocator) {
)");
}

TEST(TypeIdentifierTest, AllocatorNoParam) {
TEST(TypeIdentifierTest, AllocatorSize1) {
auto myint = Primitive{Primitive::Kind::Int32};

auto myalloc = Class{Class::Kind::Struct, "MyAlloc", 8};
auto myalloc = Class{Class::Kind::Struct, "MyAlloc", 1};
myalloc.templateParams.push_back(TemplateParam{&myint});
myalloc.functions.push_back(Function{"allocate"});
myalloc.functions.push_back(Function{"deallocate"});

auto container = getVector();
container.templateParams.push_back(TemplateParam{&myint});
container.templateParams.push_back(TemplateParam{&myalloc});
container.templateParams.push_back(TemplateParam{&myint});

test(TypeIdentifier::createPass(), {container}, R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
Param
[1] Struct: MyAlloc (size: 8)
[1] Struct: MyAlloc (size: 1)
Param
Primitive: int32_t
Function: allocate
Function: deallocate
Param
Primitive: int32_t
)",
R"(
[0] Container: std::vector (size: 24)
Param
Primitive: int32_t
Param
DummyAllocator (size: 8)
DummyAllocator (size: 0)
Primitive: int32_t
Param
Primitive: int32_t
)");
}

0 comments on commit 5a9d58a

Please sign in to comment.