teak-llvm/clang/tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp
Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

210 lines
6.1 KiB
C++

//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion
//---------------------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Implements functions for converting between protobufs and LLVM IR.
//
//
//===----------------------------------------------------------------------===//
#include "loop_proto_to_llvm.h"
#include "cxx_loop_proto.pb.h"
#include "../handle-llvm/input_arrays.h"
// The following is needed to convert protos in human-readable form
#include <google/protobuf/text_format.h>
#include <ostream>
#include <sstream>
namespace clang_fuzzer {
// Forward decls
std::string BinopToString(std::ostream &os, const BinaryOp &x);
std::string StateSeqToString(std::ostream &os, const StatementSeq &x);
// Counter variable to generate new LLVM IR variable names and wrapper function
static std::string get_var() {
static int ctr = 0;
return "%var" + std::to_string(ctr++);
}
static bool inner_loop = false;
class InnerLoop {
public:
InnerLoop() {
inner_loop = true;
}
~InnerLoop() {
inner_loop = false;
}
};
// Proto to LLVM.
std::string ConstToString(const Const &x) {
return std::to_string(x.val());
}
std::string VarRefToString(std::ostream &os, const VarRef &x) {
std::string which_loop = inner_loop ? "inner" : "outer";
std::string arr;
switch(x.arr()) {
case VarRef::ARR_A:
arr = "%a";
break;
case VarRef::ARR_B:
arr = "%b";
break;
case VarRef::ARR_C:
arr = "%c";
break;
}
std::string ptr_var = get_var();
os << ptr_var << " = getelementptr inbounds i32, i32* " << arr
<< ", i64 %" << which_loop << "_ct\n";
return ptr_var;
}
std::string RvalueToString(std::ostream &os, const Rvalue &x) {
if(x.has_cons())
return ConstToString(x.cons());
if(x.has_binop())
return BinopToString(os, x.binop());
if(x.has_varref()) {
std::string var_ref = VarRefToString(os, x.varref());
std::string val_var = get_var();
os << val_var << " = load i32, i32* " << var_ref << "\n";
return val_var;
}
return "1";
}
std::string BinopToString(std::ostream &os, const BinaryOp &x) {
std::string left = RvalueToString(os, x.left());
std::string right = RvalueToString(os, x.right());
std::string op;
switch (x.op()) {
case BinaryOp::PLUS:
op = "add";
break;
case BinaryOp::MINUS:
op = "sub";
break;
case BinaryOp::MUL:
op = "mul";
break;
case BinaryOp::XOR:
op = "xor";
break;
case BinaryOp::AND:
op = "and";
break;
case BinaryOp::OR:
op = "or";
break;
// Support for Boolean operators will be added later
case BinaryOp::EQ:
case BinaryOp::NE:
case BinaryOp::LE:
case BinaryOp::GE:
case BinaryOp::LT:
case BinaryOp::GT:
op = "add";
break;
}
std::string val_var = get_var();
os << val_var << " = " << op << " i32 " << left << ", " << right << "\n";
return val_var;
}
std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
std::string rvalue = RvalueToString(os, x.rvalue());
std::string var_ref = VarRefToString(os, x.varref());
return os << "store i32 " << rvalue << ", i32* " << var_ref << "\n";
}
std::ostream &operator<<(std::ostream &os, const Statement &x) {
return os << x.assignment();
}
std::ostream &operator<<(std::ostream &os, const StatementSeq &x) {
for (auto &st : x.statements()) {
os << st;
}
return os;
}
void NestedLoopToString(std::ostream &os, const LoopFunction &x) {
os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
<< "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
<< "outer_loop_start:\n"
<< "%cmp = icmp sgt i64 %s, 0\n"
<< "br i1 %cmp, label %inner_loop_start, label %end\n"
<< "outer_loop:\n"
<< x.outer_statements()
<< "%o_ct_new = add i64 %outer_ct, 1\n"
<< "%jmp_outer = icmp eq i64 %o_ct_new, %s\n"
<< "br i1 %jmp_outer, label %end, label %inner_loop_start\n"
<< "inner_loop_start:\n"
<< "%outer_ct = phi i64 [%o_ct_new, %outer_loop], [0, %outer_loop_start]\n"
<< "br label %inner_loop\n"
<< "inner_loop:\n"
<< "%inner_ct = phi i64 [0, %inner_loop_start], [%i_ct_new, %inner_loop]\n";
{
InnerLoop IL;
os << x.inner_statements();
}
os << "%i_ct_new = add i64 %inner_ct, 1\n"
<< "%jmp_inner = icmp eq i64 %i_ct_new, %s\n"
<< "br i1 %jmp_inner, label %outer_loop, label %inner_loop, !llvm.loop !0\n"
<< "end:\n"
<< "ret void\n"
<< "}\n"
<< "!0 = distinct !{!0, !1, !2}\n"
<< "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
<< "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
}
void SingleLoopToString(std::ostream &os, const LoopFunction &x) {
os << "target triple = \"x86_64-unknown-linux-gnu\"\n"
<< "define void @foo(i32* %a, i32* %b, i32* noalias %c, i64 %s) {\n"
<< "%cmp = icmp sgt i64 %s, 0\n"
<< "br i1 %cmp, label %start, label %end\n"
<< "start:\n"
<< "br label %loop\n"
<< "end:\n"
<< "ret void\n"
<< "loop:\n"
<< "%outer_ct = phi i64 [ %ctnew, %loop ], [ 0, %start ]\n"
<< x.outer_statements()
<< "%ctnew = add i64 %outer_ct, 1\n"
<< "%j = icmp eq i64 %ctnew, %s\n"
<< "br i1 %j, label %end, label %loop, !llvm.loop !0\n}\n"
<< "!0 = distinct !{!0, !1, !2}\n"
<< "!1 = !{!\"llvm.loop.vectorize.enable\", i1 true}\n"
<< "!2 = !{!\"llvm.loop.vectorize.width\", i32 " << kArraySize << "}\n";
}
std::ostream &operator<<(std::ostream &os, const LoopFunction &x) {
if (x.has_inner_statements())
NestedLoopToString(os, x);
else
SingleLoopToString(os, x);
return os;
}
// ---------------------------------
std::string LoopFunctionToLLVMString(const LoopFunction &input) {
std::ostringstream os;
os << input;
return os.str();
}
std::string LoopProtoToLLVM(const uint8_t *data, size_t size) {
LoopFunction message;
if (!message.ParsePartialFromArray(data, size))
return "#error invalid proto\n";
return LoopFunctionToLLVMString(message);
}
} // namespace clang_fuzzer