aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CodeGen.cc112
-rw-r--r--lib/CodeGen/FunctionGen.cc24
2 files changed, 70 insertions, 66 deletions
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
index 581e4a9..1c019d9 100644
--- a/lib/CodeGen/CodeGen.cc
+++ b/lib/CodeGen/CodeGen.cc
@@ -211,6 +211,9 @@ const TypeInfo *CodeGen::getExprTypeInfo(ExprAST *Expr) const {
if (const BuiltinInfo *B = findBuiltin(Name)) {
return resolveType(B->ReturnTypeName);
}
+ if (const FuncSig *Sig = FuncGen->getSignature(Name)) {
+ return resolveType(Sig->ReturnTypeName);
+ }
Function *CalleeF = TheModule->getFunction(Name);
if (!CalleeF) return resolveType("INTEGER");
@@ -416,6 +419,14 @@ void CodeGen::compile(const std::vector<std::unique_ptr<StmtAST>> &Statements) {
BasicBlock *BB = BasicBlock::Create(*TheContext, "entry", F);
Builder->SetInsertPoint(BB);
+ // Pre-register every top-level FUNCTION/PROCEDURE prototype so calls may
+ // precede definitions.
+ for (const auto &Stmt : Statements) {
+ if (auto *FuncDef = dynamic_cast<FunctionDefAST*>(Stmt.get())) {
+ FuncGen->emitPrototype(FuncDef->getProto());
+ }
+ }
+
for (const auto &Stmt : Statements) {
emitStmt(Stmt.get());
}
@@ -578,39 +589,54 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
return StrConvHandler->emitStrToNum(emitExpr(Call->getArgs()[0].get()), true);
}
- Function *CalleeF = TheModule->getFunction(Call->getCallee());
std::vector<Value*> Args;
+ if (!marshalCallArgs(Name, Call->getArgs(), Args)) return nullptr;
+ return FuncGen->emitCallExpr(Call, Args);
+ }
- for (unsigned i = 0; i < Call->getArgs().size(); ++i) {
- ExprAST *ArgExpr = Call->getArgs()[i].get();
- bool IsByRef = false;
+ return nullptr;
+}
- if (CalleeF && i < CalleeF->arg_size()) {
- if (CalleeF->getArg(i)->getType()->isPointerTy()) {
- IsByRef = true;
- }
- }
+// Collects the arguments for a call to a user FUNCTION/PROCEDURE, dispatching
+// on the *declared* signature: BYREF parameters take the variable's alloca,
+// BYVAL parameters are evaluated and coerced to the declared parameter type.
+bool CodeGen::marshalCallArgs(const std::string &Callee,
+ const std::vector<std::unique_ptr<ExprAST>> &ArgExprs,
+ std::vector<Value*> &Out) {
+ const FuncSig *Sig = FuncGen->getSignature(Callee);
+ if (!Sig) {
+ reportError("Call to undefined function %s", Callee.c_str());
+ return false;
+ }
+ if (ArgExprs.size() != Sig->Params.size()) {
+ reportError("Incorrect # arguments passed to %s", Callee.c_str());
+ return false;
+ }
- if (IsByRef) {
- if (auto *Var = dynamic_cast<VariableExprAST*>(ArgExpr)) {
- Value *Ptr = getNamedValue(Var->getName());
- if (!Ptr) {
- reportError("Unknown variable %s in BYREF call", Var->getName().c_str());
- return nullptr;
- }
- Args.push_back(Ptr);
- } else {
- reportError("BYREF argument must be a variable.");
- return nullptr;
- }
- } else {
- Args.push_back(emitExpr(ArgExpr));
+ for (size_t i = 0; i < ArgExprs.size(); ++i) {
+ const std::string &TypeName = Sig->Params[i].first;
+ bool IsByRef = Sig->Params[i].second;
+ ExprAST *ArgExpr = ArgExprs[i].get();
+
+ if (IsByRef) {
+ auto *Var = dynamic_cast<VariableExprAST*>(ArgExpr);
+ if (!Var) {
+ reportError("BYREF argument to %s must be a variable", Callee.c_str());
+ return false;
+ }
+ Value *Ptr = getNamedValue(Var->getName());
+ if (!Ptr) {
+ reportError("Unknown variable %s in BYREF call", Var->getName().c_str());
+ return false;
}
+ Out.push_back(Ptr);
+ } else {
+ Value *V = coerceValueToType(emitExpr(ArgExpr), resolveType(TypeName));
+ if (!V) return false;
+ Out.push_back(V);
}
- return FuncGen->emitCallExpr(Call, Args);
}
-
- return nullptr;
+ return true;
}
void CodeGen::emitIfStmt(IfStmtAST *Stmt) {
@@ -775,35 +801,8 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
}
if (auto *Call = dynamic_cast<CallStmtAST*>(Stmt)) {
- Function *CalleeF = TheModule->getFunction(Call->getCallee());
std::vector<Value*> Args;
-
- for (unsigned i = 0; i < Call->getArgs().size(); ++i) {
- ExprAST *ArgExpr = Call->getArgs()[i].get();
- bool IsByRef = false;
-
- if (CalleeF && i < CalleeF->arg_size()) {
- if (CalleeF->getArg(i)->getType()->isPointerTy()) {
- IsByRef = true;
- }
- }
-
- if (IsByRef) {
- if (auto *Var = dynamic_cast<VariableExprAST*>(ArgExpr)) {
- Value *Ptr = getNamedValue(Var->getName());
- if (!Ptr) {
- reportError("Unknown variable %s in BYREF call", Var->getName().c_str());
- return;
- }
- Args.push_back(Ptr);
- } else {
- reportError("BYREF argument must be a variable.");
- return;
- }
- } else {
- Args.push_back(emitExpr(ArgExpr));
- }
- }
+ if (!marshalCallArgs(Call->getCallee(), Call->getArgs(), Args)) return;
FuncGen->emitCallStmt(Call, Args);
return;
}
@@ -899,7 +898,10 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
Value *Val = emitExpr(Out->getExpr());
const TypeInfo *TypeInfo = getExprTypeInfo(Out->getExpr());
- if (!TypeInfo) TypeInfo = resolveType("INTEGER");
+ if (!TypeInfo) {
+ reportError("Cannot infer the type of the OUTPUT expression");
+ return;
+ }
emitOutputValue(Val, TypeInfo, true);
return;
}
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc
index 0a22278..57454b1 100644
--- a/lib/CodeGen/FunctionGen.cc
+++ b/lib/CodeGen/FunctionGen.cc
@@ -41,7 +41,15 @@ void FunctionGen::createArgumentAllocas(Function *F, const std::vector<std::tupl
}
}
+const FuncSig *FunctionGen::getSignature(const std::string &Name) const {
+ auto It = Signatures.find(Name);
+ return It == Signatures.end() ? nullptr : &It->second;
+}
+
Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
+ FuncSig Sig;
+ Sig.ReturnTypeName = Proto->getReturnType();
+
std::vector<Type*> ArgTypes;
for (const auto &Arg : Proto->getArgs()) {
Type *T = getLLVMType(std::get<1>(Arg));
@@ -49,7 +57,9 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
T = T->getPointerTo();
}
ArgTypes.push_back(T);
+ Sig.Params.emplace_back(std::get<1>(Arg), std::get<2>(Arg));
}
+ Signatures[Proto->getName()] = std::move(Sig);
Type *RetType = getLLVMType(Proto->getReturnType());
FunctionType *FT = FunctionType::get(RetType, ArgTypes, false);
@@ -112,20 +122,12 @@ Function *FunctionGen::emitFunctionDef(FunctionDefAST *FuncAST,
static Value *GenerateCall(llvm::Module &Module,
llvm::IRBuilder<> &Builder,
- llvm::LLVMContext &Context,
const std::string &CalleeName,
const std::vector<llvm::Value*> &Args,
bool &HadError) {
Function *CalleeF = Module.getFunction(CalleeName);
if (!CalleeF) {
- std::vector<Type*> ArgTypes;
- for (auto *Val : Args) ArgTypes.push_back(Val->getType());
- FunctionType *FT = FunctionType::get(Type::getInt64Ty(Context), ArgTypes, false);
- CalleeF = Function::Create(FT, Function::ExternalLinkage, CalleeName, &Module);
- }
-
- if (CalleeF->arg_size() != Args.size()) {
- fprintf(stderr, "Error: Incorrect # arguments passed to %s\n", CalleeName.c_str());
+ fprintf(stderr, "Error: Call to undefined function %s\n", CalleeName.c_str());
HadError = true;
return nullptr;
}
@@ -138,11 +140,11 @@ static Value *GenerateCall(llvm::Module &Module,
}
llvm::Value *FunctionGen::emitCallExpr(CallExprAST *Call, const std::vector<llvm::Value*> &Args) {
- return GenerateCall(Module, Builder, Context, Call->getCallee(), Args, HadError);
+ return GenerateCall(Module, Builder, Call->getCallee(), Args, HadError);
}
void FunctionGen::emitCallStmt(CallStmtAST *Call, const std::vector<llvm::Value*> &Args) {
- GenerateCall(Module, Builder, Context, Call->getCallee(), Args, HadError);
+ GenerateCall(Module, Builder, Call->getCallee(), Args, HadError);
}
void FunctionGen::emitReturn(ReturnStmtAST *Ret, llvm::Value *RetVal) {