Skip to content
Merged
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: 9 additions & 1 deletion include/patchestry/AST/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,15 @@ namespace patchestry::ast {
/// leaving the subtree shared — acceptable because subtree sharing
/// is then handled by downstream ClangEmitter cloning).
clang::Expr *CloneExpr(clang::ASTContext &ctx, clang::Expr *expr);


/// IntegerLiteral whose type StmtPrinter can print. _Bool/char8_16_32/enum
/// (or any non-builtin) crash StmtPrinter; for those, a same-width standard
/// integer is used (callers convert as usual, so semantics are unchanged).
clang::Expr *MakeIntLiteralPrintable(
clang::ASTContext &ctx, uint64_t value, clang::QualType operand_type,
bool is_signed, clang::SourceLocation loc
);

clang::SourceLocation SourceLocation(clang::SourceManager &sm, std::string key);

/// Returns a valid SourceLocation backed by a virtual "<patchestry-virtual>"
Expand Down
32 changes: 24 additions & 8 deletions include/patchestry/Util/Log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,31 @@

enum LogLevel { DEBUG, INFO, WARNING, ERROR, FATAL };

namespace patchestry::logging {
// Min level a LOG() must meet to emit (glog-style). Default DEBUG keeps the
// historical "print everything" behavior for tools that don't opt in;
// patchir-decomp raises it to WARNING (INFO off) unless --verbose.
inline LogLevel &MinLogLevel() {
static LogLevel level = DEBUG;
return level;
}
// Sink for suppressed levels.
inline llvm::raw_ostream &NullLogStream() {
static llvm::raw_null_ostream stream;
return stream;
}
} // namespace patchestry::logging

#define LOG(level) \
(((level) == DEBUG) ? llvm::outs() << "[DEBUG] " \
: ((level) == INFO) ? llvm::outs() << "[INFO] " \
: ((level) == WARNING) ? llvm::outs() << "[WARNING] " \
: ((level) == FATAL) ? llvm::errs() << "[FATAL] " \
: ((level) == ERROR) ? llvm::errs() << "[ERROR] " \
: llvm::outs() \
) << "(" \
<< __FILE__ << ":" << __LINE__ << ") "
(((level) < ::patchestry::logging::MinLogLevel()) \
? ::patchestry::logging::NullLogStream() \
: ((((level) == DEBUG) ? llvm::outs() << "[DEBUG] " \
: ((level) == INFO) ? llvm::outs() << "[INFO] " \
: ((level) == WARNING) ? llvm::outs() << "[WARNING] " \
: ((level) == FATAL) ? llvm::errs() << "[FATAL] " \
: ((level) == ERROR) ? llvm::errs() << "[ERROR] " \
: llvm::outs()) \
<< "(" << __FILE__ << ":" << __LINE__ << ") "))

#define LOG_FATAL(...) \
do { \
Expand Down
15 changes: 6 additions & 9 deletions lib/patchestry/AST/BuildSNodeFromRegion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ namespace patchestry::ast {
case_type = case_type->castAs< clang::EnumType >()
->getDecl()->getIntegerType();
}
unsigned case_width = ctx_.getIntWidth(case_type);

auto *sw = factory_.Make< SSwitch >(disp.branch_cond);

Expand Down Expand Up @@ -527,10 +526,9 @@ namespace patchestry::ast {
const size_t body_pos = total_labels - 1;
size_t pos = 0;
for (std::int64_t v : arm.values) {
auto *val = clang::IntegerLiteral::Create(
ctx_,
llvm::APInt(case_width, static_cast< uint64_t >(v), true),
case_type, VirtualLoc(ctx_));
auto *val = MakeIntLiteralPrintable(
ctx_, static_cast< uint64_t >(v), case_type,
/*is_signed=*/true, VirtualLoc(ctx_));
if (pos == body_pos) {
sw->AddCase(val, *body_seq);
} else {
Expand Down Expand Up @@ -572,10 +570,9 @@ namespace patchestry::ast {
const size_t body_pos = total_labels - 1;
size_t pos = 0;
for (std::int64_t v : arm.values) {
auto *val = clang::IntegerLiteral::Create(
ctx_,
llvm::APInt(case_width, static_cast< uint64_t >(v), true),
case_type, VirtualLoc(ctx_));
auto *val = MakeIntLiteralPrintable(
ctx_, static_cast< uint64_t >(v), case_type,
/*is_signed=*/true, VirtualLoc(ctx_));
if (pos == body_pos) {
sw->AddCase(val, std::vector< SNode * >{terminator});
} else {
Expand Down
33 changes: 15 additions & 18 deletions lib/patchestry/AST/OperationStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ namespace patchestry::ast {

auto param_type = param->getType();
if (param_type->isIntegerType()) {
return new (ctx) clang::IntegerLiteral(
ctx, llvm::APInt(ctx.getIntWidth(param_type), 0), param_type,
// param_type may be _Bool/enum (crash StmtPrinter).
return MakeIntLiteralPrintable(
ctx, 0, param_type, param_type->isSignedIntegerType(),
VirtualLoc(ctx)
);
} else if (param_type->isFloatingType()) {
Expand Down Expand Up @@ -1237,13 +1238,12 @@ namespace patchestry::ast {
disc_type = disc_type->castAs< clang::EnumType >()
->getDecl()->getIntegerType();
}
const auto disc_width = ctx.getIntWidth(disc_type);

auto create_case = [&](const SwitchCase &sc) -> clang::CaseStmt * {
auto *case_val = clang::IntegerLiteral::Create(
ctx,
llvm::APInt(disc_width, static_cast< uint64_t >(sc.value), /*isSigned=*/true),
disc_type, loc
// disc_type may be _Bool/char32_t (enum lowered above).
auto *case_val = MakeIntLiteralPrintable(
ctx, static_cast< uint64_t >(sc.value), disc_type,
/*is_signed=*/true, loc
);
auto *case_stmt =
clang::CaseStmt::Create(ctx, case_val, nullptr, loc, loc, loc);
Expand Down Expand Up @@ -1392,7 +1392,6 @@ namespace patchestry::ast {
clang::SwitchStmt::Create(ctx, nullptr, nullptr, disc_expr, loc, loc);

std::vector< clang::Stmt * > sw_body;
const auto disc_width = ctx.getIntWidth(disc_type);
for (const auto &block_key : op.successor_blocks) {
if (!function_builder().labels_declaration.contains(block_key)) {
continue;
Expand All @@ -1401,8 +1400,8 @@ namespace patchestry::ast {
if (!maybe_addr) {
continue;
}
auto *case_val = clang::IntegerLiteral::Create(
ctx, llvm::APInt(disc_width, *maybe_addr), disc_type, loc
auto *case_val = MakeIntLiteralPrintable(
ctx, *maybe_addr, disc_type, /*is_signed=*/false, loc
);
auto *case_stmt =
clang::CaseStmt::Create(ctx, case_val, nullptr, loc, loc, loc);
Expand Down Expand Up @@ -2672,8 +2671,8 @@ namespace patchestry::ast {
// getIntWidth(type).
unsigned operand_bits = ctx.getIntWidth(expr->getType());
if (operand_bits != 0 && shift_bits >= operand_bits) {
result_expr = clang::IntegerLiteral::Create(
ctx, llvm::APInt(operand_bits, 0), expr->getType(), op_location
result_expr = MakeIntLiteralPrintable(
ctx, 0, expr->getType(), /*is_signed=*/false, op_location
);
} else if (shift_bits != 0) {
// Apply right-shift only when byte_offset > 0 (skip ">> 0").
Expand Down Expand Up @@ -2996,9 +2995,8 @@ namespace patchestry::ast {
assert(!and_result.isInvalid() && "Failed to create and operation");

// scarry = and_result < 0
auto *zero = clang::IntegerLiteral::Create(
ctx, llvm::APInt(ctx.getIntWidth(input0->getType()), 0, true), input0->getType(),
op_loc
auto *zero = MakeIntLiteralPrintable(
ctx, 0, input0->getType(), /*is_signed=*/true, op_loc
);
auto scarry = sema().BuildBinOp(
sema().getCurScope(), op_loc, clang::BO_LT, and_result.getAs< clang::Expr >(),
Expand Down Expand Up @@ -3067,9 +3065,8 @@ namespace patchestry::ast {
assert(!and_result.isInvalid() && "Failed to create and operation");

// sborrow = and_result < 0
auto *zero = clang::IntegerLiteral::Create(
ctx, llvm::APInt(ctx.getIntWidth(input0->getType()), 0, true), input0->getType(),
op_loc
auto *zero = MakeIntLiteralPrintable(
ctx, 0, input0->getType(), /*is_signed=*/true, op_loc
);
auto sborrow = sema().BuildBinOp(
sema().getCurScope(), op_loc, clang::BO_LT, and_result.getAs< clang::Expr >(),
Expand Down
46 changes: 46 additions & 0 deletions lib/patchestry/AST/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,52 @@ namespace patchestry::ast {
);
}

clang::Expr *MakeIntLiteralPrintable(
clang::ASTContext &ctx, uint64_t value, clang::QualType operand_type,
bool is_signed, clang::SourceLocation loc
) {
auto printable = [](clang::QualType t) -> bool {
const auto *bt = t->getAs< clang::BuiltinType >();
if (bt == nullptr) {
return false;
}
switch (bt->getKind()) {
case clang::BuiltinType::Char_S:
case clang::BuiltinType::Char_U:
case clang::BuiltinType::SChar:
case clang::BuiltinType::UChar:
case clang::BuiltinType::Short:
case clang::BuiltinType::UShort:
case clang::BuiltinType::Int:
case clang::BuiltinType::UInt:
case clang::BuiltinType::Long:
case clang::BuiltinType::ULong:
case clang::BuiltinType::LongLong:
case clang::BuiltinType::ULongLong:
case clang::BuiltinType::Int128:
case clang::BuiltinType::UInt128:
case clang::BuiltinType::WChar_S:
case clang::BuiltinType::WChar_U:
return true;
default:
return false;
}
};
// getIntWidth() asserts on non-integer types; fall back to int.
const bool integral =
!operand_type.isNull() && operand_type->isIntegralOrEnumerationType();
clang::QualType lit_type = operand_type;
if (!integral || !printable(operand_type)) {
unsigned w = integral ? ctx.getIntWidth(operand_type) : 32U;
auto t = ctx.getIntTypeForBitwidth(w <= 1U ? 32U : w, is_signed);
lit_type = t.isNull() ? (is_signed ? ctx.IntTy : ctx.UnsignedIntTy) : t;
}
unsigned lw = ctx.getIntWidth(lit_type);
return clang::IntegerLiteral::Create(
ctx, llvm::APInt(lw, value, is_signed), lit_type, loc
);
}

clang::Expr *CloneExpr(clang::ASTContext &ctx, clang::Expr *expr) {
if (!expr) return nullptr;

Expand Down
3 changes: 3 additions & 0 deletions tools/patchir-decomp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ namespace {
argc, argv, "patche-lifter to represent high pcode into mlir representations\n"
);

// --verbose enables DEBUG/INFO; otherwise only WARNING/ERROR/FATAL.
::patchestry::logging::MinLogLevel() = verbose.getValue() ? DEBUG : WARNING;

return {
.emit_cir = emit_cir.getValue(),
.emit_mlir = emit_mlir.getValue(), // It is set to true by default
Expand Down
Loading