Replace hardcoded stdlib prototypes with a module registry.

This commit is contained in:
Stefano Sanfilippo 2015-03-08 13:25:59 +01:00
parent 3aade87599
commit b5196b1776
6 changed files with 128 additions and 94 deletions

View File

@ -20,7 +20,7 @@
#include "BitcodeEmitter.hpp" #include "BitcodeEmitter.hpp"
#include "Scope.hpp" #include "Scope.hpp"
#include "Nodes.hpp" #include "Nodes.hpp"
#include "RuntimePrototypes.hpp" #include "ModuleRegistry.hpp"
#include <llvm/IR/Verifier.h> #include <llvm/IR/Verifier.h>
#include <llvm/IR/DerivedTypes.h> #include <llvm/IR/DerivedTypes.h>
@ -578,28 +578,13 @@ bool BitcodeEmitter::emit(Function const& node) {
} }
bool BitcodeEmitter::emit(Module const& node) { bool BitcodeEmitter::emit(Module const& node) {
if (node.getType() == Module::SYSTEM) {
auto module = STANDARD_MODULES.find(node.getName());
if (module == STANDARD_MODULES.end()) {
return reportError({
"Unknown system module", node.getName()
});
}
for (FunctionPrototype const* proto: module->second) {
GUARDED(proto->emit(this));
}
}
// TODO (maybe) user modules
return true; return true;
} }
bool BitcodeEmitter::emit(Program const& program) { bool BitcodeEmitter::emit(Program const& program) {
for (Module const& module: program.getModules()) { auto const& externals = getModuleRegistry().getRegisteredFunctions();
GUARDED(module.emit(this)); for (FunctionPrototype const* proto: externals) {
GUARDED(proto->emit(this));
} }
for (Function const* function: program.getFunctions()) { for (Function const* function: program.getFunctions()) {

View File

@ -95,7 +95,7 @@ flex_target(Scanner Monicelli.lpp ${CMAKE_CURRENT_BINARY_DIR}/Lexer.cpp)
add_flex_bison_dependency(Scanner Parser) add_flex_bison_dependency(Scanner Parser)
add_executable(mcc add_executable(mcc
main.cpp Nodes.cpp main.cpp Nodes.cpp ModuleRegistry.cpp
${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS} ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS}
CppEmitter.cpp BitcodeEmitter.cpp CppEmitter.cpp BitcodeEmitter.cpp
) )

91
ModuleRegistry.cpp Normal file
View File

@ -0,0 +1,91 @@
/*
* Monicelli: an esoteric language compiler
*
* Copyright (C) 2014 Stefano Sanfilippo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ModuleRegistry.hpp"
#include "Nodes.hpp"
#include <vector>
using namespace monicelli;
static ModuleRegistry globalRegistry;
ModuleRegistry& monicelli::getModuleRegistry() {
return globalRegistry;
}
struct ModuleRegistry::Private {
PointerList<FunctionPrototype> prototypes;
};
ModuleRegistry::ModuleRegistry() {
d = new Private;
}
ModuleRegistry::~ModuleRegistry() {
delete d;
}
PointerList<FunctionPrototype> const& ModuleRegistry::getRegisteredFunctions() const {
return d->prototypes;
}
void ModuleRegistry::registerFunction(FunctionPrototype *proto) {
d->prototypes.push_back(proto);
}
#define PUT(type, funcname) \
new FunctionPrototype { \
new Id {#funcname}, Type::VOID, \
new PointerList<FunArg> { \
new FunArg {new Id {"value"}, type, false} \
}, \
}
#define GET(type, funcname) \
new FunctionPrototype { \
new Id {#funcname}, type, \
new PointerList<FunArg> {}, \
}
void monicelli::registerStdLib(ModuleRegistry &r) {
r.registerFunction(PUT(Type::CHAR, __Monicelli_putBool));
r.registerFunction(PUT(Type::CHAR, __Monicelli_putChar));
r.registerFunction(PUT(Type::FLOAT, __Monicelli_putFloat));
r.registerFunction(PUT(Type::DOUBLE, __Monicelli_putDouble));
r.registerFunction(PUT(Type::INT, __Monicelli_putInt));
r.registerFunction(GET(Type::CHAR, __Monicelli_getBool));
r.registerFunction(GET(Type::CHAR, __Monicelli_getChar));
r.registerFunction(GET(Type::FLOAT, __Monicelli_getFloat));
r.registerFunction(GET(Type::DOUBLE, __Monicelli_getDouble));
r.registerFunction(GET(Type::INT, __Monicelli_getInt));
r.registerFunction(new FunctionPrototype {
new Id("__Monicelli_assert"), Type::VOID,
new PointerList<FunArg> {
new FunArg {new Id("condition"), Type::CHAR, false}
}
});
r.registerFunction(new FunctionPrototype {
new Id("__Monicelli_abort"), Type::VOID,
new PointerList<FunArg> {}
});
}
#undef PUT
#undef GET

29
ModuleRegistry.hpp Normal file
View File

@ -0,0 +1,29 @@
#ifndef MODULE_REGISTRY_HPP
#define MODULE_REGISTRY_HPP
#include "Pointers.hpp"
namespace monicelli {
class FunctionPrototype;
class ModuleRegistry {
public:
ModuleRegistry();
ModuleRegistry(ModuleRegistry&) = delete;
virtual ~ModuleRegistry();
PointerList<FunctionPrototype> const& getRegisteredFunctions() const;
void registerFunction(FunctionPrototype *proto);
private:
struct Private;
Private *d;
};
ModuleRegistry& getModuleRegistry();
void registerStdLib(ModuleRegistry &);
}
#endif

View File

@ -1,74 +0,0 @@
#ifndef RUNTIME_PROTOTYPES_HPP
#define RUNTIME_PROTOTYPES_HPP
/*
* Monicelli: an esoteric language compiler
*
* Copyright (C) 2014 Stefano Sanfilippo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Nodes.hpp"
#include <map>
#include <string>
#include <vector>
#define PUT(type, funcname) \
new FunctionPrototype { \
new Id {#funcname}, Type::VOID, \
new PointerList<FunArg> { \
new FunArg {new Id {"value"}, type, false} \
}, \
}
#define GET(type, funcname) \
new FunctionPrototype { \
new Id {#funcname}, type, \
new PointerList<FunArg> {}, \
}
namespace monicelli {
static const std::map<std::string, std::vector<FunctionPrototype const*>> STANDARD_MODULES = {
{"iostream", {
PUT(Type::CHAR, __Monicelli_putBool),
PUT(Type::CHAR, __Monicelli_putChar),
PUT(Type::FLOAT, __Monicelli_putFloat),
PUT(Type::DOUBLE, __Monicelli_putDouble),
PUT(Type::INT, __Monicelli_putInt),
GET(Type::CHAR, __Monicelli_getBool),
GET(Type::CHAR, __Monicelli_getChar),
GET(Type::FLOAT, __Monicelli_getFloat),
GET(Type::DOUBLE, __Monicelli_getDouble),
GET(Type::INT, __Monicelli_getInt)
}},
{"cassert", { new FunctionPrototype {
new Id("__Monicelli_assert"), Type::VOID,
new PointerList<FunArg> {
new FunArg {new Id("condition"), Type::CHAR, false}
},
}}},
{"cstdlib", { new FunctionPrototype {
new Id("__Monicelli_abort"), Type::VOID,
new PointerList<FunArg> {},
}}}
};
}
#undef PUT
#undef GET
#endif

View File

@ -20,6 +20,7 @@
#include "Scanner.hpp" #include "Scanner.hpp"
#include "Parser.hpp" #include "Parser.hpp"
#include "CppEmitter.hpp" #include "CppEmitter.hpp"
#include "ModuleRegistry.hpp"
#include "BitcodeEmitter.hpp" #include "BitcodeEmitter.hpp"
#include <llvm/Bitcode/ReaderWriter.h> #include <llvm/Bitcode/ReaderWriter.h>
@ -38,6 +39,8 @@ using namespace monicelli;
int main(int argc, char **argv) { int main(int argc, char **argv) {
registerStdLib(getModuleRegistry());
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
std::string inputname(argv[i]); std::string inputname(argv[i]);
std::ifstream instream(inputname); std::ifstream instream(inputname);