xref: /llvm-project/clang/tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
1410a6b2cSVitaly Buka //==-- loop_proto_to_cxx.cpp - Protobuf-C++ conversion ---------------------==//
2410a6b2cSVitaly Buka //
3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6410a6b2cSVitaly Buka //
7410a6b2cSVitaly Buka //===----------------------------------------------------------------------===//
8410a6b2cSVitaly Buka //
91dc1ff85SMatt Morehouse // Implements functions for converting between protobufs and C++. Differs from
10ba58c3a3SEmmett Neyman // proto_to_cxx.cpp by wrapping all the generated C++ code in either a single
11ba58c3a3SEmmett Neyman // for loop or two nested loops. Also outputs a different function signature
12ba58c3a3SEmmett Neyman // that includes a size_t parameter for the loop to use. The C++ code generated
13ba58c3a3SEmmett Neyman // is meant to stress the LLVM loop vectorizer.
141dc1ff85SMatt Morehouse //
151dc1ff85SMatt Morehouse // Still a work in progress.
16410a6b2cSVitaly Buka //
17410a6b2cSVitaly Buka //===----------------------------------------------------------------------===//
18410a6b2cSVitaly Buka 
19410a6b2cSVitaly Buka #include "cxx_loop_proto.pb.h"
20410a6b2cSVitaly Buka #include "proto_to_cxx.h"
21410a6b2cSVitaly Buka 
22410a6b2cSVitaly Buka // The following is needed to convert protos in human-readable form
23410a6b2cSVitaly Buka #include <google/protobuf/text_format.h>
24410a6b2cSVitaly Buka 
25410a6b2cSVitaly Buka #include <ostream>
26410a6b2cSVitaly Buka #include <sstream>
27410a6b2cSVitaly Buka 
28410a6b2cSVitaly Buka namespace clang_fuzzer {
29410a6b2cSVitaly Buka 
30ba58c3a3SEmmett Neyman static bool inner_loop = false;
31ba58c3a3SEmmett Neyman class InnerLoop {
32ba58c3a3SEmmett Neyman   public:
InnerLoop()33ba58c3a3SEmmett Neyman   InnerLoop() {
34ba58c3a3SEmmett Neyman     inner_loop = true;
35ba58c3a3SEmmett Neyman   }
~InnerLoop()36ba58c3a3SEmmett Neyman   ~InnerLoop() {
37ba58c3a3SEmmett Neyman     inner_loop = false;
38ba58c3a3SEmmett Neyman   }
39ba58c3a3SEmmett Neyman };
40ba58c3a3SEmmett Neyman 
41410a6b2cSVitaly Buka // Forward decls.
42410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const BinaryOp &x);
43410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const StatementSeq &x);
44410a6b2cSVitaly Buka 
45410a6b2cSVitaly Buka // Proto to C++.
operator <<(std::ostream & os,const Const & x)46410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const Const &x) {
47410a6b2cSVitaly Buka   return os << "(" << x.val() << ")";
48410a6b2cSVitaly Buka }
operator <<(std::ostream & os,const VarRef & x)493416773cSMatt Morehouse std::ostream &operator<<(std::ostream &os, const VarRef &x) {
50ba58c3a3SEmmett Neyman   std::string which_loop = inner_loop ? "j" : "i";
513416773cSMatt Morehouse   switch (x.arr()) {
523416773cSMatt Morehouse     case VarRef::ARR_A:
53ba58c3a3SEmmett Neyman       return os << "a[" << which_loop << "]";
543416773cSMatt Morehouse     case VarRef::ARR_B:
55ba58c3a3SEmmett Neyman       return os << "b[" << which_loop << "]";
563416773cSMatt Morehouse     case VarRef::ARR_C:
57ba58c3a3SEmmett Neyman       return os << "c[" << which_loop << "]";
583416773cSMatt Morehouse   }
593416773cSMatt Morehouse }
operator <<(std::ostream & os,const Rvalue & x)60410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const Rvalue &x) {
61410a6b2cSVitaly Buka   if (x.has_cons())
62410a6b2cSVitaly Buka     return os << x.cons();
63410a6b2cSVitaly Buka   if (x.has_binop())
64410a6b2cSVitaly Buka     return os << x.binop();
653416773cSMatt Morehouse   if (x.has_varref())
663416773cSMatt Morehouse     return os << x.varref();
67410a6b2cSVitaly Buka   return os << "1";
68410a6b2cSVitaly Buka }
operator <<(std::ostream & os,const BinaryOp & x)69410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const BinaryOp &x) {
70410a6b2cSVitaly Buka   os << "(" << x.left();
71410a6b2cSVitaly Buka   switch (x.op()) {
72410a6b2cSVitaly Buka   case BinaryOp::PLUS:
73410a6b2cSVitaly Buka     os << "+";
74410a6b2cSVitaly Buka     break;
75410a6b2cSVitaly Buka   case BinaryOp::MINUS:
76410a6b2cSVitaly Buka     os << "-";
77410a6b2cSVitaly Buka     break;
78410a6b2cSVitaly Buka   case BinaryOp::MUL:
79410a6b2cSVitaly Buka     os << "*";
80410a6b2cSVitaly Buka     break;
81410a6b2cSVitaly Buka   case BinaryOp::XOR:
82410a6b2cSVitaly Buka     os << "^";
83410a6b2cSVitaly Buka     break;
84410a6b2cSVitaly Buka   case BinaryOp::AND:
85410a6b2cSVitaly Buka     os << "&";
86410a6b2cSVitaly Buka     break;
87410a6b2cSVitaly Buka   case BinaryOp::OR:
88410a6b2cSVitaly Buka     os << "|";
89410a6b2cSVitaly Buka     break;
90410a6b2cSVitaly Buka   case BinaryOp::EQ:
91410a6b2cSVitaly Buka     os << "==";
92410a6b2cSVitaly Buka     break;
93410a6b2cSVitaly Buka   case BinaryOp::NE:
94410a6b2cSVitaly Buka     os << "!=";
95410a6b2cSVitaly Buka     break;
96410a6b2cSVitaly Buka   case BinaryOp::LE:
97410a6b2cSVitaly Buka     os << "<=";
98410a6b2cSVitaly Buka     break;
99410a6b2cSVitaly Buka   case BinaryOp::GE:
100410a6b2cSVitaly Buka     os << ">=";
101410a6b2cSVitaly Buka     break;
102410a6b2cSVitaly Buka   case BinaryOp::LT:
103410a6b2cSVitaly Buka     os << "<";
104410a6b2cSVitaly Buka     break;
105410a6b2cSVitaly Buka   case BinaryOp::GT:
106410a6b2cSVitaly Buka     os << ">";
107410a6b2cSVitaly Buka     break;
108410a6b2cSVitaly Buka   }
109410a6b2cSVitaly Buka   return os << x.right() << ")";
110410a6b2cSVitaly Buka }
operator <<(std::ostream & os,const AssignmentStatement & x)111410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
1123416773cSMatt Morehouse   return os << x.varref() << "=" << x.rvalue() << ";\n";
113410a6b2cSVitaly Buka }
operator <<(std::ostream & os,const Statement & x)114410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const Statement &x) {
1153416773cSMatt Morehouse   return os << x.assignment();
116410a6b2cSVitaly Buka }
operator <<(std::ostream & os,const StatementSeq & x)117410a6b2cSVitaly Buka std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
118410a6b2cSVitaly Buka   for (auto &st : x.statements())
119410a6b2cSVitaly Buka     os << st;
120410a6b2cSVitaly Buka   return os;
121410a6b2cSVitaly Buka }
NestedLoopToString(std::ostream & os,const LoopFunction & x)122ba58c3a3SEmmett Neyman void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
123ba58c3a3SEmmett Neyman   os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
1241dc1ff85SMatt Morehouse      << "for (int i=0; i<s; i++){\n"
125ba58c3a3SEmmett Neyman      << "for (int j=0; j<s; j++){\n";
126ba58c3a3SEmmett Neyman   {
127ba58c3a3SEmmett Neyman     InnerLoop IL;
128ba58c3a3SEmmett Neyman     os << x.inner_statements() << "}\n";
129ba58c3a3SEmmett Neyman   }
130ba58c3a3SEmmett Neyman   os << x.outer_statements() << "}\n}\n";
131ba58c3a3SEmmett Neyman }
SingleLoopToString(std::ostream & os,const LoopFunction & x)132ba58c3a3SEmmett Neyman void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
133ba58c3a3SEmmett Neyman   os << "void foo(int *a, int *b, int *__restrict__ c, size_t s) {\n"
134ba58c3a3SEmmett Neyman      << "for (int i=0; i<s; i++){\n"
135ba58c3a3SEmmett Neyman      << x.outer_statements() << "}\n}\n";
136ba58c3a3SEmmett Neyman }
operator <<(std::ostream & os,const LoopFunction & x)137ba58c3a3SEmmett Neyman std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
138ba58c3a3SEmmett Neyman   if (x.has_inner_statements())
139ba58c3a3SEmmett Neyman     NestedLoopToString(os, x);
140ba58c3a3SEmmett Neyman   else
141ba58c3a3SEmmett Neyman     SingleLoopToString(os, x);
142ba58c3a3SEmmett Neyman   return os;
143410a6b2cSVitaly Buka }
144410a6b2cSVitaly Buka 
145410a6b2cSVitaly Buka // ---------------------------------
146410a6b2cSVitaly Buka 
LoopFunctionToString(const LoopFunction & input)147410a6b2cSVitaly Buka std::string LoopFunctionToString(const LoopFunction &input) {
148410a6b2cSVitaly Buka   std::ostringstream os;
149410a6b2cSVitaly Buka   os << input;
150410a6b2cSVitaly Buka   return os.str();
151410a6b2cSVitaly Buka }
LoopProtoToCxx(const uint8_t * data,size_t size)152410a6b2cSVitaly Buka std::string LoopProtoToCxx(const uint8_t *data, size_t size) {
153410a6b2cSVitaly Buka   LoopFunction message;
154410a6b2cSVitaly Buka   if (!message.ParsePartialFromArray(data, size))
1551dc1ff85SMatt Morehouse     return "#error invalid proto\n";
156410a6b2cSVitaly Buka   return LoopFunctionToString(message);
157410a6b2cSVitaly Buka }
158410a6b2cSVitaly Buka 
159410a6b2cSVitaly Buka } // namespace clang_fuzzer
160