Clang Project

clang_source_code/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.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-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
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 &osconst BinaryOp &x);
43std::ostream &operator<<(std::ostream &osconst StatementSeq &x);
44
45// Proto to C++.
46std::ostream &operator<<(std::ostream &osconst Const &x) {
47  return os << "(" << x.val() << ")";
48}
49std::ostream &operator<<(std::ostream &osconst 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 &osconst 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 &osconst 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 &osconst AssignmentStatement &x) {
112  return os << x.varref() << "=" << x.rvalue() << ";\n";
113}
114std::ostream &operator<<(std::ostream &osconst Statement &x) {
115  return os << x.assignment();
116}
117std::ostream &operator<<(std::ostream &osconst StatementSeq &x) {
118  for (auto &st : x.statements())
119    os << st;
120  return os;
121}
122void NestedLoopToString(std::ostream &osconst 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 &osconst 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 &osconst LoopFunction &x) {
138  if (x.has_inner_statements())
139    NestedLoopToString(osx);
140  else
141    SingleLoopToString(osx);
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_fuzzer
160