diff options
Diffstat (limited to 'node/FunctionNode.cc')
| -rw-r--r-- | node/FunctionNode.cc | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc new file mode 100644 index 0000000..3346db0 --- /dev/null +++ b/node/FunctionNode.cc @@ -0,0 +1,69 @@ +#include <memory> +#include <vector> + +#include <llvm/IR/IRBuilder.h> + +#include "DeclNode.hh" +#include "FunctionNode.hh" + +namespace pcc { +FunctionNode::FunctionNode( + Context* context, std::string name, std::list<Declaration> arguments, + std::list<std::shared_ptr<BaseNode>> LocalDeclarations, + std::shared_ptr<Type> type, std::shared_ptr<StatementListNode> body) + : BaseNode(context) + , name_(name) + , arguments_(arguments) + , LocalDeclarations_(LocalDeclarations) + , type_(type) + , locals_(context->GetGlobals()) + , body_(body) { + for (auto& decl : LocalDeclarations_) { + std::shared_ptr<VarDeclNode> VarDecl = + std::dynamic_pointer_cast<VarDeclNode>(decl); + if (VarDecl != nullptr) { + // set the inherited attribute + VarDecl->SetScope(&locals_); + } + } +} + +Value FunctionNode::CodeGen() { + llvm::Module* module = context_->GetModule(); + llvm::IRBuilder<>* builder = context_->GetBuilder(); + std::vector<llvm::Type*> params(arguments_.size()); + std::transform(arguments_.cbegin(), arguments_.cend(), params.begin(), + [](const Declaration& decl) { + return std::get<1>(decl)->GetLLVMType(); + }); + llvm::Type* type = + llvm::FunctionType::get(type_->GetLLVMType(), params, false); + llvm::FunctionCallee f = module->getOrInsertFunction(name_, type); + llvm::Function* function = llvm::cast<llvm::Function>(f.getCallee()); + function->setCallingConv(llvm::CallingConv::C); + llvm::BasicBlock* block = + llvm::BasicBlock::Create(GlobalLLVMContext, name_, function); + builder->SetInsertPoint(block); + // alloc arguments + llvm::Function::arg_iterator ArgIt; + for (auto& arg : arguments_) { + Value ArgValue = builder->CreateAlloca(std::get<1>(arg)->GetLLVMType()); + builder->CreateStore(ArgIt++, ArgValue); + locals_.Add(std::get<0>(arg), {std::get<1>(arg), ArgValue}); + } + // alloc local variables + for (auto& decl : LocalDeclarations_) { + decl->CodeGen(); + } + // create a variable with the same name as the function for return value + Value rv = builder->CreateAlloca(type_->GetLLVMType()); + locals_.Add(name_, {type_, rv}); + // push the function scope variables + context_->PushScope(&locals_); + body_->CodeGen(); + builder->CreateRet(rv); + context_->PopScope(); + return nullptr; +} + +} // namespace pcc |
