Skip to content

Commit

Permalink
Generate LocatedType
Browse files Browse the repository at this point in the history
  • Loading branch information
ahueck committed Dec 31, 2023
1 parent 155db2d commit bdf6d58
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 86 deletions.
2 changes: 1 addition & 1 deletion lib/type/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set(LIB_SOURCES
TBAA.cpp
DataflowAnalysis.cpp
GEP.cpp
SourceLocParser.cpp
SourceLocType.cpp
)

add_library(dimeta_Types STATIC
Expand Down
8 changes: 4 additions & 4 deletions lib/type/Dimeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,8 +719,8 @@ std::optional<DimetaData> type_for(const llvm::CallBase* call) {
}
auto source_loc = ditype::find::find_location(call);
const auto [final_type, pointer_level] = final_ditype(extracted_type);
const auto meta = DimetaData{
DimetaData::MemLoc::Heap, {}, extracted_type, final_type, source_loc, pointer_level + pointer_level_offset};
const auto meta = DimetaData{DimetaData::MemLoc::kHeap, {}, extracted_type, final_type, source_loc,
pointer_level + pointer_level_offset};
return meta;
}

Expand All @@ -732,7 +732,7 @@ std::optional<DimetaData> type_for(const llvm::AllocaInst* ai) {
auto source_loc = ditype::find::find_location(ai);
const auto [final_type, pointer_level] = final_ditype(extracted_type);
const auto meta =
DimetaData{DimetaData::MemLoc::Stack, local_di_var, extracted_type, final_type, source_loc, pointer_level};
DimetaData{DimetaData::MemLoc::kStack, local_di_var, extracted_type, final_type, source_loc, pointer_level};
return meta;
}

Expand All @@ -746,7 +746,7 @@ std::optional<DimetaData> type_for(const llvm::GlobalVariable* gv) {
auto gv_expr = *dbg_info.begin();
auto gv_type = gv_expr->getVariable()->getType();
const auto [final_type, pointer_level] = final_ditype(gv_type);
return DimetaData{DimetaData::MemLoc::Global, gv_expr->getVariable(), gv_type, final_type, {}, pointer_level};
return DimetaData{DimetaData::MemLoc::kGlobal, gv_expr->getVariable(), gv_type, final_type, {}, pointer_level};
}
return {};
}
Expand Down
12 changes: 10 additions & 2 deletions lib/type/Dimeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ namespace dimeta {
using DimetaDIVar = std::variant<llvm::DILocalVariable*, llvm::DIGlobalVariable*>;

struct DimetaData {
enum MemLoc { Stack = 0, Heap, Global };
MemLoc memory_location{Stack};
enum MemLoc { kStack = 0, kHeap, kGlobal };
MemLoc memory_location{kStack};
std::optional<DimetaDIVar> di_variable{}; // if existing the named variable w.r.t. allocation
std::optional<llvm::DIType*> entry_type{}; // determined to be the allocation including "pointer" DITypes
std::optional<llvm::DIType*> base_type{}; // The base type (int, struct X...) of the allocated memory
Expand All @@ -46,6 +46,14 @@ std::optional<DimetaData> type_for(const llvm::GlobalVariable*);

std::optional<location::SourceLocation> location_for(const DimetaData&);

std::optional<location::LocatedType> located_type_for(const DimetaData&);

std::optional<location::LocatedType> located_type_for(const llvm::AllocaInst*);

std::optional<location::LocatedType> located_type_for(const llvm::CallBase*);

std::optional<location::LocatedType> located_type_for(const llvm::GlobalVariable*);

} // namespace dimeta

#endif // DIMETA_DIMETA_H
46 changes: 30 additions & 16 deletions lib/type/MetaParse.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,29 @@ inline ArraySize make_array_size(const Type& type, Extent array_size_in_bits) {

} // namespace helper

struct DimetaParseResult {
QualifiedType type_;

[[nodiscard]] bool hasCompound() const {
return std::holds_alternative<QualifiedCompound>(type_);
}

[[nodiscard]] bool hasFundamental() const {
return std::holds_alternative<QualifiedFundamental>(type_);
}

template <typename QualifiedType>
std::optional<QualifiedType> getAs() const {
if (std::holds_alternative<QualifiedType>(type_)) {
return std::get<QualifiedType>(type_);
}
return {};
}
};

class DITypeParser : public visitor::DINodeVisitor<DITypeParser> {
private:
std::variant<std::monostate, QualifiedCompound, QualifiedFundamental> result_;
DimetaParseResult result_;

struct Meta {
llvm::SmallVector<unsigned, 8> tag_collector;
Expand Down Expand Up @@ -168,21 +188,14 @@ class DITypeParser : public visitor::DINodeVisitor<DITypeParser> {

CompositeStack composite_stack_;

public:
[[nodiscard]] bool hasCompound() const {
return std::holds_alternative<QualifiedCompound>(result_);
}

[[nodiscard]] bool hasFundamental() const {
return std::holds_alternative<QualifiedFundamental>(result_);
template <typename QualType>
void emplace_result(QualType type) {
result_.type_.emplace<QualType>(type);
}

template <typename QualifiedType>
std::optional<QualifiedType> getAs() const {
if (std::holds_alternative<QualifiedType>(result_)) {
return std::get<QualifiedType>(result_);
}
return {};
public:
[[nodiscard]] const DimetaParseResult& getParsedType() const {
return result_;
}

bool visitBasicType(const llvm::DIBasicType* basic_type) {
Expand All @@ -202,7 +215,7 @@ class DITypeParser : public visitor::DINodeVisitor<DITypeParser> {
return true;
}

result_.emplace<QualifiedFundamental>(
emplace_result<QualifiedFundamental>(
helper::make_qual_type(std::move(fundamental), array_size, quals, meta_.typedef_name));

return true;
Expand Down Expand Up @@ -312,7 +325,7 @@ class DITypeParser : public visitor::DINodeVisitor<DITypeParser> {
// if (current_meta.has_vtable) {
// }
assert(composite_stack_.empty());
result_.emplace<QualifiedCompound>(std::move(current_composite.q_compound));
emplace_result<QualifiedCompound>(std::move(current_composite.q_compound));
}

void leaveBasicType(const llvm::DIBasicType*) {
Expand All @@ -321,4 +334,5 @@ class DITypeParser : public visitor::DINodeVisitor<DITypeParser> {
};

} // namespace dimeta::parser

#endif // DIMETA_METAPARSE_H
30 changes: 0 additions & 30 deletions lib/type/SourceLocParser.cpp

This file was deleted.

75 changes: 75 additions & 0 deletions lib/type/SourceLocType.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "Dimeta.h"
#include "MetaParse.h"
#include "support/Logger.h"

#include "llvm/IR/DebugInfoMetadata.h"

#include <optional>

namespace dimeta {

std::optional<location::SourceLocation> location_for(const DimetaData& data) {
if (data.di_location) {
auto loc = data.di_location.value();
return location::SourceLocation{std::string{loc->getFilename()}, //
std::string{loc->getScope()->getName()}, //
loc->getLine()};
}
if (!data.di_variable) {
return {};
}

if (const auto gv = std::get_if<llvm::DIGlobalVariable*>(&data.di_variable.value())) {
const auto* global_var = *gv;
return location::SourceLocation{std::string{global_var->getFilename()}, //
std::string{global_var->getScope()->getName()}, //
global_var->getLine()};
}

return {};
}

std::optional<location::LocatedType> located_type_for(const DimetaData& type_data) {
auto loc = location_for(type_data);
if (!loc) {
LOG_DEBUG("Could not determine source location.");
return {};
}

parser::DITypeParser dimeta_parser;

assert(type_data.entry_type.has_value() && "Parsing stack type requires entry type.");
dimeta_parser.traverseType(type_data.entry_type.value());

const auto result = dimeta_parser.getParsedType();
return location::LocatedType{result.type_, loc.value()};
}

std::optional<location::LocatedType> located_type_for(const llvm::AllocaInst* ai) {
auto type_data = type_for(ai);
if (!type_data) {
LOG_DEBUG("Could not determine type.");
return {};
}
return located_type_for(type_data.value());
}

std::optional<location::LocatedType> located_type_for(const llvm::CallBase* cb) {
auto type_data = type_for(cb);
if (!type_data) {
LOG_DEBUG("Could not determine type.");
return {};
}
return located_type_for(type_data.value());
}

std::optional<location::LocatedType> located_type_for(const llvm::GlobalVariable* gv) {
auto type_data = type_for(gv);
if (!type_data) {
LOG_DEBUG("Could not determine type.");
return {};
}
return located_type_for(type_data.value());
}

} // namespace dimeta
69 changes: 36 additions & 33 deletions test/verifier/TestPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,33 +87,34 @@ const std::string rep_string(std::string input, int rep) {
return os.str();
};

const auto to_string(dimeta::DimetaData& data, bool stack = false) {
auto to_string(dimeta::DimetaData& data, bool stack = false) {
const std::string prefix = [&]() {
switch (data.memory_location) {
case DimetaData::MemLoc::Global:
case DimetaData::MemLoc::kGlobal:
return " Global";
case DimetaData::MemLoc::Stack:
case DimetaData::MemLoc::kStack:
return " Stack";
default:
return "";
}
}();
const auto print_loc = [](auto& rso, DimetaData& data) {
auto loc = dimeta::location_for(data);
if (loc) {
rso << "\"" << loc->file << "\":\"" << loc->function << "\":" << loc->line;
return;
}
rso << "empty";
};

std::string logging_message;
llvm::raw_string_ostream rso(logging_message);
rso << "Extracted Type" << prefix << ": " << log::ditype_str(data.entry_type.value_or(nullptr)) << "\n";
rso << "Final Type" << prefix << ": " << log::ditype_str(data.base_type.value_or(nullptr)) << "\n";
rso << "Pointer level: " << data.pointer_level << " (T" << rep_string("*", data.pointer_level) << ")\n";
return rso.str();
};

auto print_loc(std::optional<location::SourceLocation> loc) {
std::string logging_message;
llvm::raw_string_ostream rso(logging_message);
rso << "Location: ";
print_loc(rso, data);
if (loc) {
rso << "\"" << loc->file << "\":\"" << loc->function << "\":" << loc->line;
}
rso << "empty";
return rso.str();
};

Expand Down Expand Up @@ -156,6 +157,12 @@ class TestPass : public ModulePass {
if (global_meta) {
LOG_DEBUG("Type for global: " << global)
LOG_DEBUG(util::to_string(global_meta.value()));
auto located_type = located_type_for(&global);
if (located_type) {
LOG_DEBUG(util::print_loc(located_type->location));
} else {
LOG_ERROR("No located dimeta type for global")
}
}
}

Expand All @@ -175,29 +182,19 @@ class TestPass : public ModulePass {

LOG_MSG("\nFunction: " << f_name << ":");

// const auto ditype_tostring = [](auto* ditype) {
// llvm::DIType* type = ditype;
// while (llvm::isa<llvm::DIDerivedType>(type)) {
// auto ditype = llvm::dyn_cast<llvm::DIDerivedType>(type);
// // void*-based derived types:
// if (ditype->getBaseType() == nullptr) {
// return log::ditype_str(type);
// }
// type = ditype->getBaseType();
// }
//
// return log::ditype_str(type);
// };

for (auto& inst : llvm::instructions(func)) {
if (auto* call_inst = dyn_cast<CallBase>(&inst)) {
auto ditype_meta = type_for(call_inst);
if (ditype_meta) {
LOG_DEBUG("Type for heap-like: " << *call_inst)
// LOG_DEBUG("Extracted Type: " << log::ditype_str(ditype_meta.value()) << "\n");
// LOG_MSG("Final Type: " << ditype_tostring(ditype_meta.value()) << "\n");
LOG_DEBUG(util::to_string(ditype_meta.value()) << "\n");
}
auto located_type = located_type_for(call_inst);
if (located_type) {
LOG_DEBUG(util::print_loc(located_type->location));
} else {
LOG_ERROR("No located dimeta type for heap")
}
}

if (auto* alloca_inst = dyn_cast<AllocaInst>(&inst)) {
Expand All @@ -208,8 +205,13 @@ class TestPass : public ModulePass {
auto di_var = type_for(alloca_inst);
if (di_var) {
LOG_DEBUG("Type for alloca: " << *alloca_inst)
// LOG_MSG("Final Stack Type: " << ditype_tostring(di_var.value()->getType()) << "\n");
LOG_DEBUG(util::to_string(di_var.value()) << "\n");
auto located_type = located_type_for(alloca_inst);
if (located_type) {
LOG_DEBUG(util::print_loc(located_type->location));
} else {
LOG_ERROR("No located dimeta type for alloca")
}
}
if (di_var) {
parser::DITypeParser parser_types;
Expand All @@ -232,11 +234,12 @@ class TestPass : public ModulePass {
}

bool result{false};
if (parser_types.hasCompound()) {
auto const qual_type = parser_types.getAs<QualifiedCompound>().value();
const auto parsed_type = parser_types.getParsedType();
if (parsed_type.hasCompound()) {
auto const qual_type = parsed_type.getAs<QualifiedCompound>().value();
result = serialization_roundtrip(qual_type, cl_dimeta_test_print_yaml.getValue());
} else if (parser_types.hasFundamental()) {
auto const qual_type = parser_types.getAs<QualifiedFundamental>().value();
} else if (parsed_type.hasFundamental()) {
auto const qual_type = parsed_type.getAs<QualifiedFundamental>().value();
result = serialization_roundtrip(qual_type, cl_dimeta_test_print_yaml.getValue());
}
LOG_MSG(*alloca_inst << ": Yaml Verifier: " << static_cast<int>(result));
Expand Down

0 comments on commit bdf6d58

Please sign in to comment.