Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine types based on debug metadata #191

Draft
wants to merge 33 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9798e97
Initial work on refining types
frabert Oct 22, 2021
49e2601
Visit global variables, improve return types
frabert Oct 25, 2021
b32d10a
Implement typedef printing
frabert Oct 25, 2021
55d3a13
Improve type refinement for fields and arguments
frabert Oct 26, 2021
2b1e41d
Fix struct members
frabert Oct 26, 2021
7db935e
Add explanation for checking argument count
frabert Oct 28, 2021
1067041
Add unit test for `ASTBuilder::CreateTypedefDecl`
frabert Oct 28, 2021
0486438
Fix varargs debug type analysis
frabert Oct 29, 2021
171e90e
Use more debug info for prototypes
frabert Oct 29, 2021
09f8a2e
Fix function argument type refinement
frabert Oct 31, 2021
bdd21e4
Default to signed integers
frabert Oct 31, 2021
7c474eb
Fix tests
frabert Oct 31, 2021
e0e6efe
Desugar types for Z3 conversion
frabert Nov 1, 2021
175c073
Initial work on refining types
frabert Oct 22, 2021
b55a8d0
Visit global variables, improve return types
frabert Oct 25, 2021
287e137
Implement typedef printing
frabert Oct 25, 2021
2292193
Improve type refinement for fields and arguments
frabert Oct 26, 2021
c3da195
Fix struct members
frabert Oct 26, 2021
36cb7c8
Add explanation for checking argument count
frabert Oct 28, 2021
33294d3
Add unit test for `ASTBuilder::CreateTypedefDecl`
frabert Oct 28, 2021
e878d42
Fix varargs debug type analysis
frabert Oct 29, 2021
6b4d302
Use more debug info for prototypes
frabert Oct 29, 2021
b231b24
Fix function argument type refinement
frabert Oct 31, 2021
e02bd8a
Default to signed integers
frabert Oct 31, 2021
3676aa5
Fix tests
frabert Oct 31, 2021
a9b5371
Desugar types for Z3 conversion
frabert Nov 1, 2021
0386c2b
Merge branch 'use-debug-types' of github.com:lifting-bits/rellic into…
frabert Nov 1, 2021
af69ad5
Merge branch 'master' into use-debug-types
frabert Nov 4, 2021
8f39d9d
Add utility functions
frabert Nov 4, 2021
35599ba
Fix bugs
frabert Nov 4, 2021
2905038
Merge branch 'master' into use-debug-types
frabert Nov 8, 2021
dbd0d82
Add void to ptr casts
frabert Nov 8, 2021
38991a6
Use plain `char` when asking for `signed char`
frabert Nov 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/rellic/AST/ASTPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class DeclTokenizer : public clang::DeclVisitor<DeclTokenizer> {
void VisitTranslationUnitDecl(clang::TranslationUnitDecl *decl);
void VisitFieldDecl(clang::FieldDecl *decl);
void VisitRecordDecl(clang::RecordDecl *decl);
void VisitTypedefDecl(clang::TypedefDecl *decl);
};

class StmtTokenizer : public clang::StmtVisitor<StmtTokenizer> {
Expand Down
3 changes: 3 additions & 0 deletions include/rellic/AST/IRToASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ namespace rellic {
using IRToTypeDeclMap = std::unordered_map<llvm::Type *, clang::TypeDecl *>;
using IRToValDeclMap = std::unordered_map<llvm::Value *, clang::ValueDecl *>;
using IRToStmtMap = std::unordered_map<llvm::Value *, clang::Stmt *>;
using DIToTypedefMap =
std::unordered_map<llvm::DIDerivedType *, clang::TypedefNameDecl *>;

class IRToASTVisitor : public llvm::InstVisitor<IRToASTVisitor> {
private:
Expand All @@ -37,6 +39,7 @@ class IRToASTVisitor : public llvm::InstVisitor<IRToASTVisitor> {

IRToTypeDeclMap type_decls;
IRToValDeclMap value_decls;
DIToTypedefMap typedef_decls;
IRToStmtMap stmts;
DebugInfoCollector &dic;

Expand Down
20 changes: 20 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,26 @@ void DeclTokenizer::VisitRecordDecl(clang::RecordDecl *rdecl) {
}
}

void DeclTokenizer::VisitTypedefDecl(clang::TypedefDecl *decl) {
auto &policy{unit.getASTContext().getPrintingPolicy()};
if (!policy.SuppressSpecifiers) {
out.push_back(Token::CreateMisc("typedef"));
Space();

if (decl->isModulePrivate()) {
out.push_back(Token::CreateMisc("__module_private__ "));
}
}
clang::QualType type = decl->getTypeSourceInfo()->getType();

std::string buf{""};
llvm::raw_string_ostream ss(buf);
type.print(ss, policy, decl->getName(), indent_level);

out.push_back(Token::CreateDecl(decl, ss.str()));
PrintAttributes(decl);
}

void StmtTokenizer::Space() { SpaceImpl(out); }
void StmtTokenizer::Indent() { IndentImpl(out, indent_level); }
void StmtTokenizer::Newline() { NewlineImpl(out); }
Expand Down
71 changes: 53 additions & 18 deletions lib/AST/IRToASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,18 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
return ast_ctx.getRestrictType(GetQualType(type, base_type));
}
case llvm::dwarf::DW_TAG_typedef: {
pgoodman marked this conversation as resolved.
Show resolved Hide resolved
// TODO(frabert): typedefs need to be implemented in ASTPrinter first
//
// auto tudecl{ast_ctx.getTranslationUnitDecl()};
// auto *tdef{ast.CreateTypedefDecl(tudecl, derived->getName().str(),
// GetQualType(type, base_type))};
// tudecl->addDecl(tdef);
// return ast_ctx.getTypedefType(tdef);
return GetQualType(type, base_type);
auto &tdef_decl{typedef_decls[derived]};
if (!tdef_decl) {
auto tudecl{ast_ctx.getTranslationUnitDecl()};
tdef_decl = ast.CreateTypedefDecl(tudecl, derived->getName().str(),
GetQualType(type, base_type));
tudecl->addDecl(tdef_decl);
}
return ast_ctx.getTypedefType(tdef_decl);
} break;
case llvm::dwarf::DW_TAG_member: {
ditype = derived->getBaseType();
};
}
}
}
Expand Down Expand Up @@ -96,9 +99,13 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
case llvm::Type::IntegerTyID: {
int sign{0};
if (ditype) {
auto inttype{llvm::cast<llvm::DIBasicType>(ditype)};
sign =
inttype->getSignedness() == llvm::DIBasicType::Signedness::Signed;
// TODO(frabert): this path will not be taken when arguments will have
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you file issues for each of these cases, with an example of C code that reproduces the issue.

// been merged/split or when a struct passed by value has been optimized
// away
if (auto inttype = llvm::dyn_cast<llvm::DIBasicType>(ditype)) {
sign =
inttype->getSignedness() == llvm::DIBasicType::Signedness::Signed;
}
}
auto size{type->getIntegerBitWidth()};
CHECK(size > 0) << "Integer bit width has to be greater than 0";
Expand All @@ -107,11 +114,21 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,

case llvm::Type::FunctionTyID: {
auto func{llvm::cast<llvm::FunctionType>(type)};
auto ret{GetQualType(func->getReturnType(),
dic.GetIRFuncTypeToDIRetTypeMap()[func])};
std::vector<llvm::DIType *> ditype_array{func->getNumParams() + 1};
pgoodman marked this conversation as resolved.
Show resolved Hide resolved
if (ditype) {
auto difunctype{llvm::cast<llvm::DISubroutineType>(ditype)};
auto arr{difunctype->getTypeArray()};
if (arr.size() == ditype_array.size()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you leave a comment on why the size check is needed. Is it a sanity check on the debug info? Is it to avoid the issue of dead argument elimination?

for (auto i{0UL}; i < arr.size(); ++i) {
ditype_array[i] = arr[i];
}
}
}
auto ret{GetQualType(func->getReturnType(), ditype_array[0])};
std::vector<clang::QualType> params;
auto i{1UL};
for (auto param : func->params()) {
params.push_back(GetQualType(param));
params.push_back(GetQualType(param, ditype_array[i++]));
}
auto epi{clang::FunctionProtoType::ExtProtoInfo()};
epi.Variadic = func->isVarArg();
Expand Down Expand Up @@ -145,6 +162,16 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
if (!decl) {
auto tudecl{ast_ctx.getTranslationUnitDecl()};
auto strct{llvm::cast<llvm::StructType>(type)};
std::vector<llvm::DIType *> fields_ditype{strct->getNumElements()};
pgoodman marked this conversation as resolved.
Show resolved Hide resolved
if (ditype) {
auto strct_ditype{llvm::cast<llvm::DICompositeType>(ditype)};
auto di_elems{strct_ditype->getElements()};
if (di_elems.size() == fields_ditype.size()) {
for (auto i{0U}; i < di_elems.size(); ++i) {
fields_ditype[i] = llvm::cast<llvm::DIType>(di_elems[i]);
}
}
}
auto sname{strct->getName().str()};
if (sname.empty()) {
auto num{GetNumDecls<clang::TypeDecl>(tudecl)};
Expand All @@ -154,7 +181,8 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
decl = sdecl = ast.CreateStructDecl(tudecl, sname);
// Add fields to the C struct
for (auto ecnt{0U}; ecnt < strct->getNumElements(); ++ecnt) {
auto etype{GetQualType(strct->getElementType(ecnt))};
auto etype{
GetQualType(strct->getElementType(ecnt), fields_ditype[ecnt])};
auto fname{"field" + std::to_string(ecnt)};
sdecl->addDecl(ast.CreateFieldDecl(sdecl, etype, fname));
}
Expand All @@ -175,7 +203,7 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
default: {
if (type->isVectorTy()) {
auto vtype{llvm::cast<llvm::VectorType>(type)};
auto etype{GetQualType(vtype->getElementType())};
auto etype{GetQualType(vtype->getElementType(), ditype)};
auto ecnt{GetNumElements(vtype)};
auto vkind{clang::VectorType::GenericVector};
result = ast_ctx.getVectorType(etype, ecnt, vkind);
Expand Down Expand Up @@ -460,9 +488,16 @@ void IRToASTVisitor::VisitArgument(llvm::Argument &arg) {
// Get parent function declaration
auto func{arg.getParent()};
auto fdecl{clang::cast<clang::FunctionDecl>(GetOrCreateDecl(func))};
llvm::DIType *ditype{nullptr};
auto difunctype{dic.GetIRFuncToDITypeMap()[func]};
if (difunctype) {
auto ditype_array{difunctype->getTypeArray()};
if (ditype_array.size() == func->getFunctionType()->getNumParams() + 1) {
ditype = ditype_array[arg.getArgNo() + 1];
}
}
// Create a declaration
parm = ast.CreateParamDecl(
fdecl, GetQualType(arg.getType(), dic.GetIRToDITypeMap()[&arg]), name);
parm = ast.CreateParamDecl(fdecl, GetQualType(arg.getType(), ditype), name);
}

void IRToASTVisitor::VisitFunctionDecl(llvm::Function &func) {
Expand Down