aboutsummaryrefslogtreecommitdiffstats
path: root/llvm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm.cpp')
-rw-r--r--llvm.cpp158
1 files changed, 88 insertions, 70 deletions
diff --git a/llvm.cpp b/llvm.cpp
index 32577f9..a599872 100644
--- a/llvm.cpp
+++ b/llvm.cpp
@@ -124,6 +124,7 @@ CEnv::compile(AST* obj)
void
CEnv::optimise(CFunction f)
{
+ _pimpl->module->dump();
verifyFunction(*static_cast<Function*>(f));
_pimpl->opt.run(*static_cast<Function*>(f));
}
@@ -139,13 +140,24 @@ CEnv::write(std::ostream& os)
template<> CValue \
ALiteral<CT>::compile(CEnv& cenv) { return (COMPILED); } \
template<> void \
-ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) { c.constrain(tenv, this, tenv.named(NAME)); }
+ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const { c.constrain(tenv, this, tenv.named(NAME)); }
/// 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))
+template<typename T>
+T
+checked_cast(AST* ast)
+{
+ T t = dynamic_cast<T>(ast);
+ if (!t)
+ throw Error((format("internal error: `%1%' should be a `%2%'")
+ % typeid(ast).name() % typeid(T).name()).str(), ast->loc);
+ return t;
+}
+
static Function*
compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATuple& protT,
const vector<string> argNames=vector<string>())
@@ -154,8 +166,7 @@ compileFunction(CEnv& cenv, const std::string& name, const Type* retT, const ATu
vector<const Type*> cprot;
for (size_t i = 0; i < protT.size(); ++i) {
- AType* at = dynamic_cast<AType*>(protT.at(i));
- if (!at) throw Error("function parameter type isn't");
+ AType* at = checked_cast<AType*>(protT.at(i));
if (!lltype(at)) throw Error("function parameter is untyped");
cprot.push_back(lltype(at));
}
@@ -215,10 +226,8 @@ AClosure::lift(CEnv& cenv)
vector<Value*> args;
const_iterator p = prot()->begin();
size_t i = 0;
- for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p) {
- cenv.tenv.def(*p, dynamic_cast<AType*>(protT->at(i++)));
- cenv.vals.def(dynamic_cast<ASymbol*>(*p), &*a);
- }
+ for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p)
+ cenv.def(checked_cast<ASymbol*>(*p), *p, checked_cast<AType*>(protT->at(i++)), &*a);
// Write function body
try {
@@ -240,65 +249,71 @@ AClosure::lift(CEnv& cenv)
}
void
-AClosure::liftPoly(CEnv& cenv, const vector<AType*>& argsT)
+AClosure::liftCall(CEnv& cenv, const vector<AType*>& argsT)
{
- if (type->concrete())
- return;
-
- throw Error("No polymorphism");
+ TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(this);
+ assert(gt != cenv.tenv.genericTypes.end());
+ AType* genericType = gt->second;
-#if 0
- //Subst tsubst;
+ // Find type and build substitution
assert(argsT.size() == prot()->size());
- for (size_t i = 0; i < argsT.size(); ++i) {
- cenv.err << " " << argsT.at(i)->str();
- //tsubst[*cenv.tenv.ref(prot()->at(i))] = argsT.at(i);
- }
- cenv.err << endl;
-#endif
-}
+ Subst argsSubst;
+ ATuple* genericProtT = dynamic_cast<ATuple*>(genericType->at(1));
+ assert(genericProtT);
+ for (size_t i = 0; i < argsT.size(); ++i)
+ argsSubst[dynamic_cast<AType*>(genericProtT->at(i))] = dynamic_cast<AType*>(argsT.at(i));
+
+ AType* thisType = new AType(*dynamic_cast<ATuple*>(argsSubst.apply(genericType)), loc);
+ cenv.err << "THIS TYPE: " << thisType << endl;
-CValue
-AClosure::compile(CEnv& cenv)
-{
- /*
- cenv.err << "***********************************************" << endl;
- cenv.err << cenv.type(this) << endl;
+ //if (!thisType->concrete())
+ // throw Error("unable to resolve concrete type for function", loc);
- cenv.err << "COMPILING FOR TYPE:";
- Subst tsubst;
- assert(cenv.code.front().size() == prot()->size());
- for (size_t i = 0; i < cenv.code.front().size(); ++i) {
- cenv.err << " (" << cenv.type(prot()->at(i))->str()
- << " -> " << cenv.type(cenv.code.front().at(i).second)->str() << ")";
- tsubst[cenv.tenv.types[prot()->at(i)]] =
- cenv.type(cenv.code.front().at(i).second);
- }
- cenv.err << endl;
+ if (funcs.find(thisType))
+ return;
- Subst subst = Subst::compose(tsubst, cenv.tsubst);
- AType* concreteType = subst.apply(type);
- if (!concreteType->concrete())
- throw Error("compiled function has non-concrete type", loc);
+ ATuple* protT = dynamic_cast<ATuple*>(thisType->at(1));
- cenv.err << "*********** CONCRETE TYPE: " << concreteType->str() << endl;
- */
+ // Write function declaration
+ string name = this->name == "" ? cenv.gensym("_fn") : this->name;
+ Function* f = compileFunction(cenv, name,
+ lltype(dynamic_cast<AType*>(thisType->at(thisType->size() - 1))),
+ *protT);
- //CValue ret = funcs.find(concreteType);
- //cenv.err << "VALUE FOR TYPE " << concreteType->str() << " : " << ret << endl;
- //return ret;
- return NULL;
+ cenv.push();
+ Subst oldSubst = cenv.tsubst;
+ cenv.tsubst = Subst::compose(cenv.tsubst, Subst::compose(argsSubst, *subst));
+
+ // Bind argument values in CEnv
+ vector<Value*> args;
+ const_iterator p = prot()->begin();
+ size_t i = 0;
+ for (Function::arg_iterator a = f->arg_begin(); a != f->arg_end(); ++a, ++p)
+ cenv.def(checked_cast<ASymbol*>(*p), *p, checked_cast<AType*>(protT->at(i++)), &*a);
+
+ // Write function body
+ try {
+ // Define value first for recursion
+ cenv.precompile(this, f);
+ funcs.push_back(make_pair(thisType, f));
+
+ CValue retVal = cenv.compile(at(2));
+ llengine(cenv)->builder.CreateRet(LLVal(retVal)); // Finish function
+ cenv.optimise(LLFunc(f));
+
+ } catch (Error& e) {
+ f->eraseFromParent(); // Error reading body, remove function
+ cenv.pop();
+ throw e;
+ }
+ cenv.tsubst = oldSubst;
+ cenv.pop();
}
-template<typename T>
-T
-checked_cast(AST* ast)
+CValue
+AClosure::compile(CEnv& cenv)
{
- T t = dynamic_cast<T>(ast);
- if (!t)
- throw Error((format("internal error: `%1%' should be a `%2%'")
- % typeid(ast).name() % typeid(T).name()).str(), ast->loc);
- return t;
+ return NULL;
}
static
@@ -306,7 +321,7 @@ AST*
maybeLookup(CEnv& cenv, AST* ast)
{
ASymbol* s = dynamic_cast<ASymbol*>(ast);
- if (s)
+ if (s && s->addr)
return cenv.code.deref(s->addr);
return ast;
}
@@ -325,18 +340,19 @@ ACall::lift(CEnv& cenv)
}
if (!c) return; // Primitive
-
- // Extend environment with bound and typed parameters
- cenv.push();
+
if (c->prot()->size() < size() - 1)
throw Error((format("too many arguments to function `%1%'") % at(0)->str()).str(), loc);
if (c->prot()->size() > size() - 1)
throw Error((format("too few arguments to function `%1%'") % at(0)->str()).str(), loc);
+ // Extend environment with bound and typed parameters
+ cenv.push();
+
for (size_t i = 1; i < size(); ++i)
- cenv.code.def(checked_cast<ASymbol*>(c->prot()->at(i-1)), at(i));
+ cenv.def(checked_cast<ASymbol*>(c->prot()->at(i-1)), at(i), cenv.type(at(i)), NULL);
- c->liftPoly(cenv, argsT); // Lift called closure
+ c->liftCall(cenv, argsT); // Lift called closure
cenv.pop(); // Restore environment
}
@@ -347,16 +363,13 @@ ACall::compile(CEnv& cenv)
if (!c) return NULL; // Primitive
- if (c->prot()->size() < size() - 1)
- throw Error((format("too many arguments to function `%1%'") % at(0)->str()).str(), loc);
- if (c->prot()->size() > size() - 1)
- throw Error((format("too few arguments to function `%1%'") % at(0)->str()).str(), loc);
-
AType* protT = new AType(loc, NULL);
for (size_t i = 1; i < size(); ++i)
protT->push_back(cenv.type(at(i)));
-
- AType* polyT = c->type;
+
+ TEnv::GenericTypes::const_iterator gt = cenv.tenv.genericTypes.find(c);
+ assert(gt != cenv.tenv.genericTypes.end());
+ AType* polyT = gt->second;
AType* fnT = new AType(loc, cenv.penv.sym("Fn"), protT, polyT->at(2), 0);
Function* f = (Function*)c->funcs.find(fnT);
@@ -374,7 +387,8 @@ ADefinition::lift(CEnv& cenv)
{
if (cenv.code.lookup(checked_cast<ASymbol*>(at(1))))
throw Error(string("`") + at(1)->str() + "' redefined", loc);
- cenv.code.def((ASymbol*)at(1), at(2)); // Define first for recursion
+ // Define first for recursion
+ cenv.def(checked_cast<ASymbol*>(at(1)), at(2), cenv.type(at(2)), NULL);
at(2)->lift(cenv);
}
@@ -630,11 +644,11 @@ eval(CEnv& cenv, const string& name, istream& is)
int
repl(CEnv& cenv)
{
- Constraints c;
while (1) {
cenv.out << "() ";
cenv.out.flush();
Cursor cursor("(stdin)");
+ Constraints c;
try {
SExp exp = readExpression(cursor, std::cin);
@@ -643,6 +657,10 @@ repl(CEnv& cenv)
AST* body = cenv.penv.parse(exp); // Parse input
body->constrain(cenv.tenv, c); // Constrain types
+
+ for (TEnv::GenericTypes::const_iterator i = cenv.tenv.genericTypes.begin();
+ i != cenv.tenv.genericTypes.end(); ++i)
+ c.push_back(Constraint(cenv.tenv.var(i->first), i->second, i->first->loc));
cenv.tsubst = Subst::compose(cenv.tsubst, TEnv::unify(c)); // Solve type constraints