160 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Implements functions for converting between protobufs and C++. Differs from10// proto_to_cxx.cpp by wrapping all the generated C++ code in either a single11// for loop or two nested loops. Also outputs a different function signature12// that includes a size_t parameter for the loop to use. The C++ code generated13// 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 form23#include <google/protobuf/text_format.h>24 25#include <ostream>26#include <sstream>27 28namespace clang_fuzzer {29 30static bool inner_loop = false;31class InnerLoop {32 public:33 InnerLoop() {34 inner_loop = true;35 }36 ~InnerLoop() {37 inner_loop = false;38 }39};40 41// Forward decls.42std::ostream &operator<<(std::ostream &os, const BinaryOp &x);43std::ostream &operator<<(std::ostream &os, const StatementSeq &x);44 45// Proto to C++.46std::ostream &operator<<(std::ostream &os, const Const &x) {47 return os << "(" << x.val() << ")";48}49std::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}60std::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}69std::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}111std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {112 return os << x.varref() << "=" << x.rvalue() << ";\n";113}114std::ostream &operator<<(std::ostream &os, const Statement &x) {115 return os << x.assignment();116}117std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {118 for (auto &st : x.statements())119 os << st;120 return os;121}122void 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}132void 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}137std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {138 if (x.has_inner_statements())139 NestedLoopToString(os, x);140 else141 SingleLoopToString(os, x);142 return os;143}144 145// ---------------------------------146 147std::string LoopFunctionToString(const LoopFunction &input) {148 std::ostringstream os;149 os << input;150 return os.str();151}152std::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_fuzzer160