summaryrefslogtreecommitdiff
path: root/node
diff options
context:
space:
mode:
authorNagi5Yeq <wu@x-nagi.com>2020-05-31 17:49:34 +0800
committerNagi5Yeq <wu@x-nagi.com>2020-05-31 17:49:34 +0800
commitc2c6e5c7e620c32e7f420e8b9ac21df8855b444c (patch)
treec790ec3650c2f6caed9b59b304bc6a8bbdef1da8 /node
parent4a5bc55769804d003d6cd9f8c16eefb76bb53d1b (diff)
support for extern functions
Diffstat (limited to 'node')
-rw-r--r--node/BaseNode.cc1
-rw-r--r--node/ExprNode.cc28
-rw-r--r--node/FunctionNode.cc30
-rw-r--r--node/FunctionNode.hh12
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