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
86 changes: 83 additions & 3 deletions src/frontend/cxx/frontend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <cxx/gcc_linux_toolchain.h>
#include <cxx/lexer.h>
#include <cxx/macos_toolchain.h>
#include <cxx/memory_layout.h>
#include <cxx/preprocessor.h>
#include <cxx/private/path.h>
#include <cxx/scope.h>
Expand All @@ -43,7 +44,12 @@
#include <cxx/mlir/cxx_dialect.h>
#include <cxx/mlir/cxx_dialect_conversions.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/Pass.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>
#endif

#include <format>
Expand Down Expand Up @@ -81,6 +87,10 @@ struct Frontend::Private {
return cli.opt_emit_ir || cli.opt_emit_llvm || cli.opt_S || cli.opt_c;
}

[[nodiscard]] auto needsLLVMIR() const -> bool {
return cli.opt_emit_llvm || cli.opt_S || cli.opt_c;
}

void prepare();
void preparePreprocessor();
void preprocess();
Expand All @@ -94,6 +104,8 @@ struct Frontend::Private {
void generateIR();
void emitIR();
void emitLLVMIR();
void emitCode();
void emitObjectFile();
void printPreprocessedText();
void dumpMacros(std::ostream& out);

Expand All @@ -109,7 +121,7 @@ struct Frontend::Private {
#ifdef CXX_WITH_MLIR
void withRawOutputStream(
const std::optional<std::string>& extension,
const std::function<void(llvm::raw_ostream&)>& action);
const std::function<void(llvm::raw_pwrite_stream&)>& action);
#endif
};

Expand Down Expand Up @@ -169,6 +181,7 @@ Frontend::Private::Private(Frontend& frontend, const CLI& cli,
actions_.emplace_back([this]() { generateIR(); });
actions_.emplace_back([this]() { emitIR(); });
actions_.emplace_back([this]() { emitLLVMIR(); });
actions_.emplace_back([this]() { emitCode(); });
}

Frontend::Private::~Private() {}
Expand Down Expand Up @@ -196,7 +209,7 @@ void Frontend::Private::withOutputStream(
#ifdef CXX_WITH_MLIR
void Frontend::Private::withRawOutputStream(
const std::optional<std::string>& extension,
const std::function<void(llvm::raw_ostream&)>& action) {
const std::function<void(llvm::raw_pwrite_stream&)>& action) {
auto explicitOutput = cli.getSingle("-o");

if (explicitOutput == "-" || (!explicitOutput.has_value() &&
Expand Down Expand Up @@ -507,7 +520,7 @@ void Frontend::Private::emitIR() {
}

void Frontend::Private::emitLLVMIR() {
if (!cli.opt_emit_llvm) return;
if (!needsLLVMIR()) return;

#ifdef CXX_WITH_MLIR
if (!module_) return;
Expand All @@ -522,9 +535,76 @@ void Frontend::Private::emitLLVMIR() {
return;
}

if (!cli.opt_emit_llvm) return;

shouldExit_ = true;

withRawOutputStream(
".ll", [&](llvm::raw_ostream& out) { llvmModule_->print(out, nullptr); });

#endif
}

void Frontend::Private::emitCode() {
if (!cli.opt_S && !cli.opt_c) return;
#ifdef CXX_WITH_MLIR
llvm::InitializeAllAsmPrinters();

auto triple = toolchain_->memoryLayout()->triple();

std::string error;
auto target = llvm::TargetRegistry::lookupTarget(triple, error);

if (!target) {
std::cerr << std::format("cxx: cannot find target for triple '{}': {}\n",
triple, error);
shouldExit_ = true;
exitStatus_ = EXIT_FAILURE;
return;
}

llvm::TargetOptions opt;

auto RM = std::optional<llvm::Reloc::Model>();

auto targetMachine =
target->createTargetMachine(triple, "generic", "", opt, RM);

if (!targetMachine) {
std::cerr << std::format("cxx: cannot create target machine for '{}': {}\n",
triple, error);
shouldExit_ = true;
exitStatus_ = EXIT_FAILURE;
return;
}

std::string extension;
if (cli.opt_S) {
extension = ".s";
} else if (cli.opt_c) {
extension = ".o";
}

withRawOutputStream(extension, [&](llvm::raw_pwrite_stream& out) {
llvm::legacy::PassManager pm;

llvm::CodeGenFileType fileType;
if (cli.opt_S) {
fileType = llvm::CodeGenFileType::AssemblyFile;
} else {
fileType = llvm::CodeGenFileType::ObjectFile;
}

if (targetMachine->addPassesToEmitFile(pm, out, nullptr, fileType)) {
std::cerr << "cxx: target machine cannot emit assembly\n";
shouldExit_ = true;
exitStatus_ = EXIT_FAILURE;
return;
}

pm.run(*llvmModule_);
out.flush();
});
#endif
}

Expand Down
5 changes: 5 additions & 0 deletions src/mlir/cxx/mlir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ target_link_libraries(cxx-mlir PUBLIC
MLIRLLVMToLLVMIRTranslation
MLIRPass
MLIRTargetLLVMIRExport
MLIRTargetLLVMIRImport
MLIRTransforms
)

if (EMSCRIPTEN)
target_link_libraries(cxx-mlir PUBLIC LLVMWebAssemblyCodeGen)
endif()

target_compile_definitions(cxx-mlir PUBLIC CXX_WITH_MLIR)

add_dependencies(cxx-mlir MLIRCxxOpsIncGen)
Expand Down
4 changes: 2 additions & 2 deletions src/mlir/cxx/mlir/CxxOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def Cxx_Dialect : Dialect {
let name = "cxx";
let cppNamespace = "mlir::cxx";
let useDefaultTypePrinterParser = 1;
let dependentDialects = ["mlir::cf::ControlFlowDialect" ];
let dependentDialects = ["mlir::cf::ControlFlowDialect", "mlir::DLTIDialect", "mlir::LLVM::LLVMDialect"];
}

class Cxx_Type<string name, string typeMnemonic, list<Trait> traits = []>
Expand Down Expand Up @@ -405,4 +405,4 @@ def Cxx_TodoStmtOp : Cxx_Op<"todo.stmt"> {
let arguments = (ins StringProp:$message);
let results = (outs);
let assemblyFormat = "$message attr-dict";
}
}
46 changes: 46 additions & 0 deletions src/mlir/cxx/mlir/codegen_units.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@
// cxx
#include <cxx/ast.h>
#include <cxx/ast_visitor.h>
#include <cxx/control.h>
#include <cxx/memory_layout.h>
#include <cxx/translation_unit.h>

// mlir
#include <llvm/IR/DataLayout.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/Support/Error.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>
#include <mlir/Dialect/DLTI/DLTI.h>
#include <mlir/Target/LLVMIR/Import.h>

#include <format>

namespace cxx {

namespace {
Expand Down Expand Up @@ -57,11 +70,44 @@ auto Codegen::operator()(UnitAST* ast) -> UnitResult {
}

auto Codegen::UnitVisitor::operator()(TranslationUnitAST* ast) -> UnitResult {
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargets();
llvm::InitializeAllTargetMCs();

auto loc = gen.builder_.getUnknownLoc();
auto name = gen.unit_->fileName();
auto module = gen.builder_.create<mlir::ModuleOp>(loc, name);
gen.builder_.setInsertionPointToStart(module.getBody());

auto memoryLayout = gen.control()->memoryLayout();

auto triple = gen.control()->memoryLayout()->triple();

std::string error;
auto target = llvm::TargetRegistry::lookupTarget(triple, error);

if (!target) {
cxx_runtime_error(std::format("failed to find target for triple '{}': {}",
triple, error));
}

llvm::TargetOptions opt;

auto RM = std::optional<llvm::Reloc::Model>();

auto targetMachine =
target->createTargetMachine(triple, "generic", "", opt, RM);

auto llvmDataLayout = targetMachine->createDataLayout();

auto dataLayout =
mlir::translateDataLayout(llvmDataLayout, module->getContext());

module->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dataLayout);

module->setAttr("cxx.triple", mlir::StringAttr::get(module->getContext(),
memoryLayout->triple()));

std::swap(gen.module_, module);

ForEachExternalDefinition forEachExternalDefinition;
Expand Down
2 changes: 2 additions & 0 deletions src/mlir/cxx/mlir/cxx_dialect.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
// mlir
#include <llvm/ADT/TypeSwitch.h>
#include <mlir/Dialect/ControlFlow/IR/ControlFlowOps.h>
#include <mlir/Dialect/DLTI/DLTI.h>
#include <mlir/Dialect/Func/IR/FuncOps.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/Dialect/SCF/IR/SCF.h>
#include <mlir/IR/Builders.h>
#include <mlir/IR/DialectImplementation.h>
Expand Down
7 changes: 4 additions & 3 deletions src/mlir/cxx/mlir/cxx_dialect_conversions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
#include <cxx/mlir/cxx_dialect.h>

// mlir
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/Error.h>
#include <mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h>
#include <mlir/Conversion/LLVMCommon/TypeConverter.h>
#include <mlir/Dialect/ControlFlow/IR/ControlFlowOps.h>
#include <mlir/Dialect/DLTI/DLTI.h>
#include <mlir/Dialect/LLVMIR/LLVMDialect.h>
#include <mlir/Pass/Pass.h>
#include <mlir/Pass/PassManager.h>
Expand Down Expand Up @@ -1085,6 +1088,7 @@ class CxxToLLVMLoweringPass
auto getArgument() const -> StringRef override { return "cxx-to-llvm"; }

void getDependentDialects(DialectRegistry &registry) const override {
registry.insert<DLTIDialect>();
registry.insert<LLVM::LLVMDialect>();
}

Expand All @@ -1097,9 +1101,6 @@ void CxxToLLVMLoweringPass::runOnOperation() {
auto context = &getContext();
auto module = getOperation();

// set up the data layout
DataLayout dataLayout(module);

// set up the type converter
LLVMTypeConverter typeConverter{context};

Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/gcc_linux_toolchain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ GCCLinuxToolchain::GCCLinuxToolchain(Preprocessor* preprocessor,
: Toolchain(preprocessor), arch_(std::move(arch)) {
if (arch_ == "aarch64") {
memoryLayout()->setSizeOfLongDouble(8);
memoryLayout()->setTriple("aarch64-linux");
} else if (arch_ == "x86_64") {
memoryLayout()->setSizeOfLongDouble(16);
memoryLayout()->setTriple("x86_64-linux");
} else {
cxx_runtime_error(std::format("Unsupported architecture: {}", arch_));
}
Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/macos_toolchain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ MacOSToolchain::MacOSToolchain(Preprocessor* preprocessor, std::string arch)

if (arch_ == "aarch64") {
memoryLayout()->setSizeOfLongDouble(8);
memoryLayout()->setTriple("aarch64-darwin");
} else if (arch_ == "x86_64") {
memoryLayout()->setSizeOfLongDouble(16);
memoryLayout()->setTriple("x86_64-apple-darwin24.6.0");
} else {
cxx_runtime_error(std::format("Unsupported architecture: {}", arch_));
}
Expand Down
6 changes: 6 additions & 0 deletions src/parser/cxx/memory_layout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,10 @@ auto MemoryLayout::alignmentOf(const Type* type) const
return visit(AlignmentOf{*this}, type);
}

auto MemoryLayout::triple() const -> const std::string& { return triple_; }

void MemoryLayout::setTriple(std::string triple) {
triple_ = std::move(triple);
}

} // namespace cxx
4 changes: 4 additions & 0 deletions src/parser/cxx/memory_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,16 @@ class MemoryLayout {
[[nodiscard]] auto alignmentOf(const Type* type) const
-> std::optional<std::size_t>;

[[nodiscard]] auto triple() const -> const std::string&;
void setTriple(std::string triple);

private:
std::size_t bits_ = 0;
std::size_t sizeOfPointer_ = 0;
std::size_t sizeOfLong_ = 0;
std::size_t sizeOfLongLong_ = 0;
std::size_t sizeOfLongDouble_ = 0;
std::string triple_;
};

#undef DECLARE_METHOD
Expand Down
1 change: 1 addition & 0 deletions src/parser/cxx/wasm32_wasi_toolchain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Wasm32WasiToolchain::Wasm32WasiToolchain(Preprocessor* preprocessor)
setMemoryLayout(std::make_unique<MemoryLayout>(32));
memoryLayout()->setSizeOfLongDouble(16);
memoryLayout()->setSizeOfLongLong(8);
memoryLayout()->setTriple("wasm32");
}

auto Wasm32WasiToolchain::appdir() const -> const std::string& {
Expand Down
8 changes: 8 additions & 0 deletions src/parser/cxx/windows_toolchain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ WindowsToolchain::WindowsToolchain(Preprocessor *preprocessor,
memoryLayout()->setSizeOfLongLong(8);
memoryLayout()->setSizeOfLongDouble(8);
memoryLayout()->setSizeOfPointer(8);

if (arch_ == "aarch64") {
memoryLayout()->setTriple("aarch64-windows");
} else if (arch_ == "x86_64") {
memoryLayout()->setTriple("x86_64-windows");
} else {
cxx_runtime_error(std::format("Unsupported architecture: {}", arch_));
}
}

void WindowsToolchain::setVctoolsdir(std::string path) {
Expand Down
Loading