diff options
Diffstat (limited to 'tuplr_llvm.cpp')
-rw-r--r-- | tuplr_llvm.cpp | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/tuplr_llvm.cpp b/tuplr_llvm.cpp index 8d1f1db..3c5ee17 100644 --- a/tuplr_llvm.cpp +++ b/tuplr_llvm.cpp @@ -40,6 +40,12 @@ struct CEngine { llvm::IRBuilder<> builder; }; +struct CArg { + CArg(int o=0, int a=0) : op(o), arg(a) {} + int op; + int arg; +}; + using namespace llvm; using namespace std; using boost::format; @@ -76,13 +82,13 @@ ASTPrimitive::constrain(TEnv& tenv) const { FOREACH(const_iterator, p, *this) (*p)->constrain(tenv); - if (OP_IS_A(arg.op, Instruction::BinaryOps)) { + if (OP_IS_A(arg->op, Instruction::BinaryOps)) { if (size() <= 2) throw Error((format("`%1%' requires at least 2 arguments") % at(0)->str()).str(), exp.loc); AType* tvar = tenv.type(this); for (size_t i = 1; i < size(); ++i) tenv.constrain(at(i), tvar); - } else if (arg.op == Instruction::ICmp) { + } else if (arg->op == Instruction::ICmp) { if (size() != 3) throw Error((format("`%1%' requires exactly 2 arguments") % at(0)->str()).str(), exp.loc); tenv.constrain(at(1), tenv.type(at(2))); @@ -362,30 +368,30 @@ ASTPrimitive::compile(CEnv& cenv) Value* a = LLVal(cenv.compile(at(1))); Value* b = LLVal(cenv.compile(at(2))); - if (OP_IS_A(arg.op, Instruction::BinaryOps)) { - const Instruction::BinaryOps bo = (Instruction::BinaryOps)arg.op; + if (OP_IS_A(arg->op, Instruction::BinaryOps)) { + const Instruction::BinaryOps bo = (Instruction::BinaryOps)arg->op; if (size() == 2) return cenv.compile(at(1)); Value* val = cenv.engine.builder.CreateBinOp(bo, a, b); for (size_t i = 3; i < size(); ++i) val = cenv.engine.builder.CreateBinOp(bo, val, LLVal(cenv.compile(at(i)))); return val; - } else if (arg.op == Instruction::ICmp) { + } else if (arg->op == Instruction::ICmp) { bool isInt = cenv.tenv.type(at(1))->str() == "Int"; if (isInt) { - return cenv.engine.builder.CreateICmp((CmpInst::Predicate)arg.arg, a, b); + return cenv.engine.builder.CreateICmp((CmpInst::Predicate)arg->arg, a, b); } else { // Translate to floating point operation - switch (arg.arg) { - case CmpInst::ICMP_EQ: arg.arg = CmpInst::FCMP_OEQ; break; - case CmpInst::ICMP_NE: arg.arg = CmpInst::FCMP_ONE; break; - case CmpInst::ICMP_SGT: arg.arg = CmpInst::FCMP_OGT; break; - case CmpInst::ICMP_SGE: arg.arg = CmpInst::FCMP_OGE; break; - case CmpInst::ICMP_SLT: arg.arg = CmpInst::FCMP_OLT; break; - case CmpInst::ICMP_SLE: arg.arg = CmpInst::FCMP_OLE; break; + switch (arg->arg) { + case CmpInst::ICMP_EQ: arg->arg = CmpInst::FCMP_OEQ; break; + case CmpInst::ICMP_NE: arg->arg = CmpInst::FCMP_ONE; break; + case CmpInst::ICMP_SGT: arg->arg = CmpInst::FCMP_OGT; break; + case CmpInst::ICMP_SGE: arg->arg = CmpInst::FCMP_OGE; break; + case CmpInst::ICMP_SLT: arg->arg = CmpInst::FCMP_OLT; break; + case CmpInst::ICMP_SLE: arg->arg = CmpInst::FCMP_OLE; break; default: throw Error("Unknown primitive", exp.loc); } - return cenv.engine.builder.CreateFCmp((CmpInst::Predicate)arg.arg, a, b); + return cenv.engine.builder.CreateFCmp((CmpInst::Predicate)arg->arg, a, b); } } throw Error("Unknown primitive", exp.loc); @@ -598,31 +604,39 @@ repl(CEnv& cenv) int main(int argc, char** argv) { -#define PRIM(O, A) PEnv::Parser(parseAST<ASTPrimitive>, CArg(Instruction:: O, A)) PEnv penv; - penv.reg("fn", PEnv::Parser(parseFn)); - penv.reg("if", PEnv::Parser(parseAST<ASTIf>)); - penv.reg("def", PEnv::Parser(parseAST<ASTDefinition>)); - penv.reg("cons", PEnv::Parser(parseAST<ASTConsCall>)); - penv.reg("car", PEnv::Parser(parseAST<ASTCarCall>)); - penv.reg("cdr", PEnv::Parser(parseAST<ASTCdrCall>)); - penv.reg("+", PRIM(Add, 0)); - penv.reg("-", PRIM(Sub, 0)); - penv.reg("*", PRIM(Mul, 0)); - penv.reg("/", PRIM(FDiv, 0)); - penv.reg("%", PRIM(FRem, 0)); - penv.reg("&", PRIM(And, 0)); - penv.reg("|", PRIM(Or, 0)); - penv.reg("^", PRIM(Xor, 0)); - penv.reg("=", PRIM(ICmp, CmpInst::ICMP_EQ)); - penv.reg("!=", PRIM(ICmp, CmpInst::ICMP_NE)); - penv.reg(">", PRIM(ICmp, CmpInst::ICMP_SGT)); - penv.reg(">=", PRIM(ICmp, CmpInst::ICMP_SGE)); - penv.reg("<", PRIM(ICmp, CmpInst::ICMP_SLT)); - penv.reg("<=", PRIM(ICmp, CmpInst::ICMP_SLE)); + penv.reg(true, "fn", PEnv::Handler(parseFn)); + penv.reg(true, "if", PEnv::Handler(parseCall<ASTIf>)); + penv.reg(true, "def", PEnv::Handler(parseCall<ASTDefinition>)); + penv.reg(true, "cons", PEnv::Handler(parseCall<ASTConsCall>)); + penv.reg(true, "car", PEnv::Handler(parseCall<ASTCarCall>)); + penv.reg(true, "cdr", PEnv::Handler(parseCall<ASTCdrCall>)); + + bool trueVal = true; + bool falseVal = false; + penv.reg(false, "true", PEnv::Handler(parseLiteral<bool>, (CArg*)&trueVal)); + penv.reg(false, "false", PEnv::Handler(parseLiteral<bool>, (CArg*)&falseVal)); + + map<string, CArg> prims; + prims.insert(make_pair("+", CArg(Instruction::Add))); + prims.insert(make_pair("-", CArg(Instruction::Sub))); + prims.insert(make_pair("*", CArg(Instruction::Mul))); + prims.insert(make_pair("/", CArg(Instruction::FDiv))); + prims.insert(make_pair("%", CArg(Instruction::FRem))); + prims.insert(make_pair("&", CArg(Instruction::And))); + prims.insert(make_pair("|", CArg(Instruction::Or))); + prims.insert(make_pair("^", CArg(Instruction::Xor))); + prims.insert(make_pair("=", CArg(Instruction::ICmp, CmpInst::ICMP_EQ))); + prims.insert(make_pair("!=", CArg(Instruction::ICmp, CmpInst::ICMP_NE))); + prims.insert(make_pair(">", CArg(Instruction::ICmp, CmpInst::ICMP_SGT))); + prims.insert(make_pair(">=", CArg(Instruction::ICmp, CmpInst::ICMP_SGE))); + prims.insert(make_pair("<", CArg(Instruction::ICmp, CmpInst::ICMP_SLT))); + prims.insert(make_pair("<=", CArg(Instruction::ICmp, CmpInst::ICMP_SLE))); + for (map<string,CArg>::iterator p = prims.begin(); p != prims.end(); ++p) + penv.reg(true, p->first, PEnv::Handler(parseCall<ASTPrimitive>, &p->second)); CEngine engine; - CEnv cenv(penv, engine); + CEnv cenv(penv, engine); cenv.tenv.def(penv.sym("Bool"), new AType(penv.sym("Bool"), Type::Int1Ty)); cenv.tenv.def(penv.sym("Int"), new AType(penv.sym("Int"), Type::Int32Ty)); |