Index: tools/clang-fuzzer/CMakeLists.txt =================================================================== --- tools/clang-fuzzer/CMakeLists.txt +++ tools/clang-fuzzer/CMakeLists.txt @@ -49,6 +49,9 @@ # Build the protobuf->C++ translation library and driver. add_clang_subdirectory(proto-to-cxx) + + # Build the protobuf->LLVM IR translation library and driver. + add_clang_subdirectory(proto-to-llvm) # Build the fuzzer initialization library. add_clang_subdirectory(fuzzer-initialize) Index: tools/clang-fuzzer/cxx_loop_proto.proto =================================================================== --- tools/clang-fuzzer/cxx_loop_proto.proto +++ tools/clang-fuzzer/cxx_loop_proto.proto @@ -37,17 +37,15 @@ PLUS = 0; MINUS = 1; MUL = 2; - DIV = 3; - MOD = 4; - XOR = 5; - AND = 6; - OR = 7; - EQ = 8; - NE = 9; - LE = 10; - GE = 11; - LT = 12; - GT = 13; + XOR = 3; + AND = 4; + OR = 5; + EQ = 6; + NE = 7; + LE = 8; + GE = 9; + LT = 10; + GT = 11; }; required Op op = 1; required Rvalue left = 2; @@ -67,12 +65,6 @@ required Rvalue rvalue = 2; } -message IfElse { - required Rvalue cond = 1; - required StatementSeq if_body = 2; - required StatementSeq else_body = 3; -} - message Statement { required AssignmentStatement assignment = 1; } Index: tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp =================================================================== --- tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp +++ tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx.cpp @@ -67,12 +67,6 @@ case BinaryOp::MUL: os << "*"; break; - case BinaryOp::DIV: - os << "/"; - break; - case BinaryOp::MOD: - os << "%"; - break; case BinaryOp::XOR: os << "^"; break; @@ -106,11 +100,6 @@ std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { return os << x.varref() << "=" << x.rvalue() << ";\n"; } -std::ostream &operator<<(std::ostream &os, const IfElse &x) { - return os << "if (" << x.cond() << "){\n" - << x.if_body() << "} else { \n" - << x.else_body() << "}\n"; -} std::ostream &operator<<(std::ostream &os, const Statement &x) { return os << x.assignment(); } Index: tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp =================================================================== --- tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp +++ tools/clang-fuzzer/proto-to-cxx/loop_proto_to_cxx_main.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -// This is a copy and will be updated later to introduce changes #include #include Index: tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt =================================================================== --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD}) +set(CMAKE_CXX_FLAGS ${CXX_FLAGS_NOFUZZ}) + +# Needed by LLVM's CMake checks because this file defines multiple targets. +set(LLVM_OPTIONAL_SOURCES loop_proto_to_llvm.cpp loop_proto_to_llvm_main.cpp) + +add_clang_library(clangLoopProtoToLLVM loop_proto_to_llvm.cpp + DEPENDS clangCXXLoopProto + LINK_LIBS clangCXXLoopProto ${PROTOBUF_LIBRARIES} + ) + +add_clang_executable(clang-loop-proto-to-llvm loop_proto_to_llvm_main.cpp) + +target_link_libraries(clang-loop-proto-to-llvm PRIVATE clangLoopProtoToLLVM) Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h =================================================================== --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.h @@ -0,0 +1,23 @@ +//==-- loop_proto_to_llvm.h - Protobuf-C++ conversion ----------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines functions for converting between protobufs and LLVM IR. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +namespace clang_fuzzer { +class LoopFunction; + +std::string LoopFunctionToLLVMString(const LoopFunction &input); +std::string LoopProtoToLLVM(const uint8_t *data, size_t size); +} Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp =================================================================== --- /dev/null +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm.cpp @@ -0,0 +1,174 @@ +//==-- loop_proto_to_llvm.cpp - Protobuf-C++ conversion +//---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements functions for converting between protobufs and LLVM IR. +// +// +//===----------------------------------------------------------------------===// + +#include "loop_proto_to_llvm.h" +#include "cxx_loop_proto.pb.h" + +// The following is needed to convert protos in human-readable form +#include + +#include +#include + +namespace clang_fuzzer { + +// Forward decls. +std::ostream &operator<<(std::ostream &os, const BinaryOp &x); +std::ostream &operator<<(std::ostream &os, const StatementSeq &x); + +// Counter variables to generate new LLVM IR variable names +int ptr_ctr = 0; +int val_ctr = 0; + +// Proto to LLVM. +std::ostream &operator<<(std::ostream &os, const Const &x) { + return os << "%pval_" << val_ctr << " = alloca i32\n" + << "store i32 " << x.val() << ", i32* %pval_" << val_ctr << "\n" + << "%val_" << val_ctr << " = load i32, i32* %pval_" << val_ctr + << "\n"; +} +std::ostream &operator<<(std::ostream &os, const VarRef &x) { + ptr_ctr++; + switch (x.arr()) { + case VarRef::ARR_A: + return os << "%p2i_" << ptr_ctr << " = ptrtoint i32* %a to i64\n" + << "%m_" << ptr_ctr << " = mul i64 8, %ct\n" + << "%i_" << ptr_ctr << " = add i64 %p2i_" << ptr_ctr << ", %m_" + << ptr_ctr << "\n" + << "%i2p_" << ptr_ctr << " = inttoptr i64 %i_" << ptr_ctr + << " to i32*\n"; + case VarRef::ARR_B: + return os << "%p2i_" << ptr_ctr << " = ptrtoint i32* %b to i64\n" + << "%m_" << ptr_ctr << " = mul i64 8, %ct\n" + << "%i_" << ptr_ctr << " = add i64 %p2i_" << ptr_ctr << ", %m_" + << ptr_ctr << "\n" + << "%i2p_" << ptr_ctr << " = inttoptr i64 %i_" << ptr_ctr + << " to i32*\n"; + case VarRef::ARR_C: + return os << "%p2i_" << ptr_ctr << " = ptrtoint i32* %c to i64\n" + << "%m_" << ptr_ctr << " = mul i64 8, %ct\n" + << "%i_" << ptr_ctr << " = add i64 %p2i_" << ptr_ctr << ", %m_" + << ptr_ctr << "\n" + << "%i2p_" << ptr_ctr << " = inttoptr i64 %i_" << ptr_ctr + << " to i32*\n"; + } +} +std::ostream &operator<<(std::ostream &os, const Rvalue &x) { + val_ctr++; + if (x.has_cons()) + return os << x.cons(); + if (x.has_binop()) + return os << x.binop(); + if (x.has_varref()) + return os << x.varref() << "%val_" << val_ctr << " = load i32, i32* %i2p_" + << ptr_ctr << "\n"; + return os << "%pval_" << val_ctr << " = alloca i32\n" + << "store i32 1, i32* %pval_" << val_ctr << "\n" + << "%val_" << val_ctr << " = load i32, i32* %pval_" << val_ctr + << "\n"; +} +std::ostream &operator<<(std::ostream &os, const BinaryOp &x) { + os << x.left(); + int v1 = val_ctr; + os << x.right(); + int v2 = val_ctr; + val_ctr++; + os << "%val_" << val_ctr << " = "; + switch (x.op()) { + case BinaryOp::PLUS: + os << "add"; + break; + case BinaryOp::MINUS: + os << "sub"; + break; + case BinaryOp::MUL: + os << "mul"; + break; + case BinaryOp::XOR: + os << "xor"; + break; + case BinaryOp::AND: + os << "and"; + break; + case BinaryOp::OR: + os << "or"; + break; + // Support for Boolean operators will be added later + case BinaryOp::EQ: + os << "add"; + break; + case BinaryOp::NE: + os << "add"; + break; + case BinaryOp::LE: + os << "add"; + break; + case BinaryOp::GE: + os << "add"; + break; + case BinaryOp::LT: + os << "add"; + break; + case BinaryOp::GT: + os << "add"; + break; + } + return os << " i32 %val_" << v1 << ", %val_" << v2 << "\n"; +} +std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) { + int p = ptr_ctr + 1; + return os << x.varref() << x.rvalue() << "store i32 %val_" << val_ctr + << ", i32* %i2p_" << p << "\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; +} +std::ostream &operator<<(std::ostream &os, const LoopFunction &x) { + return os << "define void @foo(i32* %a, i32*%b, i32* noalias %c, i64 %s) {\n" + << "%i = alloca i64\n" + << "store i64 0, i64* %i\n" + << "br label %loop\n\n" + << "loop:\n" + << "%ct = load i64, i64* %i\n" + << "%comp = icmp eq i64 %ct, %s\n" + << "br i1 %comp, label %endloop, label %body\n\n" + << "body:\n" + << x.statements() << "%z = add i64 1, %ct\n" + << "store i64 %z, i64* %i\n" + << "br label %loop\n" + << "\nendloop:\n" + << "ret void\n}\n"; +} + +// --------------------------------- + +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 Index: tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp =================================================================== --- tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp +++ tools/clang-fuzzer/proto-to-llvm/loop_proto_to_llvm_main.cpp @@ -1,4 +1,4 @@ -//==-- loop_proto_to_cxx_main.cpp - Driver for protobuf-C++ conversion -----==// +//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion----==// // // The LLVM Compiler Infrastructure // @@ -7,26 +7,25 @@ // //===----------------------------------------------------------------------===// // -// Implements a simple driver to print a C++ program from a protobuf with loops. +// Implements a simple driver to print a LLVM program from a protobuf with loops // //===----------------------------------------------------------------------===// -// This is a copy and will be updated later to introduce changes #include #include #include #include -#include "proto_to_cxx.h" +#include "loop_proto_to_llvm.h" int main(int argc, char **argv) { for (int i = 1; i < argc; i++) { std::fstream in(argv[i]); std::string str((std::istreambuf_iterator(in)), std::istreambuf_iterator()); - std::cout << "// " << argv[i] << std::endl; - std::cout << clang_fuzzer::LoopProtoToCxx( + std::cout << ";; " << argv[i] << std::endl; + std::cout << clang_fuzzer::LoopProtoToLLVM( reinterpret_cast(str.data()), str.size()); } }