From a2d5ea733a24bc49f6de2405846d631efc2e353c Mon Sep 17 00:00:00 2001 From: Francesco Bertolaccini Date: Mon, 29 Apr 2024 18:25:09 +0200 Subject: [PATCH] Fix large literals (#323) * Fix large literals * Restore previous logic * Clang16 supports literals for wide integers --- include/rellic/AST/ASTBuilder.h | 6 ----- include/rellic/AST/Util.h | 1 + lib/AST/ASTBuilder.cpp | 16 ------------- lib/AST/ExprCombine.cpp | 2 +- lib/AST/IRToASTVisitor.cpp | 18 +-------------- lib/AST/Util.cpp | 7 ++++++ unittests/AST/ASTBuilder.cpp | 40 ++------------------------------- 7 files changed, 12 insertions(+), 78 deletions(-) diff --git a/include/rellic/AST/ASTBuilder.h b/include/rellic/AST/ASTBuilder.h index 3e9f7de8..b3bf020f 100644 --- a/include/rellic/AST/ASTBuilder.h +++ b/include/rellic/AST/ASTBuilder.h @@ -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); diff --git a/include/rellic/AST/Util.h b/include/rellic/AST/Util.h index e42363e9..c0785150 100644 --- a/include/rellic/AST/Util.h +++ b/include/rellic/AST/Util.h @@ -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); diff --git a/lib/AST/ASTBuilder.cpp b/lib/AST/ASTBuilder.cpp index 08b9e352..9ea4517e 100644 --- a/lib/AST/ASTBuilder.cpp +++ b/lib/AST/ASTBuilder.cpp @@ -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); } @@ -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( diff --git a/lib/AST/ExprCombine.cpp b/lib/AST/ExprCombine.cpp index 2a057457..1c11c46f 100644 --- a/lib/AST/ExprCombine.cpp +++ b/lib/AST/ExprCombine.cpp @@ -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; } diff --git a/lib/AST/IRToASTVisitor.cpp b/lib/AST/IRToASTVisitor.cpp index 2d14717e..1dea0a47 100755 --- a/lib/AST/IRToASTVisitor.cpp +++ b/lib/AST/IRToASTVisitor.cpp @@ -275,23 +275,7 @@ clang::Expr *ExprGen::CreateLiteralExpr(llvm::Constant *constant) { case llvm::Type::IntegerTyID: { if (llvm::isa(constant)) { auto val{llvm::cast(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(constant)) { result = ast.CreateUndefInteger(c_type); } else { diff --git a/lib/AST/Util.cpp b/lib/AST/Util.cpp index e6c1da99..3796d62a 100644 --- a/lib/AST/Util.cpp +++ b/lib/AST/Util.cpp @@ -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()); diff --git a/unittests/AST/ASTBuilder.cpp b/unittests/AST/ASTBuilder.cpp index 31f065ed..e48cd43d 100644 --- a/unittests/AST/ASTBuilder.cpp +++ b/unittests/AST/ASTBuilder.cpp @@ -70,18 +70,6 @@ TEST_SUITE("ASTBuilder::CreateIntLit") { CHECK(clang::isa(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(cast)); - CHECK(cast->getType() == ctx.UnsignedCharTy); - auto lit{cast->IgnoreCasts()}; - CHECK(clang::isa(lit)); - CHECK(lit->getType() == ctx.UnsignedIntTy); - } } } } @@ -99,18 +87,6 @@ TEST_SUITE("ASTBuilder::CreateIntLit") { CHECK(clang::isa(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(cast)); - CHECK(cast->getType() == ctx.UnsignedShortTy); - auto lit{cast->IgnoreCasts()}; - CHECK(clang::isa(lit)); - CHECK(lit->getType() == ctx.UnsignedIntTy); - } } } } @@ -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(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(cast)); - CHECK(cast->getType() == ctx.UnsignedInt128Ty); - auto lit{cast->IgnoreCasts()}; - CHECK(clang::isa(lit)); - CHECK(lit->getType() == ctx.UnsignedLongLongTy); + CHECK(lit->getType() == ctx.UnsignedInt128Ty); } } }