1 //==-- loop_proto_to_cxx.cpp - Protobuf-C++ conversion ---------------------==// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Implements functions for converting between protobufs and C++. Differs from 10 // proto_to_cxx.cpp by wrapping all the generated C++ code in either a single 11 // for loop or two nested loops. Also outputs a different function signature 12 // that includes a size_t parameter for the loop to use. The C++ code generated 13 // is meant to stress the LLVM loop vectorizer. 14 // 15 // Still a work in progress. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #include "cxx_loop_proto.pb.h" 20 #include "proto_to_cxx.h" 21 22 // The following is needed to convert protos in human-readable form 23 #include <google/protobuf/text_format.h> 24 25 #include <ostream> 26 #include <sstream> 27 28 namespace clang_fuzzer { 29 30 static bool inner_loop = false; 31 class InnerLoop { 32 public: 33 InnerLoop() { 34 inner_loop = true; 35 } 36 ~InnerLoop() { 37 inner_loop = false; 38 } 39 }; 40 41 // Forward decls. 42 std::ostream &operator<<(std::ostream &os, const BinaryOp &x); 43 std::ostream &operator<<(std::ostream &os, const StatementSeq &x); 44 45 // Proto to C++. 46 std::ostream &operator<<(std::ostream &os, const Const &x) { 47 return os << "(" << x.val() << ")"; 48 } 49 std::ostream &operator<<(std::ostream &os, const VarRef &x) { 50 std::string which_loop = inner_loop ? "j" : "i"; 51 switch (x.arr()) { 52 case VarRef::ARR_A: 53 return os << "a[" << which_loop << "]"; 54 case VarRef::ARR_B: 55 return os << "b[" << which_loop << "]"; 56 case VarRef::ARR_C: 57 return os << "c[" << which_loop << "]"; 58 } 59 } 60 std::ostream &operator<<(std::ostream &os, const Rvalue &x) { 61 if (x.has_cons()) 62 return os << x.cons(); 63 if (x.has_binop()) 64 return os << x.binop(); 65 if (x.has_varref()) 66 return os << x.varref(); 67 return os << "1"; 68 } 69 std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { 70 os << "(" << x.left(); 71 switch (x.op()) { 72 case BinaryOp::PLUS: 73 os << "+"; 74 break; 75 case BinaryOp::MINUS: 76 os << "-"; 77 break; 78 case BinaryOp::MUL: 79 os << "*"; 80 break; 81 case BinaryOp::XOR: 82 os << "^"; 83 break; 84 case BinaryOp::AND: 85 os << "&"; 86 break; 87 case BinaryOp::OR: 88 os << "|"; 89 break; 90 case BinaryOp::EQ: 91 os << "=="; 92 break; 93 case BinaryOp::NE: 94 os << "!="; 95 break; 96 case BinaryOp::LE: 97 os << "<="; 98 break; 99 case BinaryOp::GE: 100 os << ">="; 101 break; 102 case BinaryOp::LT: 103 os << "<"; 104 break; 105 case BinaryOp::GT: 106 os << ">"; 107 break; 108 } 109 return os << x.right() << ")"; 110 } 111 std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { 112 return os << x.varref() << "=" << x.rvalue() << ";\n"; 113 } 114 std::ostream &operator<<(std::ostream &os, const Statement &x) { 115 return os << x.assignment(); 116 } 117 std::ostream &operator<<(std::ostream &os, const StatementSeq &x) { 118 for (auto &st : x.statements()) 119 os << st; 120 return os; 121 } 122 void NestedLoopToString(std::ostream &os, const LoopFunction &x) { 123 os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n" 124 << "for (int i=0; i<s; i++){\n" 125 << "for (int j=0; j<s; j++){\n"; 126 { 127 InnerLoop IL; 128 os << x.inner_statements() << "}\n"; 129 } 130 os << x.outer_statements() << "}\n}\n"; 131 } 132 void SingleLoopToString(std::ostream &os, const LoopFunction &x) { 133 os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n" 134 << "for (int i=0; i<s; i++){\n" 135 << x.outer_statements() << "}\n}\n"; 136 } 137 std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { 138 if (x.has_inner_statements()) 139 NestedLoopToString(os, x); 140 else 141 SingleLoopToString(os, x); 142 return os; 143 } 144 145 // --------------------------------- 146 147 std::string LoopFunctionToString(const LoopFunction &input) { 148 std::ostringstream os; 149 os << input; 150 return os.str(); 151 } 152 std::string LoopProtoToCxx(const uint8_t *data, size_t size) { 153 LoopFunction message; 154 if (!message.ParsePartialFromArray(data, size)) 155 return "#error invalid proto\n"; 156 return LoopFunctionToString(message); 157 } 158 159 } // namespace clang_fuzzer 160