Skip to content

Commit

Permalink
Fix large literals (#323)
Browse files Browse the repository at this point in the history
* Fix large literals

* Restore previous logic

* Clang16 supports literals for wide integers
  • Loading branch information
frabert authored Apr 29, 2024
1 parent 0de1db1 commit a2d5ea7
Show file tree
Hide file tree
Showing 7 changed files with 12 additions and 78 deletions.
6 changes: 0 additions & 6 deletions include/rellic/AST/ASTBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ class ASTBuilder {
clang::CharacterLiteral *CreateCharLit(unsigned val);
clang::StringLiteral *CreateStrLit(std::string val);
clang::Expr *CreateFPLit(llvm::APFloat val);
// Casted literals
clang::Expr *CreateAdjustedIntLit(llvm::APSInt val);

clang::Expr *CreateAdjustedIntLit(llvm::APInt val) {
return CreateAdjustedIntLit(llvm::APSInt(val, /*isUnsigned=*/true));
};
// Special values
clang::Expr *CreateNull();
clang::Expr *CreateUndefPointer(clang::QualType type);
Expand Down
1 change: 1 addition & 0 deletions include/rellic/AST/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ clang::Expr *Clone(clang::ASTUnit &unit, clang::Expr *stmt,
DecompilationContext::ExprToUseMap &provenance);

std::string ClangThingToString(const clang::Stmt *stmt);
std::string ClangThingToString(clang::QualType ty);

z3::goal ApplyTactic(const z3::tactic &tactic, z3::expr expr);

Expand Down
16 changes: 0 additions & 16 deletions lib/AST/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ clang::IntegerLiteral *ASTBuilder::CreateIntLit(llvm::APSInt val) {
clang::QualType type;
if (value_size <= ctx.getIntWidth(ctx.IntTy)) {
type = sign ? ctx.IntTy : ctx.UnsignedIntTy;
} else if (value_size > ctx.getIntWidth(ctx.LongLongTy)) {
type = sign ? ctx.LongLongTy : ctx.UnsignedLongLongTy;
} else {
type = GetLeastIntTypeForBitWidth(value_size, sign);
}
Expand All @@ -159,20 +157,6 @@ clang::IntegerLiteral *ASTBuilder::CreateIntLit(llvm::APSInt val) {
return clang::IntegerLiteral::Create(ctx, val, type, clang::SourceLocation());
}

clang::Expr *ASTBuilder::CreateAdjustedIntLit(llvm::APSInt val) {
auto lit{CreateIntLit(val)};
auto value_size{val.getBitWidth()};
// Cast the integer literal to a type of the smallest bit width
// that can contain `val`. Either `short` or `char`.
if (value_size <= ctx.getIntWidth(ctx.ShortTy) ||
value_size > ctx.getIntWidth(ctx.LongLongTy)) {
return CreateCStyleCast(
GetLeastIntTypeForBitWidth(value_size, val.isSigned()), lit);
} else {
return lit;
}
}

clang::CharacterLiteral *ASTBuilder::CreateCharLit(llvm::APInt val) {
CHECK(val.getBitWidth() == 8U);
return new (ctx) clang::CharacterLiteral(
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/ExprCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ bool ExprCombine::VisitCStyleCastExpr(clang::CStyleCastExpr *cast) {

switch (result.Val.getKind()) {
case clang::APValue::ValueKind::Int: {
auto sub{dec_ctx.ast.CreateAdjustedIntLit(result.Val.getInt())};
auto sub{dec_ctx.ast.CreateIntLit(result.Val.getInt())};
if (GetHash(dec_ctx.ast_ctx, cast) != GetHash(dec_ctx.ast_ctx, sub)) {
substitutions[cast] = sub;
}
Expand Down
18 changes: 1 addition & 17 deletions lib/AST/IRToASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,23 +275,7 @@ clang::Expr *ExprGen::CreateLiteralExpr(llvm::Constant *constant) {
case llvm::Type::IntegerTyID: {
if (llvm::isa<llvm::ConstantInt>(constant)) {
auto val{llvm::cast<llvm::ConstantInt>(constant)->getValue()};
auto val_bitwidth{val.getBitWidth()};
auto ull_bitwidth{ast_ctx.getIntWidth(ast_ctx.LongLongTy)};
if (val_bitwidth == 1U) {
// Booleans
result = ast.CreateIntLit(val);
} else if (val.getActiveBits() <= ull_bitwidth) {
result = ast.CreateAdjustedIntLit(val);
} else {
// Values wider than `long long` will be represented as:
// (uint128_t)hi_64 << 64U | lo_64
auto lo{ast.CreateIntLit(val.extractBits(64U, 0U))};
auto hi{ast.CreateIntLit(val.extractBits(val_bitwidth - 64U, 64U))};
auto shl_val{ast.CreateIntLit(llvm::APInt(32U, 64U))};
result = ast.CreateCStyleCast(ast_ctx.UnsignedInt128Ty, hi);
result = ast.CreateShl(result, shl_val);
result = ast.CreateOr(result, lo);
}
result = ast.CreateIntLit(val);
} else if (llvm::isa<llvm::UndefValue>(constant)) {
result = ast.CreateUndefInteger(c_type);
} else {
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,13 @@ std::string ClangThingToString(const clang::Stmt *stmt) {
return s;
}

std::string ClangThingToString(clang::QualType ty) {
std::string s;
llvm::raw_string_ostream os(s);
ty.print(os, clang::PrintingPolicy(clang::LangOptions()));
return s;
}

z3::goal ApplyTactic(const z3::tactic &tactic, z3::expr expr) {
z3::goal goal(tactic.ctx());
goal.add(expr.simplify());
Expand Down
40 changes: 2 additions & 38 deletions unittests/AST/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,6 @@ TEST_SUITE("ASTBuilder::CreateIntLit") {
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedIntTy);
}

THEN(
"return a unsigned int typed integer literal casted to unsigned "
"char") {
auto cast{ast.CreateAdjustedIntLit(api)};
REQUIRE(cast != nullptr);
CHECK(clang::isa<clang::CStyleCastExpr>(cast));
CHECK(cast->getType() == ctx.UnsignedCharTy);
auto lit{cast->IgnoreCasts()};
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedIntTy);
}
}
}
}
Expand All @@ -99,18 +87,6 @@ TEST_SUITE("ASTBuilder::CreateIntLit") {
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedIntTy);
}

THEN(
"return a unsigned int typed integer literal casted to unsigned "
"short") {
auto cast{ast.CreateAdjustedIntLit(api)};
REQUIRE(cast != nullptr);
CHECK(clang::isa<clang::CStyleCastExpr>(cast));
CHECK(cast->getType() == ctx.UnsignedShortTy);
auto lit{cast->IgnoreCasts()};
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedIntTy);
}
}
}
}
Expand Down Expand Up @@ -156,23 +132,11 @@ TEST_SUITE("ASTBuilder::CreateIntLit") {
rellic::ASTBuilder ast(*unit);
GIVEN("128 bits wide llvm::APInt") {
llvm::APInt api(128U, UINT64_C(42), /*isSigned=*/false);
THEN("return a unsigned long long typed integer literal") {
THEN("return a _uint128_t typed integer literal") {
auto lit{ast.CreateIntLit(api)};
REQUIRE(lit != nullptr);
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedLongLongTy);
}

THEN(
"return a unsigned long long typed integer literal casted to "
"_uint128_t") {
auto cast{ast.CreateAdjustedIntLit(api)};
REQUIRE(cast != nullptr);
CHECK(clang::isa<clang::CStyleCastExpr>(cast));
CHECK(cast->getType() == ctx.UnsignedInt128Ty);
auto lit{cast->IgnoreCasts()};
CHECK(clang::isa<clang::IntegerLiteral>(lit));
CHECK(lit->getType() == ctx.UnsignedLongLongTy);
CHECK(lit->getType() == ctx.UnsignedInt128Ty);
}
}
}
Expand Down

0 comments on commit a2d5ea7

Please sign in to comment.