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 1 commit
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
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
5 changes: 4 additions & 1 deletion include/rellic/AST/IRToASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

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

namespace rellic {

Expand All @@ -37,16 +38,18 @@ class IRToASTVisitor : public llvm::InstVisitor<IRToASTVisitor> {
IRToTypeDeclMap type_decls;
IRToValDeclMap value_decls;
IRToStmtMap stmts;
DebugInfoCollector &dic;

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
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
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
86 changes: 76 additions & 10 deletions lib/AST/IRToASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#define GOOGLE_STRIP_LOG 1

#include "rellic/AST/IRToASTVisitor.h"
Expand All @@ -22,10 +21,55 @@

namespace rellic {

IRToASTVisitor::IRToASTVisitor(clang::ASTUnit &unit)
: ast_ctx(unit.getASTContext()), ast(unit) {}
IRToASTVisitor::IRToASTVisitor(clang::ASTUnit &unit, DebugInfoCollector &dic)
: ast_ctx(unit.getASTContext()), ast(unit), dic(dic) {}

clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type) {
return GetQualType(type, dic.GetIRTypeToDITypeMap()[type]);
}

clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type,
llvm::DIType *ditype) {
if (ditype) {
if (auto derived = llvm::dyn_cast<llvm::DIDerivedType>(ditype)) {
auto base_type{derived->getBaseType()};
switch (derived->getTag()) {
default:
break;
case llvm::dwarf::DW_TAG_const_type:
// FIXME(frabert):
// https://github.com/lifting-bits/rellic/issues/190#issuecomment-949694419
if (!base_type) {
return ast_ctx.VoidTy;
} else {
return GetQualType(type, base_type);
}
case llvm::dwarf::DW_TAG_volatile_type:
if (!base_type) {
return ast_ctx.getVolatileType(ast_ctx.VoidTy);
} else {
return ast_ctx.getVolatileType(GetQualType(type, base_type));
}
case llvm::dwarf::DW_TAG_restrict_type:
if (!base_type) {
return ast_ctx.getRestrictType(ast_ctx.VoidTy);
} else {
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);
} break;
}
}
}

DLOG(INFO) << "GetQualType: " << LLVMThingToString(type);
clang::QualType result;
switch (type->getTypeID()) {
Expand All @@ -50,9 +94,15 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type) {
break;

case llvm::Type::IntegerTyID: {
int sign{0};
if (ditype) {
auto inttype{llvm::cast<llvm::DIBasicType>(ditype)};
pgoodman marked this conversation as resolved.
Show resolved Hide resolved
sign =
inttype->getSignedness() == llvm::DIBasicType::Signedness::Signed;
}
auto size{type->getIntegerBitWidth()};
CHECK(size > 0) << "Integer bit width has to be greater than 0";
result = ast.GetLeastIntTypeForBitWidth(size, /*sign=*/0);
result = ast.GetLeastIntTypeForBitWidth(size, sign);
} break;

case llvm::Type::FunctionTyID: {
Expand All @@ -68,13 +118,23 @@ clang::QualType IRToASTVisitor::GetQualType(llvm::Type *type) {
} break;

case llvm::Type::PointerTyID: {
auto derived{ditype ? llvm::cast<llvm::DIDerivedType>(ditype) : nullptr};
auto elem_ditype{derived ? derived->getBaseType() : nullptr};
auto ptr{llvm::cast<llvm::PointerType>(type)};
result = ast_ctx.getPointerType(GetQualType(ptr->getElementType()));
auto elem_type{GetQualType(ptr->getElementType(), elem_ditype)};
if (derived && !elem_ditype) {
result = ast_ctx.VoidPtrTy;
} else {
result = ast_ctx.getPointerType(elem_type);
}
} break;

case llvm::Type::ArrayTyID: {
auto derived{ditype ? llvm::cast<llvm::DICompositeType>(ditype)
: nullptr};
auto elem_type{derived ? derived->getBaseType() : nullptr};
auto arr{llvm::cast<llvm::ArrayType>(type)};
auto elm{GetQualType(arr->getElementType())};
auto elm{GetQualType(arr->getElementType(), elem_type)};
result = GetConstantArrayType(ast_ctx, elm, arr->getNumElements());
} break;

Expand Down Expand Up @@ -376,7 +436,8 @@ void IRToASTVisitor::VisitGlobalVar(llvm::GlobalVariable &gvar) {
name = "gvar" + std::to_string(GetNumDecls<clang::VarDecl>(tudecl));
}
// Create a variable declaration
var = ast.CreateVarDecl(tudecl, GetQualType(type), name);
var = ast.CreateVarDecl(
tudecl, GetQualType(type, dic.GetIRToDITypeMap()[&gvar]), name);
// Add to translation unit
tudecl->addDecl(var);
// Create an initalizer literal
Expand All @@ -399,7 +460,8 @@ void IRToASTVisitor::VisitArgument(llvm::Argument &arg) {
auto func{arg.getParent()};
auto fdecl{clang::cast<clang::FunctionDecl>(GetOrCreateDecl(func))};
// Create a declaration
parm = ast.CreateParamDecl(fdecl, GetQualType(arg.getType()), name);
parm = ast.CreateParamDecl(
fdecl, GetQualType(arg.getType(), dic.GetIRToDITypeMap()[&arg]), name);
}

void IRToASTVisitor::VisitFunctionDecl(llvm::Function &func) {
Expand All @@ -418,7 +480,8 @@ void IRToASTVisitor::VisitFunctionDecl(llvm::Function &func) {

DLOG(INFO) << "Creating FunctionDecl for " << name;
auto tudecl{ast_ctx.getTranslationUnitDecl()};
auto type{GetQualType(func.getFunctionType())};
auto ftype{func.getFunctionType()};
auto type{GetQualType(ftype, dic.GetIRTypeToDITypeMap()[ftype])};
decl = ast.CreateFunctionDecl(tudecl, type, name);

tudecl->addDecl(decl);
Expand Down Expand Up @@ -634,7 +697,10 @@ void IRToASTVisitor::visitAllocaInst(llvm::AllocaInst &inst) {
// (`varname_addr` being a common name used by clang for variables used as
// storage for parameters e.g. a parameter named "foo" has a corresponding
// local variable named "foo_addr").
var = ast.CreateVarDecl(fdecl, GetQualType(inst.getAllocatedType()), name);
var = ast.CreateVarDecl(
fdecl,
GetQualType(inst.getAllocatedType(), dic.GetIRToDITypeMap()[&inst]),
name);
fdecl->addDecl(var);
}

Expand Down
2 changes: 0 additions & 2 deletions lib/AST/LocalDeclRenamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#include <glog/logging.h>
#include <llvm/Support/Casting.h>

#include <ios>

#include "rellic/AST/Compat/Stmt.h"

namespace rellic {
Expand Down
2 changes: 1 addition & 1 deletion tools/decomp/Decomp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ static bool GeneratePseudocode(llvm::Module& module,
auto ast_unit{clang::tooling::buildASTFromCodeWithArgs("", args, "out.c")};

llvm::legacy::PassManager pm_ast;
rellic::GenerateAST* gr{new rellic::GenerateAST(*ast_unit)};
rellic::GenerateAST* gr{new rellic::GenerateAST(*ast_unit, dic)};
rellic::DeadStmtElim* dse{new rellic::DeadStmtElim(*ast_unit)};
rellic::LocalDeclRenamer* ldr{new rellic::LocalDeclRenamer(
*ast_unit, dic.GetIRToNameMap(), gr->GetIRToValDeclMap())};
Expand Down