aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-10-06 17:02:44 +0000
committerDavid Robillard <d@drobilla.net>2009-10-06 17:02:44 +0000
commit165fc3638f9666e94c5cfc4fe719697b0ce72774 (patch)
tree00976bf8aae033f04b94875a983f6762e2a5c235
parentce95207bc617e6152efe068c1e045b64121803cc (diff)
downloadresp-165fc3638f9666e94c5cfc4fe719697b0ce72774.tar.gz
resp-165fc3638f9666e94c5cfc4fe719697b0ce72774.tar.bz2
resp-165fc3638f9666e94c5cfc4fe719697b0ce72774.zip
Split backend specific compilation functions from generic ones.
git-svn-id: http://svn.drobilla.net/resp/tuplr@191 ad02d1e2-f140-0410-9f75-f8b11f17cedd
-rw-r--r--Makefile5
-rw-r--r--src/compile.cpp126
-rw-r--r--src/constrain.cpp11
-rw-r--r--src/llvm.cpp123
-rw-r--r--src/tuplr.hpp7
5 files changed, 158 insertions, 114 deletions
diff --git a/Makefile b/Makefile
index 2915c8a..afe7d80 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,7 @@ builddir:
mkdir -p build
OBJECTS = \
+ build/compile.o \
build/constrain.o \
build/cps.o \
build/gc.o \
@@ -25,9 +26,9 @@ OBJECTS = \
build/parse.o \
build/pprint.o \
build/repl.o \
+ build/tlsf.o \
build/tuplr.o \
- build/unify.o \
- build/tlsf.o
+ build/unify.o
build/tuplr: $(OBJECTS)
g++ -o $@ $^ $(LDFLAGS)
diff --git a/src/compile.cpp b/src/compile.cpp
new file mode 100644
index 0000000..8862f73
--- /dev/null
+++ b/src/compile.cpp
@@ -0,0 +1,126 @@
+/* Tuplr: A programming language
+ * Copyright (C) 2008-2009 David Robillard <dave@drobilla.net>
+ *
+ * Tuplr is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * Tuplr 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 Affero General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Tuplr. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** @file
+ * @brief Compile AST using generic backend interface
+ *
+ * Compilation pass functions (lift/compile) that don't require direct use
+ * of any specific backend API are implemented here. Others are implemented
+ * in e.g. llvm.cpp.
+ */
+
+#include "tuplr.hpp"
+
+using namespace std;
+
+CValue
+ASymbol::compile(CEnv& cenv)
+{
+ return cenv.vals.ref(this);
+}
+
+void
+AFn::lift(CEnv& cenv)
+{
+ cenv.push();
+ for (const_iterator p = prot()->begin(); p != prot()->end(); ++p)
+ cenv.def((*p)->as<ASymbol*>(), *p, NULL, NULL);
+
+ // Lift body
+ for (size_t i = 2; i < size(); ++i)
+ at(i)->lift(cenv);
+
+ cenv.pop();
+
+ AType* type = cenv.type(this);
+ if (impls.find(type) || !type->concrete())
+ return;
+
+ AType* protT = type->at(1)->as<AType*>();
+ liftCall(cenv, *protT);
+}
+
+void
+ACall::lift(CEnv& cenv)
+{
+ AFn* c = cenv.tenv.resolve(at(0))->to<AFn*>();
+ AType argsT(loc);
+
+ // Lift arguments
+ for (size_t i = 1; i < size(); ++i) {
+ at(i)->lift(cenv);
+ argsT.push_back(cenv.type(at(i)));
+ }
+
+ if (!c) return; // Primitive
+
+ if (c->prot()->size() < size() - 1)
+ throw Error(loc, (format("too many arguments to function `%1%'") % at(0)->str()).str());
+ if (c->prot()->size() > size() - 1)
+ throw Error(loc, (format("too few arguments to function `%1%'") % at(0)->str()).str());
+
+ c->liftCall(cenv, argsT); // Lift called closure
+}
+
+CValue
+ACall::compile(CEnv& cenv)
+{
+ AFn* c = cenv.tenv.resolve(at(0))->to<AFn*>();
+
+ if (!c) return NULL; // Primitive
+
+ AType protT(loc);
+ for (size_t i = 1; i < size(); ++i)
+ protT.push_back(cenv.type(at(i)));
+
+ TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(c);
+ assert(gt != cenv.tenv.genericTypes.end());
+ AType fnT(loc);
+ fnT.push_back(cenv.penv.sym("Fn"));
+ fnT.push_back(&protT);
+ fnT.push_back(cenv.type(this));
+
+ CFunction f = c->impls.find(&fnT);
+ THROW_IF(!f, loc, (format("callee failed to compile for type %1%") % fnT.str()).str());
+
+ vector<CValue> args(size() - 1);
+ for (size_t i = 0; i < args.size(); ++i)
+ args[i] = cenv.compile(at(i + 1));
+
+ return cenv.engine()->compileCall(cenv, f, args);
+}
+
+void
+ADef::lift(CEnv& cenv)
+{
+ // Define stub first for recursion
+ cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
+ AFn* c = at(2)->to<AFn*>();
+ if (c)
+ c->name = sym()->str();
+ at(2)->lift(cenv);
+}
+
+CValue
+ADef::compile(CEnv& cenv)
+{
+ // Define stub first for recursion
+ cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
+ CValue val = cenv.compile(at(size() - 1));
+ cenv.vals.def(sym(), val);
+ return val;
+}
diff --git a/src/constrain.cpp b/src/constrain.cpp
index 0581115..87cc698 100644
--- a/src/constrain.cpp
+++ b/src/constrain.cpp
@@ -22,6 +22,17 @@
#include <set>
#include "tuplr.hpp"
+#define CONSTRAIN_LITERAL(CT, NAME) \
+template<> void \
+ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { \
+ c.constrain(tenv, this, tenv.named(NAME)); \
+}
+
+// Literal template instantiations
+CONSTRAIN_LITERAL(int32_t, "Int")
+CONSTRAIN_LITERAL(float, "Float")
+CONSTRAIN_LITERAL(bool, "Bool")
+
void
AString::constrain(TEnv& tenv, Constraints& c) const
{
diff --git a/src/llvm.cpp b/src/llvm.cpp
index ec2c2a4..36f639f 100644
--- a/src/llvm.cpp
+++ b/src/llvm.cpp
@@ -17,6 +17,10 @@
/** @file
* @brief Compile AST to LLVM IR
+ *
+ * Compilation pass functions (lift/compile) that require direct use of LLVM
+ * specific things are implemented here. Generic compilation pass functions
+ * are implemented in compile.cpp.
*/
#include <map>
@@ -155,6 +159,11 @@ struct LLVMEngine : public Engine {
llFunc(f)->eraseFromParent();
}
+ CValue compileCall(CEnv& cenv, CFunction f, const vector<CValue>& args) {
+ const vector<Value*>& llArgs = *reinterpret_cast<const vector<Value*>*>(&args);
+ return builder.CreateCall(llFunc(f), llArgs.begin(), llArgs.end());
+ }
+
void writeModule(CEnv& cenv, std::ostream& os) {
AssemblyAnnotationWriter writer;
module->print(os, &writer);
@@ -211,44 +220,13 @@ tuplr_free_engine(Engine* engine)
* Code Generation *
***************************************************************************/
-#define LITERAL(CT, NAME, COMPILED) \
-template<> CValue ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \
-template<> void \
-ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { \
- c.constrain(tenv, this, tenv.named(NAME)); \
-}
+#define COMPILE_LITERAL(CT, COMPILED) \
+template<> CValue ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); }
// Literal template instantiations
-LITERAL(int32_t, "Int", ConstantInt::get(Type::Int32Ty, val, true))
-LITERAL(float, "Float", ConstantFP::get(Type::FloatTy, val))
-LITERAL(bool, "Bool", ConstantInt::get(Type::Int1Ty, val, false))
-
-CValue
-ASymbol::compile(CEnv& cenv)
-{
- return cenv.vals.ref(this);
-}
-
-void
-AFn::lift(CEnv& cenv)
-{
- cenv.push();
- for (const_iterator p = prot()->begin(); p != prot()->end(); ++p)
- cenv.def((*p)->as<ASymbol*>(), *p, NULL, NULL);
-
- // Lift body
- for (size_t i = 2; i < size(); ++i)
- at(i)->lift(cenv);
-
- cenv.pop();
-
- AType* type = cenv.type(this);
- if (impls.find(type) || !type->concrete())
- return;
-
- AType* protT = type->at(1)->as<AType*>();
- liftCall(cenv, *protT);
-}
+COMPILE_LITERAL(int32_t, ConstantInt::get(Type::Int32Ty, val, true))
+COMPILE_LITERAL(float, ConstantFP::get(Type::FloatTy, val))
+COMPILE_LITERAL(bool, ConstantInt::get(Type::Int1Ty, val, false))
void
AFn::liftCall(CEnv& cenv, const AType& argsT)
@@ -404,79 +382,6 @@ AFn::compile(CEnv& cenv)
return tupPtr;*/
}
-void
-ACall::lift(CEnv& cenv)
-{
- AFn* c = cenv.tenv.resolve(at(0))->to<AFn*>();
- AType argsT(loc);
-
- // Lift arguments
- for (size_t i = 1; i < size(); ++i) {
- at(i)->lift(cenv);
- argsT.push_back(cenv.type(at(i)));
- }
-
- if (!c) return; // Primitive
-
- if (c->prot()->size() < size() - 1)
- throw Error(loc, (format("too many arguments to function `%1%'") % at(0)->str()).str());
- if (c->prot()->size() > size() - 1)
- throw Error(loc, (format("too few arguments to function `%1%'") % at(0)->str()).str());
-
- c->liftCall(cenv, argsT); // Lift called closure
-}
-
-CValue
-ACall::compile(CEnv& cenv)
-{
- AFn* c = cenv.tenv.resolve(at(0))->to<AFn*>();
-
- if (!c) return NULL; // Primitive
-
- AType protT(loc);
- vector<const Type*> types;
- for (size_t i = 1; i < size(); ++i) {
- protT.push_back(cenv.type(at(i)));
- types.push_back(llType(cenv.type(at(i))));
- }
-
- TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(c);
- assert(gt != cenv.tenv.genericTypes.end());
- AType fnT(loc);
- fnT.push_back(cenv.penv.sym("Fn"));
- fnT.push_back(&protT);
- fnT.push_back(cenv.type(this));
- Function* f = (Function*)c->impls.find(&fnT);
- THROW_IF(!f, loc, (format("callee failed to compile for type %1%") % fnT.str()).str());
-
- vector<Value*> params(size() - 1);
- for (size_t i = 0; i < types.size(); ++i)
- params[i] = llVal(cenv.compile(at(i+1)));
-
- return llEngine(cenv)->builder.CreateCall(f, params.begin(), params.end());
-}
-
-void
-ADef::lift(CEnv& cenv)
-{
- // Define stub first for recursion
- cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
- AFn* c = at(2)->to<AFn*>();
- if (c)
- c->name = sym()->str();
- at(2)->lift(cenv);
-}
-
-CValue
-ADef::compile(CEnv& cenv)
-{
- // Define stub first for recursion
- cenv.def(sym(), at(2), cenv.type(at(2)), NULL);
- CValue val = cenv.compile(at(size() - 1));
- cenv.vals.def(sym(), val);
- return val;
-}
-
CValue
AIf::compile(CEnv& cenv)
{
diff --git a/src/tuplr.hpp b/src/tuplr.hpp
index 1e64da1..ca97da9 100644
--- a/src/tuplr.hpp
+++ b/src/tuplr.hpp
@@ -627,9 +627,10 @@ struct Engine {
const AType* retT, const ATuple& argsT,
const vector<string> argNames=vector<string>()) = 0;
- virtual void finishFunction(CEnv& cenv, CFunction f, const AType* retT, CValue ret) = 0;
- virtual void eraseFunction(CEnv& cenv, CFunction f) = 0;
- virtual void writeModule(CEnv& cenv, std::ostream& os) = 0;
+ virtual void finishFunction(CEnv& cenv, CFunction f, const AType* retT, CValue ret) = 0;
+ virtual void eraseFunction(CEnv& cenv, CFunction f) = 0;
+ virtual CValue compileCall(CEnv& cenv, CFunction f, const vector<CValue>& args) = 0;
+ virtual void writeModule(CEnv& cenv, std::ostream& os) = 0;
virtual const string call(CEnv& cenv, CFunction f, AType* retT) = 0;
};