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 &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 else
141 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_fuzzer
160

source code of clang/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp