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

View File

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

View File

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

View File

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

View File

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

View File

@ -150,7 +150,7 @@ fun_decls:
;
fun_decl:
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:

View File

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

View File

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

View File

@ -26,19 +26,17 @@
#include <vector>
#define PUT(type, funcname) \
new Function { \
new FunctionPrototype { \
new Id {#funcname}, Type::VOID, \
new PointerList<FunArg> { \
new FunArg {new Id {"value"}, type, false} \
}, \
new PointerList<Statement>{} \
}
#define GET(type, funcname) \
new Function { \
new FunctionPrototype { \
new Id {#funcname}, type, \
new PointerList<FunArg> {}, \
new PointerList<Statement>{} \
}
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::map<std::string, std::vector<Function const*>> STANDARD_MODULES = {
static const std::map<std::string, std::vector<FunctionPrototype const*>> STANDARD_MODULES = {
{"iostream", {
PUT(Type::BOOL, __Monicelli_putBool),
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::INT, __Monicelli_getInt)
}},
{"cassert", { new Function{
{"cassert", { new FunctionPrototype {
new Id("__Monicelli_assert"), Type::VOID,
new PointerList<FunArg> {
new FunArg {new Id("condition"), Type::BOOL, false}
},
new PointerList<Statement>{}
}}},
{"cstdlib", { new Function{
{"cstdlib", { new FunctionPrototype {
new Id("__Monicelli_abort"), Type::VOID,
new PointerList<FunArg> {},
new PointerList<Statement>{}
}}}
};