diff options
author | David Robillard <d@drobilla.net> | 2009-10-06 17:02:44 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-10-06 17:02:44 +0000 |
commit | 165fc3638f9666e94c5cfc4fe719697b0ce72774 (patch) | |
tree | 00976bf8aae033f04b94875a983f6762e2a5c235 | |
parent | ce95207bc617e6152efe068c1e045b64121803cc (diff) | |
download | resp-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-- | Makefile | 5 | ||||
-rw-r--r-- | src/compile.cpp | 126 | ||||
-rw-r--r-- | src/constrain.cpp | 11 | ||||
-rw-r--r-- | src/llvm.cpp | 123 | ||||
-rw-r--r-- | src/tuplr.hpp | 7 |
5 files changed, 158 insertions, 114 deletions
@@ -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; }; |