Extracting a FunctionPrototype node.

This will allow more flexibility in defining externed functions.
This commit is contained in:
Stefano Sanfilippo 2015-03-08 11:25:41 +01:00
parent 3f19125574
commit f933cc3163
9 changed files with 51 additions and 36 deletions

View File

@ -468,7 +468,7 @@ bool BitcodeEmitter::emit(Branch const& node) {
return true; return true;
} }
bool BitcodeEmitter::emitFunctionPrototype(Function const& node, llvm::Function **proto) { bool BitcodeEmitter::emit(FunctionPrototype const& node) {
std::vector<llvm::Type*> argTypes; std::vector<llvm::Type*> argTypes;
for (FunArg const* arg: node.getArgs()) { for (FunArg const* arg: node.getArgs()) {
@ -521,14 +521,14 @@ bool BitcodeEmitter::emitFunctionPrototype(Function const& node, llvm::Function
++argToEmit; ++argToEmit;
} }
*proto = func; d->retval = func;
return true; return true;
} }
bool BitcodeEmitter::emit(Function const& node) { bool BitcodeEmitter::emit(Function const& node) {
llvm::Function *func = nullptr; GUARDED(node.getPrototype().emit(this));
GUARDED(emitFunctionPrototype(node, &func)); llvm::Function *func = dynamic_cast<llvm::Function*>(d->retval);
d->scope.enter(); d->scope.enter();
@ -538,7 +538,7 @@ bool BitcodeEmitter::emit(Function const& node) {
d->builder.SetInsertPoint(bb); d->builder.SetInsertPoint(bb);
auto argToAlloc = func->arg_begin(); auto argToAlloc = func->arg_begin();
for (FunArg const* arg: node.getArgs()) { for (FunArg const* arg: node.getPrototype().getArgs()) {
llvm::AllocaInst *alloc = allocateVar( llvm::AllocaInst *alloc = allocateVar(
func, arg->getName(), LLVMType(arg->getType()) func, arg->getName(), LLVMType(arg->getType())
); );
@ -558,8 +558,6 @@ bool BitcodeEmitter::emit(Function const& node) {
} }
bool BitcodeEmitter::emit(Module const& node) { bool BitcodeEmitter::emit(Module const& node) {
llvm::Function *dummy;
if (node.getType() == Module::SYSTEM) { if (node.getType() == Module::SYSTEM) {
auto module = STANDARD_MODULES.find(node.getName()); auto module = STANDARD_MODULES.find(node.getName());
@ -569,8 +567,8 @@ bool BitcodeEmitter::emit(Module const& node) {
}); });
} }
for (Function const* func: module->second) { for (FunctionPrototype const* proto: module->second) {
if (!emitFunctionPrototype(*func, &dummy)) return false; GUARDED(proto->emit(this));
} }
} }

View File

@ -48,6 +48,7 @@ public:
virtual bool emit(Abort const&) override; virtual bool emit(Abort const&) override;
virtual bool emit(Assert const&) override; virtual bool emit(Assert const&) override;
virtual bool emit(Branch const&) override; virtual bool emit(Branch const&) override;
virtual bool emit(FunctionPrototype const&) override;
virtual bool emit(Function const&) override; virtual bool emit(Function const&) override;
virtual bool emit(Module const&) override; virtual bool emit(Module const&) override;
virtual bool emit(Program const&) override; virtual bool emit(Program const&) override;
@ -66,7 +67,6 @@ public:
private: private:
bool emitSemiExpression(Id const& left, SemiExpression const& right); bool emitSemiExpression(Id const& left, SemiExpression const& right);
bool emitFunctionPrototype(Function const& node, llvm::Function **proto);
std::unique_ptr<llvm::Module> module; std::unique_ptr<llvm::Module> module;
Private *d; Private *d;

View File

@ -59,7 +59,7 @@ bool CppEmitter::emit(Program const& program) {
} }
for (Function *function: program.getFunctions()) { for (Function *function: program.getFunctions()) {
emitFunctionSignature(*function); emit(function->getPrototype());
stream << ";\n"; stream << ";\n";
} }
@ -258,7 +258,7 @@ bool CppEmitter::emit(FunctionCall const& funcall) {
} }
bool CppEmitter::emit(Function const& function) { bool CppEmitter::emit(Function const& function) {
emitFunctionSignature(function); emit(function.getPrototype());
stream << " {\n"; stream << " {\n";
indent(); indent();
emitStatements(function.getBody()); emitStatements(function.getBody());
@ -317,11 +317,11 @@ bool CppEmitter::emit(Module const& module) {
return stream; return stream;
} }
bool CppEmitter::emitFunctionSignature(Function const& function) { bool CppEmitter::emit(FunctionPrototype const& proto) {
stream << function.getType() << ' '; stream << proto.getType() << ' ';
GUARDED(function.getName().emit(this)); GUARDED(proto.getName().emit(this));
stream << "("; stream << "(";
emitFunctionParams(function.getArgs()); emitFunctionParams(proto.getArgs());
stream << ")"; stream << ")";
return stream; return stream;

View File

@ -40,6 +40,7 @@ public:
virtual bool emit(Abort const&) override; virtual bool emit(Abort const&) override;
virtual bool emit(Assert const&) override; virtual bool emit(Assert const&) override;
virtual bool emit(Branch const&) override; virtual bool emit(Branch const&) override;
virtual bool emit(FunctionPrototype const&) override;
virtual bool emit(Function const&) override; virtual bool emit(Function const&) override;
virtual bool emit(Module const&) override; virtual bool emit(Module const&) override;
virtual bool emit(Program const&) override; virtual bool emit(Program const&) override;
@ -52,7 +53,6 @@ public:
private: private:
bool emitIndent(); bool emitIndent();
bool emitFunctionSignature(Function const& function);
bool emitFunctionParams(PointerList<FunArg> const& funargs); bool emitFunctionParams(PointerList<FunArg> const& funargs);
bool emitFunctionArglist(PointerList<Expression> const& args); bool emitFunctionArglist(PointerList<Expression> const& args);
bool emitStatements(PointerList<Statement> const& node); bool emitStatements(PointerList<Statement> const& node);

View File

@ -37,6 +37,7 @@ class Assert;
class FunctionCall; class FunctionCall;
class Branch; class Branch;
class Main; class Main;
class FunctionPrototype;
class Function; class Function;
class Module; class Module;
class Program; class Program;
@ -53,6 +54,7 @@ public:
virtual bool emit(Input const&) = 0; virtual bool emit(Input const&) = 0;
virtual bool emit(Abort const&) = 0; virtual bool emit(Abort const&) = 0;
virtual bool emit(Assert const&) = 0; virtual bool emit(Assert const&) = 0;
virtual bool emit(FunctionPrototype const&) = 0;
virtual bool emit(Branch const&) = 0; virtual bool emit(Branch const&) = 0;
virtual bool emit(Function const&) = 0; virtual bool emit(Function const&) = 0;
virtual bool emit(Module const&) = 0; virtual bool emit(Module const&) = 0;

View File

@ -150,7 +150,7 @@ fun_decls:
; ;
fun_decl: fun_decl:
FUN_DECL fun_return ID args FUN_END statements { FUN_DECL fun_return ID args FUN_END statements {
$$ = new Function(new Id($3), $2, $4, $6); $$ = new Function(new FunctionPrototype(new Id($3), $2, $4), $6);
} }
; ;
fun_return: fun_return:

View File

@ -26,9 +26,10 @@ using namespace monicelli;
Function *monicelli::makeMain(PointerList<Statement> *body) { Function *monicelli::makeMain(PointerList<Statement> *body) {
PointerList<FunArg> *noargs = new PointerList<FunArg>(); PointerList<FunArg> *noargs = new PointerList<FunArg>();
return new Function( FunctionPrototype *proto = new FunctionPrototype(
new Id(new std::string(ENTRYPOINT_NAME)), new Id(new std::string(ENTRYPOINT_NAME)), Type::VOID, noargs
Type::VOID, noargs, body
); );
return new Function(proto, body);
} }

View File

@ -392,10 +392,10 @@ private:
}; };
class Function: public Emittable { class FunctionPrototype: public Emittable {
public: public:
Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *b): FunctionPrototype(Id *n, Type r, PointerList<FunArg> *a):
name(n), type(r), args(a), body(b) {} name(n), type(r), args(a) {}
virtual bool emit(Emitter *emitter) const { virtual bool emit(Emitter *emitter) const {
return emitter->emit(*this); return emitter->emit(*this);
@ -413,14 +413,32 @@ public:
return *args; return *args;
} }
private:
Pointer<Id> name;
Type type;
Pointer<PointerList<FunArg>> args;
};
class Function: public Emittable {
public:
Function(FunctionPrototype *p, PointerList<Statement> *b):
prototype(p), body(b) {}
virtual bool emit(Emitter *emitter) const {
return emitter->emit(*this);
}
FunctionPrototype const& getPrototype() const {
return *prototype;
}
PointerList<Statement> const& getBody() const { PointerList<Statement> const& getBody() const {
return *body; return *body;
} }
private: private:
Pointer<Id> name; Pointer<FunctionPrototype> prototype;
Type type;
Pointer<PointerList<FunArg>> args;
Pointer<PointerList<Statement>> body; Pointer<PointerList<Statement>> body;
}; };

View File

@ -26,19 +26,17 @@
#include <vector> #include <vector>
#define PUT(type, funcname) \ #define PUT(type, funcname) \
new Function { \ new FunctionPrototype { \
new Id {#funcname}, Type::VOID, \ new Id {#funcname}, Type::VOID, \
new PointerList<FunArg> { \ new PointerList<FunArg> { \
new FunArg {new Id {"value"}, type, false} \ new FunArg {new Id {"value"}, type, false} \
}, \ }, \
new PointerList<Statement>{} \
} }
#define GET(type, funcname) \ #define GET(type, funcname) \
new Function { \ new FunctionPrototype { \
new Id {#funcname}, type, \ new Id {#funcname}, type, \
new PointerList<FunArg> {}, \ new PointerList<FunArg> {}, \
new PointerList<Statement>{} \
} }
namespace monicelli { namespace monicelli {
@ -64,7 +62,7 @@ static const std::string ASSERT_NAME = "__Monicelli_assert";
static const std::string ENTRYPOINT_NAME = "__Monicelli_main"; static const std::string ENTRYPOINT_NAME = "__Monicelli_main";
static const std::map<std::string, std::vector<Function const*>> STANDARD_MODULES = { static const std::map<std::string, std::vector<FunctionPrototype const*>> STANDARD_MODULES = {
{"iostream", { {"iostream", {
PUT(Type::BOOL, __Monicelli_putBool), PUT(Type::BOOL, __Monicelli_putBool),
PUT(Type::CHAR, __Monicelli_putChar), PUT(Type::CHAR, __Monicelli_putChar),
@ -77,17 +75,15 @@ static const std::map<std::string, std::vector<Function const*>> STANDARD_MODULE
GET(Type::DOUBLE, __Monicelli_getDouble), GET(Type::DOUBLE, __Monicelli_getDouble),
GET(Type::INT, __Monicelli_getInt) GET(Type::INT, __Monicelli_getInt)
}}, }},
{"cassert", { new Function{ {"cassert", { new FunctionPrototype {
new Id("__Monicelli_assert"), Type::VOID, new Id("__Monicelli_assert"), Type::VOID,
new PointerList<FunArg> { new PointerList<FunArg> {
new FunArg {new Id("condition"), Type::BOOL, false} new FunArg {new Id("condition"), Type::BOOL, false}
}, },
new PointerList<Statement>{}
}}}, }}},
{"cstdlib", { new Function{ {"cstdlib", { new FunctionPrototype {
new Id("__Monicelli_abort"), Type::VOID, new Id("__Monicelli_abort"), Type::VOID,
new PointerList<FunArg> {}, new PointerList<FunArg> {},
new PointerList<Statement>{}
}}} }}}
}; };