diff --git a/BitcodeEmitter.cpp b/BitcodeEmitter.cpp index f0d128a..e7078c9 100644 --- a/BitcodeEmitter.cpp +++ b/BitcodeEmitter.cpp @@ -18,14 +18,28 @@ */ #include "BitcodeEmitter.hpp" +#include "Scope.hpp" #include "Nodes.hpp" +#include +#include +#include +#include +#include + + using namespace monicelli; +using llvm::getGlobalContext; struct BitcodeEmitter::Private { + llvm::Value *expval = nullptr; + llvm::Module *module = nullptr; + + llvm::IRBuilder<> builder = llvm::IRBuilder<>(getGlobalContext()); + Scope scope; }; -BitcodeEmitter::BitcodeEmitter() { +BitcodeEmitter::BitcodeEmitter(llvm::Module *module): module(module) { d = new Private; } @@ -34,6 +48,12 @@ BitcodeEmitter::~BitcodeEmitter() { } void BitcodeEmitter::emit(Return const& node) { + if (node.getExpression()) { + node.getExpression()->emit(this); + d->builder.CreateRet(d->expval); + } else { + d->builder.CreateRetVoid(); + } } void BitcodeEmitter::emit(Loop const& node) { @@ -60,36 +80,126 @@ void BitcodeEmitter::emit(Assert const& node) { void BitcodeEmitter::emit(FunctionCall const& node) { } -void BitcodeEmitter::emit(BranchCase const& node) { -} - void BitcodeEmitter::emit(Branch const& node) { } void BitcodeEmitter::emit(Main const& node) { + d->scope.enter(); + for (Statement const* statement: node.getBody()) { + statement->emit(this); + } + d->scope.leave(); } void BitcodeEmitter::emit(Function const& node) { } -void BitcodeEmitter::emit(Module const& node) { -} +void BitcodeEmitter::emit(Module const& node) {} -void BitcodeEmitter::emit(Program const& node) { +void BitcodeEmitter::emit(Program const& program) { + if (program.getMain()) { + program.getMain()->emit(this); + } + + for (Function const* function: program.getFunctions()) { + function->emit(this); + } + + // TODO modules } void BitcodeEmitter::emit(Id const& node) { + auto value = d->scope.lookup(&node); + + if (!value) { + // TODO errore + } + + d->expval = *value; } void BitcodeEmitter::emit(Integer const& node) { + d->expval = llvm::ConstantInt::get( + getGlobalContext(), llvm::APInt(64, node.getValue(), true) + ); } void BitcodeEmitter::emit(Float const& node) { + d->expval = llvm::ConstantFP::get( + getGlobalContext(), llvm::APFloat(node.getValue()) + ); } -void BitcodeEmitter::emit(BinaryExpression const& node) { +static inline +bool isFP(llvm::Value const* var) { + llvm::Type *type = var->getType(); + return type->isFloatTy() || type->isDoubleTy(); } -void BitcodeEmitter::emit(BinarySemiExpression const& node) { +#define HANDLE(intop, fpop) \ + if (fp) { \ + d->expval = d->builder.Create##fpop(left, right); \ + } else { \ + d->expval = d->builder.Create##intop(left, right); \ + } + +#define HANDLE_INT_ONLY(op) \ + if (fp) { \ + d->expval = nullptr; \ + } else { \ + d->expval = d->builder.Create##op(left, right); \ + } + + +// TODO Handle automatic casts +void BitcodeEmitter::emit(BinaryExpression const& expression) { + expression.getLeft().emit(this); + llvm::Value *left = d->expval; + + expression.getRight().emit(this); + llvm::Value *right = d->expval; + + bool fp = isFP(left) || isFP(right); + + // TODO left->getType() != right->getType() + + switch (expression.getOperator()) { + case Operator::PLUS: + HANDLE(Add, FAdd) + break; + case Operator::MINUS: + HANDLE(Sub, FSub) + break; + case Operator::TIMES: + HANDLE(Mul, FMul) + break; + case Operator::DIV: + HANDLE(SDiv, FDiv) + break; + case Operator::SHL: + HANDLE_INT_ONLY(Shl); + break; + case Operator::SHR: + HANDLE_INT_ONLY(LShr); + break; + case Operator::LT: + HANDLE(ICmpULT, FCmpULT) + break; + case Operator::GT: + HANDLE(ICmpUGT, FCmpUGT) + break; + case Operator::GTE: + HANDLE(ICmpUGE, FCmpUGE) + break; + case Operator::LTE: + HANDLE(ICmpULE, FCmpULE) + break; + case Operator::EQ: + HANDLE(ICmpEQ, FCmpOEQ) + break; + } } +#undef HANDLE +#undef HANDLE_INT_ONLY + diff --git a/BitcodeEmitter.hpp b/BitcodeEmitter.hpp index e96067c..9ab6899 100644 --- a/BitcodeEmitter.hpp +++ b/BitcodeEmitter.hpp @@ -22,11 +22,15 @@ #include "Emitter.hpp" +namespace llvm { + class Module; +} + namespace monicelli { class BitcodeEmitter: public Emitter { public: - BitcodeEmitter(); + BitcodeEmitter(llvm::Module *module); BitcodeEmitter(BitcodeEmitter &) = delete; virtual ~BitcodeEmitter(); @@ -54,7 +58,9 @@ public: private: struct Private; - Private const* d; + + llvm::Module *module; + Private *d; }; }