Skip to content

Support for llvm 20 #340

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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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: 8 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,15 @@ find_package(gflags CONFIG REQUIRED)
find_package(glog CONFIG REQUIRED)
find_package(Z3 4.8 CONFIG REQUIRED)
find_package(doctest CONFIG REQUIRED)
find_package(LLVM CONFIG REQUIRED)
find_package(LLVM 20 CONFIG REQUIRED)
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
llvm_map_components_to_libnames(llvm_libs support core irreader bitreader bitwriter)
find_package(Clang CONFIG REQUIRED)

find_package(MLIR 20 CONFIG REQUIRED)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Rellic need MLIR?

message(STATUS "Using MLIRConfig.cmake in: ${MLIR_DIR}")

find_package(Clang 20 CONFIG REQUIRED)
message(STATUS "Using ClangConfig.cmake in: ${Clang_DIR}")


#
Expand Down
26 changes: 13 additions & 13 deletions lib/AST/ASTBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ clang::IntegerLiteral *ASTBuilder::CreateIntLit(llvm::APSInt val) {
// Extend the literal value based on it's sign if we have a
// mismatch between the bit width of the value and inferred type.
auto type_size{ctx.getIntWidth(type)};
if (val.getBitWidth() != type_size && val.getMinSignedBits() < type_size) {
if (val.getBitWidth() != type_size && val.getSignificantBits() < type_size) {
val = val.extOrTrunc(type_size);
}
// Clang does this check in the `clang::IntegerLiteral::Create`, but
Expand All @@ -159,21 +159,21 @@ clang::IntegerLiteral *ASTBuilder::CreateIntLit(llvm::APSInt val) {

clang::CharacterLiteral *ASTBuilder::CreateCharLit(llvm::APInt val) {
CHECK(val.getBitWidth() == 8U);
return new (ctx) clang::CharacterLiteral(
val.getLimitedValue(), clang::CharacterLiteral::CharacterKind::Ascii,
ctx.IntTy, clang::SourceLocation());
return new (ctx) clang::CharacterLiteral(val.getLimitedValue(),
clang::CharacterLiteralKind::Ascii,
ctx.IntTy, clang::SourceLocation());
}

clang::CharacterLiteral *ASTBuilder::CreateCharLit(unsigned val) {
return new (ctx) clang::CharacterLiteral(
val, clang::CharacterLiteral::CharacterKind::Ascii, ctx.IntTy,
clang::SourceLocation());
return new (ctx)
clang::CharacterLiteral(val, clang::CharacterLiteralKind::Ascii,
ctx.IntTy, clang::SourceLocation());
}

clang::StringLiteral *ASTBuilder::CreateStrLit(std::string val) {
auto type{ctx.getStringLiteralArrayType(ctx.CharTy, val.size())};
return clang::StringLiteral::Create(
ctx, val, clang::StringLiteral::StringKind::Ordinary,
ctx, val, clang::StringLiteralKind::Ordinary,
/*Pascal=*/false, type, clang::SourceLocation());
}

Expand All @@ -199,13 +199,13 @@ clang::Expr *ASTBuilder::CreateFPLit(llvm::APFloat val) {

clang::Expr *ASTBuilder::CreateNull() {
auto type{ctx.UnsignedIntTy};
auto val{llvm::APInt::getNullValue(ctx.getTypeSize(type))};
auto val{llvm::APInt::getZero(ctx.getTypeSize(type))};
auto lit{CreateIntLit(val)};
return CreateCStyleCast(ctx.VoidPtrTy, lit);
}

clang::Expr *ASTBuilder::CreateUndefInteger(clang::QualType type) {
auto val{llvm::APInt::getNullValue(ctx.getTypeSize(type))};
auto val{llvm::APInt::getZero(ctx.getTypeSize(type))};
auto lit{CreateIntLit(val)};
return lit;
}
Expand Down Expand Up @@ -253,15 +253,15 @@ clang::ParmVarDecl *ASTBuilder::CreateParamDecl(clang::DeclContext *decl_ctx,
clang::RecordDecl *ASTBuilder::CreateStructDecl(clang::DeclContext *decl_ctx,
clang::IdentifierInfo *id,
clang::RecordDecl *prev_decl) {
return clang::RecordDecl::Create(ctx, clang::TagTypeKind::TTK_Struct,
decl_ctx, clang::SourceLocation(),
return clang::RecordDecl::Create(ctx, clang::TagTypeKind::Struct, decl_ctx,
clang::SourceLocation(),
clang::SourceLocation(), id, prev_decl);
}

clang::RecordDecl *ASTBuilder::CreateUnionDecl(clang::DeclContext *decl_ctx,
clang::IdentifierInfo *id,
clang::RecordDecl *prev_decl) {
return clang::RecordDecl::Create(ctx, clang::TagTypeKind::TTK_Union, decl_ctx,
return clang::RecordDecl::Create(ctx, clang::TagTypeKind::Union, decl_ctx,
clang::SourceLocation(),
clang::SourceLocation(), id, prev_decl);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/CXXToCDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static std::string GetMangledName(clang::NamedDecl *decl) {
llvm::raw_string_ostream os(buffer);
if (auto type_decl = clang::dyn_cast<clang::TypeDecl>(decl)) {
auto type = clang::QualType(type_decl->getTypeForDecl(), 0);
mangler->mangleTypeName(type, os);
mangler->mangleCanonicalTypeName(type, os);
} else if (auto cst = clang::dyn_cast<clang::CXXConstructorDecl>(decl)) {
mangler->mangleName(clang::GlobalDecl(cst), os);
} else if (auto dst = clang::dyn_cast<clang::CXXDestructorDecl>(decl)) {
Expand Down
19 changes: 11 additions & 8 deletions lib/AST/StructGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static FieldInfo CreatePadding(clang::ASTContext& ast_ctx,
auto padding_count{needed_padding / type_size};
auto padding_arr_type{ast_ctx.getConstantArrayType(
padding_type, llvm::APInt(64, padding_count), nullptr,
clang::ArrayType::ArraySizeModifier::Normal, 0)};
clang::ArraySizeModifier::Normal, 0)};
return {name, padding_arr_type, 0};
}
}
Expand All @@ -146,7 +146,8 @@ static unsigned GetStructSize(clang::ASTContext& ast_ctx, ASTBuilder& ast,

auto tudecl{ast_ctx.getTranslationUnitDecl()};
auto decl{ast.CreateStructDecl(tudecl, "temp" + std::to_string(count++))};
clang::AttributeCommonInfo info{clang::SourceLocation{}};
clang::AttributeCommonInfo info{nullptr, clang::SourceLocation{},
clang::AttributeCommonInfo::Form::GNU()};
decl->addAttr(clang::PackedAttr::Create(ast_ctx, info));
for (auto& field : fields) {
decl->addDecl(FieldInfoToFieldDecl(ast_ctx, ast, decl, field));
Expand Down Expand Up @@ -217,7 +218,9 @@ void StructGenerator::VisitFields(clang::RecordDecl* decl,
auto field_count{0U};
std::vector<FieldInfo> fields{};
if (!isUnion) {
clang::AttributeCommonInfo attrinfo{clang::SourceLocation{}};
clang::AttributeCommonInfo attrinfo{
nullptr, clang::SourceLocation{},
clang::AttributeCommonInfo::Form::GNU()};
decl->addAttr(clang::PackedAttr::Create(ast_ctx, attrinfo));
}

Expand Down Expand Up @@ -333,10 +336,10 @@ clang::QualType StructGenerator::BuildArray(llvm::DICompositeType* a) {
VLOG(1) << "BuildArray: " << rellic::LLVMThingToString(a);
auto base{BuildType(a->getBaseType())};
auto subrange{llvm::cast<llvm::DISubrange>(a->getElements()[0])};
auto* ci = subrange->getCount().get<llvm::ConstantInt*>();
return ast_ctx.getConstantArrayType(
base, llvm::APInt(64, ci->getZExtValue()), nullptr,
clang::ArrayType::ArraySizeModifier::Normal, 0);
auto* ci = llvm::dyn_cast<llvm::ConstantInt*>(subrange->getCount());
return ast_ctx.getConstantArrayType(base, llvm::APInt(64, ci->getZExtValue()),
nullptr, clang::ArraySizeModifier::Normal,
0);
}

clang::QualType StructGenerator::BuildDerived(llvm::DIDerivedType* d,
Expand Down Expand Up @@ -608,7 +611,7 @@ std::vector<clang::Expr*> StructGenerator::GetAccessor(clang::Expr* base,
auto idx{field->getFieldIndex()};
auto type{field->getType().getDesugaredType(ast_ctx)};
auto field_offset{layout.getFieldOffset(idx)};
auto field_size{field->isBitField() ? field->getBitWidthValue(ast_ctx)
auto field_size{field->isBitField() ? field->getBitWidthValue()
: ast_ctx.getTypeSize(type)};
if (offset >= field_offset &&
offset + length <= field_offset + field_size) {
Expand Down
13 changes: 5 additions & 8 deletions lib/AST/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,20 +462,17 @@ clang::QualType DecompilationContext::GetQualType(llvm::Type *type) {

case llvm::Type::PointerTyID: {
auto ptr_type{llvm::cast<llvm::PointerType>(type)};
if (ptr_type->isOpaque()) {
result = ast_ctx.VoidPtrTy;
} else {
result = ast_ctx.getPointerType(
GetQualType(ptr_type->getNonOpaquePointerElementType()));
}
// With opaque pointers, we can't get element type directly from the
// pointer; Use the context's void pointer type as the default
result = ast_ctx.VoidPtrTy;
} break;

case llvm::Type::ArrayTyID: {
auto arr{llvm::cast<llvm::ArrayType>(type)};
auto elm{GetQualType(arr->getElementType())};
result = ast_ctx.getConstantArrayType(
elm, llvm::APInt(64, arr->getNumElements()), nullptr,
clang::ArrayType::ArraySizeModifier::Normal, 0);
clang::ArraySizeModifier::Normal, 0);
} break;

case llvm::Type::StructTyID: {
Expand Down Expand Up @@ -521,7 +518,7 @@ clang::QualType DecompilationContext::GetQualType(llvm::Type *type) {
auto vtype{llvm::cast<llvm::FixedVectorType>(type)};
auto etype{GetQualType(vtype->getElementType())};
auto ecnt{vtype->getNumElements()};
auto vkind{clang::VectorType::GenericVector};
auto vkind{clang::VectorKind::Generic};
result = ast_ctx.getVectorType(etype, ecnt, vkind);
} else {
THROW() << "Unknown LLVM Type: " << LLVMThingToString(type);
Expand Down
29 changes: 15 additions & 14 deletions lib/BC/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,14 @@ static llvm::LoadInst *ConvertInsertValue(llvm::InsertValueInst *I) {

auto F{I->getParent()->getParent()};
auto alloca{new llvm::AllocaInst(I->getType(), DL.getAllocaAddrSpace(),
nullptr, I->getName() + ".iv2mem", I)};
nullptr, I->getName() + ".iv2mem",
I->getIterator())};
auto aggr_opnd{I->getAggregateOperand()};
auto aggr_ty{aggr_opnd->getType()};
auto ins_opnd{I->getInsertedValueOperand()};

if (!llvm::isa<llvm::UndefValue>(aggr_opnd)) {
new llvm::StoreInst(aggr_opnd, alloca, I);
new llvm::StoreInst(aggr_opnd, alloca, I->getIterator());
}
std::vector<llvm::Value *> indices;
indices.push_back(llvm::ConstantInt::get(ctx, llvm::APInt(64, 0, false)));
Expand All @@ -273,10 +274,10 @@ static llvm::LoadInst *ConvertInsertValue(llvm::InsertValueInst *I) {
llvm::ConstantInt::get(ctx, llvm::APInt(sizeof(i) * 8, i)));
}
auto ptr{llvm::GetElementPtrInst::Create(aggr_opnd->getType(), alloca,
indices, "", I)};
new llvm::StoreInst(ins_opnd, ptr, I);
auto load{
new llvm::LoadInst(I->getType(), alloca, I->getName() + ".reload", I)};
indices, "", I->getIterator())};
new llvm::StoreInst(ins_opnd, ptr, I->getIterator());
auto load{new llvm::LoadInst(I->getType(), alloca, I->getName() + ".reload",
I->getIterator())};

I->replaceAllUsesWith(load);
I->eraseFromParent();
Expand Down Expand Up @@ -359,9 +360,9 @@ void ConvertArrayArguments(llvm::Module &m) {
if (orig_func->getReturnType()->isArrayTy()) {
auto undef{llvm::UndefValue::get(return_ty)};
for (auto ret : Returns) {
auto wrap{llvm::InsertValueInst::Create(undef, ret->getReturnValue(),
indices, "", ret)};
auto new_ret{llvm::ReturnInst::Create(ctx, wrap, ret)};
auto wrap{llvm::InsertValueInst::Create(
undef, ret->getReturnValue(), indices, "", ret->getIterator())};
auto new_ret{llvm::ReturnInst::Create(ctx, wrap, ret->getIterator())};
ret->eraseFromParent();
}
}
Expand Down Expand Up @@ -397,8 +398,8 @@ void ConvertArrayArguments(llvm::Module &m) {
for (auto &old_arg : call->args()) {
if (old_arg->getType()->isArrayTy()) {
auto undef{llvm::UndefValue::get(conv_types[old_arg->getType()])};
auto new_arg{llvm::InsertValueInst::Create(undef, old_arg, indices,
"", call)};
auto new_arg{llvm::InsertValueInst::Create(
undef, old_arg, indices, "", call->getIterator())};
args.push_back(new_arg);
} else {
args.push_back(old_arg);
Expand All @@ -407,12 +408,12 @@ void ConvertArrayArguments(llvm::Module &m) {
llvm::SmallVector<std::pair<unsigned, llvm::MDNode *>, 16u> mds;
auto new_call{llvm::CallInst::Create(new_func->getFunctionType(),
new_func, args, call->getName(),
call)};
call->getIterator())};
call->getAllMetadata(mds);
CloneMetadataInto(new_call, mds);
if (callee->getReturnType()->isArrayTy()) {
auto unwrap{
llvm::ExtractValueInst::Create(new_call, indices, "", call)};
auto unwrap{llvm::ExtractValueInst::Create(new_call, indices, "",
call->getIterator())};
call->replaceAllUsesWith(unwrap);
} else {
call->replaceAllUsesWith(new_call);
Expand Down
18 changes: 13 additions & 5 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ target_link_libraries(${RELLIC_DECOMP}
PRIVATE
"${PROJECT_NAME}_cxx_settings"
"${PROJECT_NAME}"
gflags::gflags
gflags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changing? gflags provides official support for gflags::gflags

)

set(RELLIC_DECOMP "${RELLIC_DECOMP}" PARENT_SCOPE)
Expand All @@ -39,7 +39,7 @@ target_link_libraries(${RELLIC_HEADERGEN}
PRIVATE
"${PROJECT_NAME}_cxx_settings"
"${PROJECT_NAME}"
gflags::gflags
gflags
)

set(RELLIC_HEADERGEN "${RELLIC_HEADERGEN}" PARENT_SCOPE)
Expand All @@ -57,14 +57,22 @@ add_executable(${RELLIC_XREF}
"xref/Xref.cpp"
)

include(FetchContent)
FetchContent_Declare(cpp-httplib
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
GIT_TAG v0.20.0
)
FetchContent_MakeAvailable(cpp-httplib)
set(CPP_HTTPLIB_INCLUDE_DIRS "${cpp-httplib_SOURCE_DIR}")

find_path(CPP_HTTPLIB_INCLUDE_DIRS "httplib.h")
target_include_directories(${RELLIC_XREF} PRIVATE ${CPP_HTTPLIB_INCLUDE_DIRS})

target_link_libraries(${RELLIC_XREF}
PRIVATE
"${PROJECT_NAME}_cxx_settings"
"${PROJECT_NAME}"
gflags::gflags
gflags
)
Comment on lines +60 to 76
Copy link
Contributor

@ekilmer ekilmer May 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this should be gated behind an option like

option(RELLIC_FIND_ALL_EXTERNAL_DEPENDENCIES "Use find_package for ALL dependencies" OFF)

in cmake/options.cmake. At least let the user choose to provide their own cpp-httplib, even if it's untested by default. Most users won't care, which is fine, and it'll do the right thing because it's OFF by default.

Also, we should use the target httplib::httplib instead of CPP_HTTPLIB_INCLUDE_DIRS.


set(RELLIC_XREF "${RELLIC_XREF}" PARENT_SCOPE)
Expand Down Expand Up @@ -98,7 +106,7 @@ target_link_libraries(${RELLIC_REPL}
PRIVATE
"${PROJECT_NAME}_cxx_settings"
"${PROJECT_NAME}"
gflags::gflags
gflags
linenoise
)

Expand All @@ -117,7 +125,7 @@ target_link_libraries(${RELLIC_DEC2HEX}
PRIVATE
"${PROJECT_NAME}_cxx_settings"
"${PROJECT_NAME}"
gflags::gflags
gflags
)

set(RELLIC_DEC2HEX "${RELLIC_DEC2HEX}" PARENT_SCOPE)
Expand Down
6 changes: 3 additions & 3 deletions tools/decomp/Decomp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ DEFINE_bool(lower_switch, false,
DECLARE_bool(version);

namespace {
static llvm::Optional<llvm::APInt> GetPCMetadata(llvm::Value* value) {
static std::optional<llvm::APInt> GetPCMetadata(llvm::Value* value) {
auto inst{llvm::dyn_cast<llvm::Instruction>(value)};
if (!inst) {
return llvm::Optional<llvm::APInt>();
return std::nullopt;
}

auto pc{inst->getMetadata("pc")};
if (!pc) {
return llvm::Optional<llvm::APInt>();
return std::nullopt;
}

auto& cop{pc->getOperand(0U)};
Expand Down
Loading
Loading