#include "DSL/AST.h"
#include <llvm/IR/Module.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Function.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/IR/IRBuilder.h>
#include <memory>
#include <iostream>
llvm::Function* generateFunction(llvm::LLVMContext& context, llvm::Module& module, ASTNode* root) {
// Create function type: double ().
llvm::FunctionType* funcType = llvm::FunctionType::get(llvm::Type::getDoubleTy(context), false);
llvm::Function* function = llvm::Function::Create(funcType, llvm::Function::ExternalLinkage, "main_expr", module);
llvm::BasicBlock* block = llvm::BasicBlock::Create(context, "entry", function);
llvm::IRBuilder<> builder(block);
llvm::Value* retVal = root->codegen(builder);
if (!retVal) {
std::cerr << "Error generating code for the expression." << std::endl;
return nullptr;
}
builder.CreateRet(retVal);
if (llvm::verifyFunction(*function, &llvm::errs())) {
function->eraseFromParent();
return nullptr;
}
return function;
}
void optimizeModule(llvm::Module& module) {
llvm::legacy::PassManager passManager;
// Add some basic optimization passes.
// In a production compiler, you'd add many more!
passManager.add(llvm::createInstructionCombiningPass());
passManager.add(llvm::createReassociatePass());
passManager.add(llvm::createGVNPass());
passManager.add(llvm::createCFGSimplificationPass());
passManager.run(module);
}
After generating LLVM IR, we optimize it using LLVM’s pass managers. The above optimizeModule
function demonstrates adding a few standard optimization passes. In 2025, you might incorporate cutting-edge passes or even machine learning–based tuning for further enhancements.