Replace hardcoded stdlib prototypes with a module registry.
This commit is contained in:
parent
3aade87599
commit
b5196b1776
|
@ -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()) {
|
||||||
|
|
|
@ -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
91
ModuleRegistry.cpp
Normal 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
29
ModuleRegistry.hpp
Normal 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
|
|
@ -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
|
|
3
main.cpp
3
main.cpp
|
@ -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);
|
||||||
|
|
Reference in New Issue
Block a user