Skip to content

Commit

Permalink
codegen: Initial framework changes to emit hl-mlir and llvm ir
Browse files Browse the repository at this point in the history
  • Loading branch information
kumarak committed Jan 26, 2025
1 parent db62ae1 commit 14339a5
Show file tree
Hide file tree
Showing 26 changed files with 1,185 additions and 183 deletions.
4 changes: 3 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ Checks: "*,\
-google-build-using-namespace, \
-cppcoreguidelines-owning-memory, \
-readability-identifier-length, \
-readability-function-cognitive-complexity "
-readability-function-cognitive-complexity, \
-cppcoreguidelines-pro-type-const-cast, \
-clang-tidycppcoreguidelines-avoid-const-or-ref-data-members "
WarningsAsErrors: ''
CheckOptions:
- key: 'bugprone-argument-comment.StrictMode'
Expand Down
12 changes: 5 additions & 7 deletions include/patchestry/AST/ASTConsumer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#pragma once

#include "patchestry/Util/Options.hpp"
#include <functional>
#include <memory>
#include <unordered_map>
Expand Down Expand Up @@ -37,12 +38,9 @@ namespace patchestry::ast {
{
public:
explicit PcodeASTConsumer(
clang::CompilerInstance &ci, Program &prog, std::string &outfile
clang::CompilerInstance &ci, Program &prog, patchestry::Options &opts
)
: program(prog)
, ci(ci)
, outfile(outfile)
, type_builder(std::make_unique< TypeBuilder >(ci.getASTContext())) {}
: options(opts), program(prog), ci(ci), type_builder(nullptr) {}

void HandleTranslationUnit(clang::ASTContext &ctx) override;

Expand All @@ -65,10 +63,10 @@ namespace patchestry::ast {

clang::Sema &sema(void) const { return ci.get().getSema(); }

const patchestry::Options &options;

std::reference_wrapper< Program > program;
std::reference_wrapper< clang::CompilerInstance > ci;

std::string outfile;
std::unique_ptr< TypeBuilder > type_builder;

std::unordered_map< std::string, clang::FunctionDecl * > function_declarations;
Expand Down
3 changes: 2 additions & 1 deletion include/patchestry/AST/OperationBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ namespace patchestry::ast {
* occurs.
*/
clang::Expr *perform_explicit_cast(
clang::ASTContext &ctx, clang::Expr *expr, clang::QualType to_type
clang::ASTContext &ctx, clang::Expr *expr, clang::QualType to_type,
const std::string &location_key
);

clang::Stmt *create_varnode(
Expand Down
14 changes: 13 additions & 1 deletion include/patchestry/AST/TypeBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ namespace patchestry::ast {
static constexpr uint32_t num_bits_in_byte = 8U;
static constexpr uint32_t num_bits_uint = 32U;

explicit TypeBuilder(clang::ASTContext &ctx) : context(ctx), serialized_types({}) {}
explicit TypeBuilder(
clang::ASTContext &ctx, std::unordered_map< void *, std::string > &locations
)
: location_map(locations), context(ctx), serialized_types({}) {}

TypeBuilder &operator=(const TypeBuilder &) = delete;
TypeBuilder(const TypeBuilder &) = delete;
Expand All @@ -34,6 +37,13 @@ namespace patchestry::ast {

virtual ~TypeBuilder() = default;

template< typename T >
void set_location_key(T *pointer, const std::string &key) {
if (!location_map.get().contains(pointer)) {
location_map.get().emplace(pointer, key);
}
}

/**
* @brief Provides access to the serialized type map.
*
Expand Down Expand Up @@ -199,6 +209,8 @@ namespace patchestry::ast {

std::unordered_map< std::string, clang::Decl * > missing_type_definition;

std::reference_wrapper< std::unordered_map< void *, std::string > > location_map;

std::reference_wrapper< clang::ASTContext > context;
SerializedTypeMap serialized_types;
};
Expand Down
110 changes: 110 additions & 0 deletions include/patchestry/Codegen/Codegen.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2024, Trail of Bits, Inc.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#pragma once

#include "patchestry/Util/Options.hpp"
#include <mlir/IR/MLIRContext.h>
#include <unordered_map>

#include <clang/AST/ASTContext.h>
#include <clang/Frontend/CompilerInstance.h>
#include <mlir/Pass/PassRegistry.h>

#include <vast/Frontend/FrontendAction.hpp>
#include <vast/Frontend/Options.hpp>
#include <vast/Frontend/Targets.hpp>

namespace llvm {
class raw_fd_ostream;
} // namespace llvm

namespace patchestry::codegen {

using LocationMap = std::unordered_map< void *, std::string >;

class MLIRRegistryInitializer
{
public:
explicit MLIRRegistryInitializer(mlir::DialectRegistry &registry);
};

class CodegenInitializer
{
public:
// Delete copy and move constructors and assignment operators
CodegenInitializer(const CodegenInitializer &) = delete;
CodegenInitializer &operator=(const CodegenInitializer &) = delete;
CodegenInitializer(CodegenInitializer &&) noexcept = delete;
CodegenInitializer &operator=(CodegenInitializer &&) noexcept = delete;

// Public static method to access the singleton instance
static CodegenInitializer &getInstance() {
static CodegenInitializer instance(0);
return instance;
}

inline mlir::MLIRContext &context() const noexcept { return ctx; }

~CodegenInitializer();

private:
explicit CodegenInitializer(int /*unused*/);

// Members
mlir::DialectRegistry registry;
MLIRRegistryInitializer registry_initializer;
mutable mlir::MLIRContext ctx;
};

class CodeGenerator

{
public:
explicit CodeGenerator(clang::CompilerInstance &ci) : opts(vast::cc::options(ci)) {}

CodeGenerator(const CodeGenerator &) = delete;
CodeGenerator &operator=(const CodeGenerator &) = delete;
CodeGenerator(CodeGenerator &&) noexcept = delete;
CodeGenerator &operator=(CodeGenerator &&) noexcept = delete;

virtual ~CodeGenerator() = default;

void emit_tower(
clang::ASTContext &actx, const LocationMap &locations,
const patchestry::Options &options
);

void emit_source_ir(
clang::ASTContext &actx, const LocationMap &locations,
const patchestry::Options &options
);

private:
void process_mlir_module(
clang::ASTContext &actx, vast::cc::target_dialect target, vast::mlir_module mod
);

void emit_mlir_after_pipeline(
clang::ASTContext &actx, vast::mlir_module mod, const patchestry::Options &options
);

void emit_llvmir(
clang::ASTContext &actx, vast::mlir_module mod, const patchestry::Options &options
);

void emit_asm(
clang::ASTContext &actx, vast::mlir_module mod, const patchestry::Options &options
);

std::optional< vast::owning_mlir_module_ref >
emit_mlir(clang::ASTContext &ctx, const LocationMap &locations);

vast::cc::action_options opts;
};

} // namespace patchestry::codegen
47 changes: 47 additions & 0 deletions include/patchestry/Codegen/MetaGenerator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2024, Trail of Bits, Inc.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#pragma once

#include <clang/AST/ASTContext.h>
#include <mlir/IR/MLIRContext.h>

#define GAP_ENABLE_COROUTINES
#include <vast/CodeGen/CodeGenMetaGenerator.hpp>

#include <patchestry/Codegen/Codegen.hpp>

namespace patchestry::codegen {

struct MetaGen final : vast::cg::meta_generator
{
MetaGen(clang::ASTContext *actx, mlir::MLIRContext *mctx, const LocationMap &locs);

void *raw_pointer(const clang::Decl *decl) const;

void *raw_pointer(const clang::Stmt *stmt) const;

void *raw_pointer(const clang::Expr *expr) const;

mlir::Location location(const clang::Decl *decl) const override;

mlir::Location location(const clang::Stmt *stmt) const override;

mlir::Location location(const clang::Expr *expr) const override;

private:
uint64_t address_from_location(const std::string &str, char delimiter) const;

mlir::Location location(void *data, const clang::SourceLocation &loc) const;

clang::ASTContext *actx;

mlir::MLIRContext *mctx;
const LocationMap &locations;
};

} // namespace patchestry::codegen
31 changes: 31 additions & 0 deletions include/patchestry/Codegen/PassInstrumentation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2024, Trail of Bits, Inc.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#pragma once

#include <mlir/InitAllPasses.h>
#include <mlir/Pass/Pass.h>
#include <mlir/Pass/PassManager.h>
#include <mlir/Pass/PassRegistry.h>

namespace patchestry::codegen {

class PassInstrumentation : public mlir::PassInstrumentation
{
public:
explicit PassInstrumentation(bool enable_location_transform = false)
: location_transform(enable_location_transform) {}

void runAfterPass(mlir::Pass *pass, mlir::Operation *op) override;

void runBeforePass(mlir::Pass *pass, mlir::Operation *op) override;

private:
bool location_transform;
};

} // namespace patchestry::codegen
79 changes: 79 additions & 0 deletions include/patchestry/Codegen/PassManager.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Trail of Bits, Inc.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#pragma once

#include "patchestry/Util/Log.hpp"
#include <llvm/Support/LogicalResult.h>
#include <memory>

#include <mlir/IR/MLIRContext.h>
#include <mlir/Pass/Pass.h>
#include <mlir/Pass/PassManager.h>
#include <mlir/Pass/PassRegistry.h>
#include <unordered_map>

namespace patchestry::codegen {

inline std::string to_string(mlir::Pass *pass) {
std::string buffer;
llvm::raw_string_ostream os(buffer);
pass->printAsTextualPipeline(os);
return os.str();
}

class PassManagerBuilder
{
public:
explicit PassManagerBuilder(mlir::MLIRContext *context) : mctx(context) {
pm = std::make_unique< mlir::PassManager >(context);
}

void build_operation_map(const std::vector< std::string > &anchors) {
mlir::PassManager parser_pm(mctx);
for (const auto &anchor : anchors) {
if (llvm::failed(mlir::parsePassPipeline(anchor, parser_pm))) {
LOG(ERROR) << "Failed to parse anchor name";
}
}

for (auto &p : parser_pm.getPasses()) {
operation_names.emplace(
std::pair< std::string, std::string >(to_string(&p), p.getOpName()->str())
);
}
}

void add_passes(const std::vector< std::string > &anchors) {
build_operation_map(anchors);
for (const auto &step : anchors) {
auto operation_name = operation_names.at(step);
llvm::errs() << "Operation name for step: " << step << " -> " << operation_name
<< "\n";
if (operation_name == "core.module") {
auto &nested_pm = pm->nest(operation_name);
if (failed(mlir::parsePassPipeline(step, nested_pm))) {
llvm::errs() << "Failed to parse pipeline " << step << " for op "
<< operation_name << "\n";
}
} else if (operation_name == "builtin.module") {
if (failed(mlir::parsePassPipeline(step, *pm))) {
llvm::errs() << "Failed to parse pipeline " << step << " for op "
<< operation_name << "\n";
}
}
}
}

std::unique_ptr< mlir::PassManager > build() { return std::move(pm); }

private:
mlir::MLIRContext *mctx;
std::unique_ptr< mlir::PassManager > pm;
std::unordered_map< std::string, std::string > operation_names;
};
} // namespace patchestry::codegen
27 changes: 27 additions & 0 deletions include/patchestry/Codegen/Serializer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2024, Trail of Bits, Inc.
*
* This source code is licensed in accordance with the terms specified in
* the LICENSE file found in the root directory of this source tree.
*/

#pragma once

#include <vast/Util/Common.hpp>

namespace patchestry::codegen {

class Serializer
{
public:
static bool serializeToFile(vast::mlir_module mod, const std::string &filename);

static vast::mlir_module
deserializeFromFile(mlir::MLIRContext *mctx, const std::string &filename);

static std::string convertModuleToString(vast::mlir_module mod);

static vast::mlir_module
parseModuleFromString(mlir::MLIRContext *mctx, const std::string &module_string);
};
} // namespace patchestry::codegen
2 changes: 2 additions & 0 deletions include/patchestry/Util/Log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <llvm/Support/raw_ostream.h>

#define ENABLE_DEBUG

enum LogLevel { INFO, WARNING, ERROR };

#define LOG(level) \
Expand Down
Loading

0 comments on commit 14339a5

Please sign in to comment.