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