diff --git a/rellic/AST/ASTBuilder.cpp b/rellic/AST/ASTBuilder.cpp index fd77fd3a..21e64fed 100644 --- a/rellic/AST/ASTBuilder.cpp +++ b/rellic/AST/ASTBuilder.cpp @@ -162,10 +162,16 @@ clang::Expr *ASTBuilder::CreateNull() { return CreateCStyleCast(ctx.VoidPtrTy, lit); }; -clang::Expr *ASTBuilder::CreateUndef(clang::QualType type) { +clang::Expr *ASTBuilder::CreateUndefInteger(clang::QualType type) { + auto val{llvm::APInt::getNullValue(ctx.getTypeSize(type))}; + auto lit{CreateIntLit(val)}; + return lit; +}; + +clang::Expr *ASTBuilder::CreateUndefPointer(clang::QualType type) { auto null{CreateNull()}; auto cast{CreateCStyleCast(ctx.getPointerType(type), null)}; - return CreateDeref(cast); + return cast; }; clang::IdentifierInfo *ASTBuilder::CreateIdentifier(std::string name) { diff --git a/rellic/AST/ASTBuilder.h b/rellic/AST/ASTBuilder.h index d140e9e4..06f99ba9 100644 --- a/rellic/AST/ASTBuilder.h +++ b/rellic/AST/ASTBuilder.h @@ -54,7 +54,8 @@ class ASTBuilder { }; // Special values clang::Expr *CreateNull(); - clang::Expr *CreateUndef(clang::QualType type); + clang::Expr *CreateUndefPointer(clang::QualType type); + clang::Expr *CreateUndefInteger(clang::QualType type); // Identifiers clang::IdentifierInfo *CreateIdentifier(std::string name); // Variable declaration diff --git a/rellic/AST/IRToASTVisitor.cpp b/rellic/AST/IRToASTVisitor.cpp index 9f4c48fd..03880df5 100644 --- a/rellic/AST/IRToASTVisitor.cpp +++ b/rellic/AST/IRToASTVisitor.cpp @@ -150,11 +150,18 @@ clang::Expr *IRToASTVisitor::CreateLiteralExpr(llvm::Constant *constant) { } break; // Integers case llvm::Type::IntegerTyID: { - auto val{llvm::cast(constant)->getValue()}; - if (val.getBitWidth() == 1U) { - result = ast.CreateIntLit(val); + if (llvm::isa(constant)) { + auto ci = llvm::cast(constant); + auto val{ci->getValue()}; + if (val.getBitWidth() == 1U) { + result = ast.CreateIntLit(val); + } else { + result = ast.CreateAdjustedIntLit(val); + } + } else if (llvm::isa(constant)) { + result = ast.CreateUndefInteger(c_type); } else { - result = ast.CreateAdjustedIntLit(val); + LOG(FATAL) << "Unsupported integer constant"; } } break; @@ -162,7 +169,7 @@ clang::Expr *IRToASTVisitor::CreateLiteralExpr(llvm::Constant *constant) { if (llvm::isa(constant)) { result = ast.CreateNull(); } else if (llvm::isa(constant)) { - result = ast.CreateUndef(c_type); + result = ast.CreateUndefPointer(c_type); } else { LOG(FATAL) << "Unsupported pointer constant"; } diff --git a/unittests/AST/ASTBuilder.cpp b/unittests/AST/ASTBuilder.cpp index 70cdfaea..68d0f630 100644 --- a/unittests/AST/ASTBuilder.cpp +++ b/unittests/AST/ASTBuilder.cpp @@ -268,21 +268,29 @@ TEST_SUITE("ASTBuilder::CreateNull") { } TEST_SUITE("ASTBuilder::CreateUndef") { - SCENARIO("Create clang::Expr whose value is undefined") { + SCENARIO("Create clang::Expr to stand in for LLVM's 'undef' values") { GIVEN("Empty clang::ASTContext") { auto unit{GetASTUnit()}; auto &ctx{unit->getASTContext()}; rellic::ASTBuilder ast(*unit); + GIVEN("an unsigned integer type") { + auto type{ctx.UnsignedIntTy}; + THEN( + "return a value that satisfied LLVM's undef semantics (aka " + "anything)") { + auto expr{ast.CreateUndefInteger(type)}; + REQUIRE(expr != nullptr); + CHECK(expr->getType() == ctx.UnsignedIntTy); + } + } GIVEN("an arbitrary type t") { auto type{ctx.DoubleTy}; - THEN("return a null pointer dereference of type t") { - auto expr{ast.CreateUndef(type)}; + THEN("return an undef pointer (we use null pointers) of type t") { + auto expr{ast.CreateUndefPointer(type)}; REQUIRE(expr != nullptr); - CHECK(expr->getType() == ctx.DoubleTy); - auto deref{clang::dyn_cast(expr)}; - REQUIRE(deref != nullptr); - CHECK(deref->getOpcode() == clang::UO_Deref); - IsNullPtrExprCheck(ctx, deref->getSubExpr()->IgnoreCasts()); + auto double_ptr_ty{ctx.getPointerType(ctx.DoubleTy)}; + CHECK(expr->getType() == double_ptr_ty); + IsNullPtrExprCheck(ctx, expr->IgnoreCasts()); } } }