From 9d698c8078bdf219d122213b8d4834595ff774ba Mon Sep 17 00:00:00 2001 From: Tomas Pecka <peckato1@fit.cvut.cz> Date: Mon, 30 Nov 2015 22:02:51 +0100 Subject: [PATCH 1/4] gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cca2b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.swp +build/ From 4fb51e8aa24bfb60e4c1a4a130b0a8298b2194e0 Mon Sep 17 00:00:00 2001 From: Tomas Pecka <peckato1@fit.cvut.cz> Date: Fri, 4 Dec 2015 15:22:09 +0100 Subject: [PATCH 2/4] exam tasks 1-4 --- compiler.cpp | 3 +++ runtime.cpp | 13 +++++++++++-- tests.cpp | 9 +++++---- type_analysis.cpp | 3 +++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/compiler.cpp b/compiler.cpp index 606a455..8ae0cc7 100644 --- a/compiler.cpp +++ b/compiler.cpp @@ -390,6 +390,9 @@ class Compiler : public Visitor { case ast::BinExp::Type::gt: result = RUNTIME_CALL(genericGt, lhs, rhs); return; + case ast::BinExp::Type::dot: + result = RUNTIME_CALL(genericDot, lhs, rhs); + return; default: // can't happen return; } diff --git a/runtime.cpp b/runtime.cpp index c1bdd1f..3d51c14 100644 --- a/runtime.cpp +++ b/runtime.cpp @@ -526,11 +526,20 @@ RVal * c(int size, ...) { } double doubleDot(DoubleVector * lhs, DoubleVector * rhs) { - assert(false and "Fill me in"); + int mLen = std::max(lhs->size, rhs->size); + double res = 0; + + for(int i = 0; i < mLen; i++) + { + res += lhs->data[i % lhs->size] * rhs->data[i % rhs->size]; + } + return res; } RVal * genericDot(RVal * lhs, RVal * rhs) { - assert(false and "Fill me in"); + if(lhs->type != RVal::Type::Double || rhs->type != RVal::Type::Double) + throw "Both operands to dot product must be double vectors"; + return new RVal(new DoubleVector(doubleDot(lhs->d, rhs->d))); } diff --git a/tests.cpp b/tests.cpp index fe05cac..ef33cb6 100644 --- a/tests.cpp +++ b/tests.cpp @@ -86,7 +86,8 @@ namespace rift { TEST("(f = function(a, b) { a %*% b })(c(1,2,3), c(3,2,1))", 10); TEST("(f = function(a, b) { a %*% b })(c(1,2,3), 3)", 18); TEST("(f = function(a, b) { a %*% b })(10, 2)", 20); - TEST("(f = function(a, b) { a %*% b })(c(1,2,3,4), c(5,6))", 5 + 6 * 2 + 3 * 5 + 4 * 6); + TEST("(f = function(a, b) { a %*% b })(c(1,2,3,4), c(5,6))", 1*5 + 2*6 + 3*5 + 4*6); + TEST("(f = function(a, b) { a %*% b })(c(1,2), c(5))", 1*5 + 2*5); } /** Checks that a dot operator result type is correctly set to be double scalar by the type analysis. */ @@ -222,9 +223,9 @@ namespace rift { TEST("a = \"aba\" a[c(0,2)]", "aa"); TEST("a = c(1,2,3) a[c(0,1)] = 56 a", 56, 56, 3); - // project2(); - // project3(); - // project4(); + project2(); + project3(); + project4(); // project5(); // project6(); } diff --git a/type_analysis.cpp b/type_analysis.cpp index 136e3f7..3821e94 100644 --- a/type_analysis.cpp +++ b/type_analysis.cpp @@ -108,6 +108,9 @@ bool TypeAnalysis::runOnFunction(llvm::Function & f) { genericRelational(ci); } else if (s == "genericGt") { genericRelational(ci); + } else if (s == "genericDot") { + // DV with len 1 is R->DV->D? + state.update(ci, new AType(AType::Kind::R, new AType(AType::Kind::DV, new AType(AType::Kind::D)))); } else if (s == "length") { // result of length operation is always // double scalar From 1e3556bf1998b9d7e5968235f45e45c129837eab Mon Sep 17 00:00:00 2001 From: Tomas Pecka <peckato1@fit.cvut.cz> Date: Fri, 4 Dec 2015 16:46:51 +0100 Subject: [PATCH 3/4] exam tasks 5,6 --- tests.cpp | 4 ++-- unboxing.cpp | 26 ++++++++++++++++++++++++++ unboxing.h | 2 ++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/tests.cpp b/tests.cpp index ef33cb6..3105f55 100644 --- a/tests.cpp +++ b/tests.cpp @@ -226,8 +226,8 @@ namespace rift { project2(); project3(); project4(); - // project5(); - // project6(); + project5(); + project6(); } } // namespace rift diff --git a/unboxing.cpp b/unboxing.cpp index 2b11f32..8231520 100644 --- a/unboxing.cpp +++ b/unboxing.cpp @@ -169,6 +169,30 @@ bool Unboxing::genericArithmetic(llvm::Instruction::BinaryOps op, llvm::Function } } +bool Unboxing::genericDot() { + AType *lhs = state().get(ins->getOperand(0)); + AType *rhs = state().get(ins->getOperand(1)); + AType *result_t; + + // both must be doubles + if(not (lhs->isDouble() and rhs->isDouble())) { + return false; + } + + if(lhs->isScalar() and rhs->isScalar()) { + result_t = updateAnalysis( + BinaryOperator::Create(Instruction::FMul, getScalarPayload(lhs), getScalarPayload(rhs), "", ins), + new AType(AType::Kind::D)); + } else { + result_t = updateAnalysis( + RUNTIME_CALL(m->doubleDot, getVectorPayload(lhs), getVectorPayload(rhs)), + new AType(AType::Kind::D)); + } + + ins->replaceAllUsesWith(box(result_t)); + return true; +} + void Unboxing::doubleRelational(AType * lhs, AType * rhs, llvm::CmpInst::Predicate op, llvm::Function * fop) { assert(lhs->isDouble() and rhs->isDouble() and "Doubles expected"); AType * result_t; @@ -337,6 +361,8 @@ bool Unboxing::runOnFunction(llvm::Function & f) { erase = genericArithmetic(Instruction::FMul, m->doubleMul); } else if (s == "genericDiv") { erase = genericArithmetic(Instruction::FDiv, m->doubleDiv); + } else if (s == "genericDot") { + erase = genericDot(); } else if (s == "genericLt") { erase = genericRelational(FCmpInst::FCMP_OLT, m->doubleLt); } else if (s == "genericGt") { diff --git a/unboxing.h b/unboxing.h index bb134c1..16ed2bf 100644 --- a/unboxing.h +++ b/unboxing.h @@ -46,6 +46,8 @@ class Unboxing : public llvm::FunctionPass { void doubleArithmetic(AType * lhs, AType * rhs, llvm::Instruction::BinaryOps op, llvm::Function * fop); + bool genericDot(); + bool genericAdd(); bool genericArithmetic(llvm::Instruction::BinaryOps op, llvm::Function * fop); From c0436c0e8266b6d094e75042169d98925373bb92 Mon Sep 17 00:00:00 2001 From: Tomas Pecka <peckato1@fit.cvut.cz> Date: Fri, 4 Dec 2015 16:54:46 +0100 Subject: [PATCH 4/4] logic bugfix --- unboxing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unboxing.cpp b/unboxing.cpp index 8231520..92d9a17 100644 --- a/unboxing.cpp +++ b/unboxing.cpp @@ -175,7 +175,7 @@ bool Unboxing::genericDot() { AType *result_t; // both must be doubles - if(not (lhs->isDouble() and rhs->isDouble())) { + if(not lhs->isDouble() or not rhs->isDouble()) { return false; }