//===----------------------------------------------------------------------===//
//
// Implements functions for converting between protobufs and C++. Differs from
-// proto_to_cxx.cpp by wrapping all the generated C++ code in a single for
-// loop. Also coutputs a different function signature that includes a
-// size_t parameter for the loop to use. The C++ code generated is meant to
-// stress the LLVM loop vectorizer.
+// proto_to_cxx.cpp by wrapping all the generated C++ code in either a single
+// for loop or two nested loops. Also outputs a different function signature
+// that includes a size_t parameter for the loop to use. The C++ code generated
+// is meant to stress the LLVM loop vectorizer.
//
// Still a work in progress.
//
namespace clang_fuzzer {
+static bool inner_loop = false;
+class InnerLoop {
+ public:
+ InnerLoop() {
+ inner_loop = true;
+ }
+ ~InnerLoop() {
+ inner_loop = false;
+ }
+};
+
// Forward decls.
std::ostream &operator<<(std::ostream &os, const BinaryOp &x);
std::ostream &operator<<(std::ostream &os, const StatementSeq &x);
return os << "(" << x.val() << ")";
}
std::ostream &operator<<(std::ostream &os, const VarRef &x) {
+ std::string which_loop = inner_loop ? "j" : "i";
switch (x.arr()) {
case VarRef::ARR_A:
- return os << "a[i]";
+ return os << "a[" << which_loop << "]";
case VarRef::ARR_B:
- return os << "b[i]";
+ return os << "b[" << which_loop << "]";
case VarRef::ARR_C:
- return os << "c[i]";
+ return os << "c[" << which_loop << "]";
}
}
std::ostream &operator<<(std::ostream &os, const Rvalue &x) {
os << st;
return os;
}
+void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
+ << "for (int i=0; i<s; i++){\n"
+ << "for (int j=0; j<s; j++){\n";
+ {
+ InnerLoop IL;
+ os << x.inner_statements() << "}\n";
+ }
+ os << x.outer_statements() << "}\n}\n";
+}
+void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
+ << "for (int i=0; i<s; i++){\n"
+ << x.outer_statements() << "}\n}\n";
+}
std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
- return os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
- << "for (int i=0; i<s; i++){\n"
- << x.statements() << "}\n}\n";
+ if (x.has_inner_statements())
+ NestedLoopToString(os, x);
+ else
+ SingleLoopToString(os, x);
+ return os;
}
// ---------------------------------
std::string StateSeqToString(std::ostream &os, const StatementSeq &x);
// Counter variable to generate new LLVM IR variable names and wrapper function
-std::string get_var() {
+static std::string get_var() {
static int ctr = 0;
return "%var" + std::to_string(ctr++);
}
+static bool inner_loop = false;
+class InnerLoop {
+ public:
+ InnerLoop() {
+ inner_loop = true;
+ }
+ ~InnerLoop() {
+ inner_loop = false;
+ }
+};
+
+
// Proto to LLVM.
std::string ConstToString(const Const &x) {
return std::to_string(x.val());
}
std::string VarRefToString(std::ostream &os, const VarRef &x) {
+ std::string which_loop = inner_loop ? "inner" : "outer";
std::string arr;
switch(x.arr()) {
case VarRef::ARR_A:
break;
}
std::string ptr_var = get_var();
- os << ptr_var << " = getelementptr inbounds i32, i32* " << arr << ", i64 %ct\n";
+ os << ptr_var << " = getelementptr inbounds i32, i32* " << arr
+ << ", i64 %" << which_loop << "_ct\n";
return ptr_var;
}
std::string RvalueToString(std::ostream &os, const Rvalue &x) {
}
return os;
}
+void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
+ << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
+ << "outer_loop_start:\n"
+ << "%cmp = icmp sgt i64 %s, 0\n"
+ << "br i1 %cmp, label %inner_loop_start, label %end\n"
+ << "outer_loop:\n"
+ << x.outer_statements()
+ << "%o_ct_new = add i64 %outer_ct, 1\n"
+ << "%jmp_outer = icmp eq i64 %o_ct_new, %s\n"
+ << "br i1 %jmp_outer, label %end, label %inner_loop_start\n"
+ << "inner_loop_start:\n"
+ << "%outer_ct = phi i64 [%o_ct_new, %outer_loop], [0, %outer_loop_start]\n"
+ << "br label %inner_loop\n"
+ << "inner_loop:\n"
+ << "%inner_ct = phi i64 [0, %inner_loop_start], [%i_ct_new, %inner_loop]\n";
+ {
+ InnerLoop IL;
+ os << x.inner_statements();
+ }
+ os << "%i_ct_new = add i64 %inner_ct, 1\n"
+ << "%jmp_inner = icmp eq i64 %i_ct_new, %s\n"
+ << "br i1 %jmp_inner, label %outer_loop, label %inner_loop, !llvm.loop !0\n"
+ << "end:\n"
+ << "ret void\n"
+ << "}\n"
+ << "!0 = distinct !{!0, !1, !2}\n"
+ << "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
+ << "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
+}
+void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
+ os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
+ << "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
+ << "%cmp = icmp sgt i64 %s, 0\n"
+ << "br i1 %cmp, label %start, label %end\n"
+ << "start:\n"
+ << "br label %loop\n"
+ << "end:\n"
+ << "ret void\n"
+ << "loop:\n"
+ << "%outer_ct = phi i64 [ %ctnew, %loop ], [ 0, %start ]\n"
+ << x.outer_statements()
+ << "%ctnew = add i64 %outer_ct, 1\n"
+ << "%j = icmp eq i64 %ctnew, %s\n"
+ << "br i1 %j, label %end, label %loop, !llvm.loop !0\n}\n"
+ << "!0 = distinct !{!0, !1, !2}\n"
+ << "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
+ << "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
+}
std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
- return os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
- << "define void @foo(i32* %a, i32* %b, i32* %c, i64 %s) {\n"
- << "%1 = icmp sgt i64 %s, 0\n"
- << "br i1 %1, label %start, label %end\n"
- << "start:\n"
- << "br label %loop\n"
- << "end:\n"
- << "ret void\n"
- << "loop:\n"
- << " %ct = phi i64 [ %ctnew, %loop ], [ 0, %start ]\n"
- << x.statements()
- << "%ctnew = add i64 %ct, 1\n"
- << "%j = icmp eq i64 %ctnew, %s\n"
- << "br i1 %j, label %end, label %loop, !llvm.loop !0\n}\n"
- << "!0 = distinct !{!0, !1, !2}\n"
- << "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
- << "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize
- << "}\n";
+ if (x.has_inner_statements())
+ NestedLoopToString(os, x);
+ else
+ SingleLoopToString(os, x);
+ return os;
}
// ---------------------------------