diff options
| author | Nagi5Yeq <wu@x-nagi.com> | 2020-05-31 17:49:34 +0800 |
|---|---|---|
| committer | Nagi5Yeq <wu@x-nagi.com> | 2020-05-31 17:49:34 +0800 |
| commit | c2c6e5c7e620c32e7f420e8b9ac21df8855b444c (patch) | |
| tree | c790ec3650c2f6caed9b59b304bc6a8bbdef1da8 /node | |
| parent | 4a5bc55769804d003d6cd9f8c16eefb76bb53d1b (diff) | |
support for extern functions
Diffstat (limited to 'node')
| -rw-r--r-- | node/BaseNode.cc | 1 | ||||
| -rw-r--r-- | node/ExprNode.cc | 28 | ||||
| -rw-r--r-- | node/FunctionNode.cc | 30 | ||||
| -rw-r--r-- | node/FunctionNode.hh | 12 |
4 files changed, 62 insertions, 9 deletions
diff --git a/node/BaseNode.cc b/node/BaseNode.cc index 8391322..a923498 100644 --- a/node/BaseNode.cc +++ b/node/BaseNode.cc @@ -14,6 +14,7 @@ ProgramNode::ProgramNode( , functions_(std::move(functions)) {} Value ProgramNode::CodeGen() { + context_->GetModule()->setModuleIdentifier(name_); for (auto&& decl : GlobalDeclarations_) { decl->CodeGen(); } diff --git a/node/ExprNode.cc b/node/ExprNode.cc index 13a85e9..e75eda5 100644 --- a/node/ExprNode.cc +++ b/node/ExprNode.cc @@ -124,7 +124,7 @@ Value ArrayAccessNode::CodeGen() { if (array != nullptr) { std::shared_ptr<Type> IndexType = array->GetIndexType(); Value indices[2] = {llvm::ConstantInt::get( - manager->GetPointerIndexType_()->GetLLVMType(), 0)}; + manager->GetPointerIndexType()->GetLLVMType(), 0)}; if (array->GetIsZeroStarted() == false) { Value ConvertedRight = manager->CreateCast(IndexType, RightType, right, context_); @@ -167,7 +167,7 @@ Value DereferenceNode::CodeGen() { return nullptr; } Value zero = llvm::ConstantInt::get( - context_->GetTypeManager()->GetPointerIndexType_()->GetLLVMType(), 0); + context_->GetTypeManager()->GetPointerIndexType()->GetLLVMType(), 0); type_ = pointer; return context_->GetBuilder()->CreateInBoundsGEP(value, zero); } @@ -201,7 +201,7 @@ Value MemberAccessNode::CodeGen() { int MemberIndex; std::shared_ptr<Type> MemberType; std::tie(MemberIndex, MemberType) = LeftInner->GetMember(rhs_); - llvm::Type* IndexLLLVMType = manager->GetPointerIndexType_()->GetLLVMType(); + llvm::Type* IndexLLLVMType = manager->GetPointerIndexType()->GetLLVMType(); Value indices[2] = {llvm::ConstantInt::get(IndexLLLVMType, 0), llvm::ConstantInt::get(IndexLLLVMType, MemberIndex)}; type_ = manager->GetPointerType(MemberType); @@ -234,21 +234,31 @@ Value FunctionCallNode::CodeGen() { return nullptr; } const std::vector<std::shared_ptr<Type>>& ArgTypes = type->GetArgTypes(); + if (type->IsVariadic() == false && ArgTypes.size() != args_.size()) { + Log(LogLevel ::PCC_ERROR, + "argument number mismatch, %d wanted, %d given", ArgTypes.size(), + args_.size()); + return nullptr; + } std::vector<Value> ArgValues(args_.size()); - auto ArgTypeIt = ArgTypes.begin(); + auto ArgIt = args_.begin(); auto ArgValueIt = ArgValues.begin(); - for (auto&& arg : args_) { - Value argv = arg->CodeGen(); + for (auto&& ArgType : ArgTypes) { + Value argv = (*ArgIt)->CodeGen(); Value ConvertedArgv = - manager->CreateCast(*ArgTypeIt, arg->GetType(), argv, context_); + manager->CreateCast(ArgType, (*ArgIt)->GetType(), argv, context_); if (ConvertedArgv == nullptr) { Log(LogLevel ::PCC_ERROR, "argument type mismatch, the function type is %s, an argument " "of type %s needed", - type->GetCommonName(), (*ArgTypeIt)->GetCommonName()); + type->GetCommonName(), ArgType->GetCommonName()); } *ArgValueIt = ConvertedArgv; - ++ArgTypeIt, ++ArgValueIt; + ++ArgIt, ++ArgValueIt; + } + while (ArgIt != args_.end()) { + *ArgValueIt = (*ArgIt)->CodeGen(); + ++ArgIt, ++ArgValueIt; } type_ = type->GetReturnType(); return context_->GetBuilder()->CreateCall(std::get<1>(function), ArgValues); diff --git a/node/FunctionNode.cc b/node/FunctionNode.cc index 97b1680..4fb5138 100644 --- a/node/FunctionNode.cc +++ b/node/FunctionNode.cc @@ -91,4 +91,34 @@ Value FunctionNode::CodeGen() { return nullptr; } +ExternNode::ExternNode(Context* context, std::string&& name, + std::list<Declaration>&& arguments, + std::shared_ptr<TypeIdentifier> ReturnTypeIdentifier, + bool IsVariadic) + : FunctionNode(context, std::move(name), std::move(arguments), + std::list<std::shared_ptr<DeclNode>>(), ReturnTypeIdentifier, + nullptr) + , IsVariadic_(IsVariadic) {} + +Value ExternNode::CodeGen() { + llvm::Module* module = context_->GetModule(); + llvm::IRBuilder<>* builder = context_->GetBuilder(); + TypeManager* manager = context_->GetTypeManager(); + std::vector<std::shared_ptr<Type>> params(arguments_.size()); + std::transform( + arguments_.cbegin(), arguments_.cend(), params.begin(), + [](const Declaration& decl) { return std::get<1>(decl)->GetType(); }); + std::shared_ptr<Type> ReturnType = ReturnTypeIdentifier_->GetType(); + std::shared_ptr<FunctionType> type = + manager->CreateFunctionType(ReturnType, params, IsVariadic_); + llvm::FunctionType* LLVMType = + llvm::cast<llvm::FunctionType>(type->GetLLVMType()); + llvm::FunctionCallee callee = module->getOrInsertFunction(name_, LLVMType); + llvm::Function* function = llvm::cast<llvm::Function>(callee.getCallee()); + function->setCallingConv(llvm::CallingConv::C); + context_->AddFunction(name_, {type, function}); + Log(LogLevel::PCC_INFO, "extern function %s of type %s", name_.c_str(), + type->GetCommonName()); + return nullptr; +} } // namespace pcc diff --git a/node/FunctionNode.hh b/node/FunctionNode.hh index e939121..6860c45 100644 --- a/node/FunctionNode.hh +++ b/node/FunctionNode.hh @@ -25,6 +25,18 @@ class FunctionNode : public BaseNode { VariableList locals_; std::shared_ptr<StatementListNode> body_; }; + +class ExternNode : public FunctionNode { + public: + ExternNode(Context* context, std::string&& name, + std::list<Declaration>&& arguments, + std::shared_ptr<TypeIdentifier> ReturnTypeIdentifier, + bool IsVariadic); + virtual Value CodeGen() override; + + protected: + bool IsVariadic_; +}; } // namespace pcc #endif |
