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 30 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
10 changes: 10 additions & 0 deletions include/rellic/AST/ASTBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,16 @@ class ASTBuilder {
clang::BreakStmt *CreateBreak();
// Return
clang::ReturnStmt *CreateReturn(clang::Expr *retval = nullptr);
// Typedef declaration
clang::TypedefDecl *CreateTypedefDecl(clang::DeclContext *decl_ctx,
clang::IdentifierInfo *id,
clang::QualType type);

clang::TypedefDecl *CreateTypedefDecl(clang::DeclContext *decl_ctx,
pgoodman marked this conversation as resolved.
Show resolved Hide resolved
std::string name,
clang::QualType type) {
return CreateTypedefDecl(decl_ctx, CreateIdentifier(name), type);
}
};

} // namespace rellic
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
7 changes: 6 additions & 1 deletion include/rellic/AST/DebugInfoCollector.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
namespace rellic {

using IRToNameMap = std::unordered_map<llvm::Value *, std::string>;
using IRToScopeMap = std::unordered_map<llvm::Value *, llvm::DILocalScope *>;
using IRToScopeMap = std::unordered_map<llvm::Value *, llvm::DIScope *>;
using IRToDITypeMap = std::unordered_map<llvm::Value *, llvm::DIType *>;
using IRTypeToDITypeMap = std::unordered_map<llvm::Type *, llvm::DIType *>;
using IRFuncToDITypeMap =
std::unordered_map<llvm::Function *, llvm::DISubroutineType *>;
using IRArgToDITypeMap = std::unordered_map<llvm::Argument *, llvm::DIType *>;
using IRFuncTypeToDIRetTypeMap =
std::unordered_map<llvm::FunctionType *, llvm::DIType *>;

class DebugInfoCollector : public llvm::InstVisitor<DebugInfoCollector> {
private:
Expand All @@ -32,6 +34,7 @@ class DebugInfoCollector : public llvm::InstVisitor<DebugInfoCollector> {
IRTypeToDITypeMap types;
IRFuncToDITypeMap funcs;
IRArgToDITypeMap args;
IRFuncTypeToDIRetTypeMap ret_types;

void WalkType(llvm::Type *type, llvm::DIType *ditype);

Expand All @@ -42,11 +45,13 @@ class DebugInfoCollector : public llvm::InstVisitor<DebugInfoCollector> {
IRTypeToDITypeMap &GetIRTypeToDITypeMap() { return types; }
IRFuncToDITypeMap &GetIRFuncToDITypeMap() { return funcs; }
IRArgToDITypeMap &GetIRArgToDITypeMap() { return args; }
IRFuncTypeToDIRetTypeMap &GetIRFuncTypeToDIRetTypeMap() { return ret_types; }

void visitDbgDeclareInst(llvm::DbgDeclareInst &inst);
void visitInstruction(llvm::Instruction &inst);

void visitFunction(llvm::Function &func);
void visitModule(llvm::Module &module);
};

} // namespace rellic
2 changes: 1 addition & 1 deletion include/rellic/AST/GenerateAST.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class GenerateAST : public llvm::ModulePass {
public:
static char ID;

GenerateAST(clang::ASTUnit &unit);
GenerateAST(clang::ASTUnit &unit, DebugInfoCollector &dic);

IRToStmtMap &GetIRToStmtMap() { return ast_gen.GetIRToStmtMap(); }
IRToValDeclMap &GetIRToValDeclMap() { return ast_gen.GetIRToValDeclMap(); }
Expand Down
8 changes: 7 additions & 1 deletion include/rellic/AST/IRToASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@

#include "rellic/AST/ASTBuilder.h"
#include "rellic/AST/Compat/ASTContext.h"
#include "rellic/AST/DebugInfoCollector.h"

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 *>;
using ArgToTempMap = std::unordered_map<llvm::Argument *, clang::VarDecl *>;

class IRToASTVisitor : public llvm::InstVisitor<IRToASTVisitor> {
Expand All @@ -38,18 +41,21 @@ class IRToASTVisitor : public llvm::InstVisitor<IRToASTVisitor> {

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

clang::Expr *GetOperandExpr(llvm::Value *val);
clang::QualType GetQualType(llvm::Type *type, llvm::DIType *ditype);
clang::QualType GetQualType(llvm::Type *type);

clang::Expr *CreateLiteralExpr(llvm::Constant *constant);

clang::Decl *GetOrCreateIntrinsic(llvm::InlineAsm *val);

public:
IRToASTVisitor(clang::ASTUnit &unit);
IRToASTVisitor(clang::ASTUnit &unit, DebugInfoCollector &dic);

clang::Stmt *GetOrCreateStmt(llvm::Value *val);
clang::Decl *GetOrCreateDecl(llvm::Value *val);
Expand Down
1 change: 1 addition & 0 deletions include/rellic/BC/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace rellic {
// Serialize an LLVM object into a string.
std::string LLVMThingToString(llvm::Value *thing);
std::string LLVMThingToString(llvm::Type *thing);
std::string LLVMThingToString(llvm::DIType *thing);

// Try to verify a module.
bool VerifyModule(llvm::Module *module);
Expand Down
8 changes: 8 additions & 0 deletions lib/AST/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,4 +442,12 @@ clang::ReturnStmt *ASTBuilder::CreateReturn(clang::Expr *retval) {
return CreateReturnStmt(ctx, retval);
}

clang::TypedefDecl *ASTBuilder::CreateTypedefDecl(clang::DeclContext *decl_ctx,
clang::IdentifierInfo *id,
clang::QualType type) {
return clang::TypedefDecl::Create(ctx, decl_ctx, clang::SourceLocation(),
clang::SourceLocation(), id,
ctx.getTrivialTypeSourceInfo(type));
}

} // namespace rellic
20 changes: 20 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,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
28 changes: 24 additions & 4 deletions lib/AST/DebugInfoCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ void DebugInfoCollector::visitDbgDeclareInst(llvm::DbgDeclareInst& inst) {
WalkType(loc->getType(), var->getType());
}

void DebugInfoCollector::visitModule(llvm::Module& module) {
for (auto& gvar : module.globals()) {
llvm::SmallVector<llvm::DIGlobalVariableExpression*> gves;
gvar.getDebugInfo(gves);
auto ptrtype{gvar.getType()};
CHECK_LE(gves.size(), 1)
<< "More than one DIGlobalVariableExpression for global variable";

if (gves.size() > 0) {
auto digve{gves[0]};
auto digvar{digve->getVariable()};
names[&gvar] = digvar->getName().str();
scopes[&gvar] = digvar->getScope();
valtypes[&gvar] = digvar->getType();

WalkType(ptrtype->getElementType(), digvar->getType());
}
}
}

void DebugInfoCollector::visitInstruction(llvm::Instruction& inst) {
if (auto loc{inst.getDebugLoc().get()}) {
scopes[&inst] = loc->getScope();
Expand Down Expand Up @@ -88,7 +108,8 @@ void DebugInfoCollector::WalkType(llvm::Type* type, llvm::DIType* ditype) {
std::copy(params.begin(), params.end(), std::back_inserter(type_array));

auto di_types{funcditype->getTypeArray()};
if (type_array.size() != di_types.size()) {
ret_types[functype] = di_types[0];
if (type_array.size() + functype->isVarArg() != di_types.size()) {
// Mismatch between bitcode and debug metadata, bail out
break;
}
Expand Down Expand Up @@ -139,16 +160,15 @@ void DebugInfoCollector::visitFunction(llvm::Function& func) {
}

auto ditype{subprogram->getType()};

if (func.arg_size() + 1 != ditype->getTypeArray().size()) {
auto type_array{ditype->getTypeArray()};
if (func.arg_size() + func.isVarArg() + 1 != type_array.size()) {
// Debug metadata is not compatible with bitcode, bail out
// TODO(frabert): Find a way to reconcile differences
return;
}

funcs[&func] = ditype;
size_t i{1};
auto type_array{ditype->getTypeArray()};
for (auto& arg : func.args()) {
auto argtype{type_array[i++]};
args[&arg] = argtype;
Expand Down
4 changes: 2 additions & 2 deletions lib/AST/GenerateAST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,10 @@ clang::CompoundStmt *GenerateAST::StructureRegion(llvm::Region *region) {

char GenerateAST::ID = 0;

GenerateAST::GenerateAST(clang::ASTUnit &unit)
GenerateAST::GenerateAST(clang::ASTUnit &unit, DebugInfoCollector &dic)
: ModulePass(GenerateAST::ID),
ast_ctx(&unit.getASTContext()),
ast_gen(unit),
ast_gen(unit, dic),
ast(unit) {}

void GenerateAST::getAnalysisUsage(llvm::AnalysisUsage &usage) const {
Expand Down
Loading