Implemented proto to LLVM conversion and LLVM fuzz target
Differential Revision: https://reviews.llvm.org/D48106 llvm-svn: 335374
This commit is contained in:
parent
cd18bb523c
commit
e5f4a9ff76
|
@ -15,6 +15,7 @@ set(LLVM_OPTIONAL_SOURCES
|
||||||
DummyClangFuzzer.cpp
|
DummyClangFuzzer.cpp
|
||||||
ExampleClangProtoFuzzer.cpp
|
ExampleClangProtoFuzzer.cpp
|
||||||
ExampleClangLoopProtoFuzzer.cpp
|
ExampleClangLoopProtoFuzzer.cpp
|
||||||
|
ExampleClangLLVMProtoFuzzer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CLANG_ENABLE_PROTO_FUZZER)
|
if(CLANG_ENABLE_PROTO_FUZZER)
|
||||||
|
@ -49,6 +50,9 @@ if(CLANG_ENABLE_PROTO_FUZZER)
|
||||||
|
|
||||||
# Build the protobuf->C++ translation library and driver.
|
# Build the protobuf->C++ translation library and driver.
|
||||||
add_clang_subdirectory(proto-to-cxx)
|
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.
|
# Build the fuzzer initialization library.
|
||||||
add_clang_subdirectory(fuzzer-initialize)
|
add_clang_subdirectory(fuzzer-initialize)
|
||||||
|
@ -65,29 +69,45 @@ if(CLANG_ENABLE_PROTO_FUZZER)
|
||||||
ExampleClangLoopProtoFuzzer.cpp
|
ExampleClangLoopProtoFuzzer.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Build the llvm protobuf fuzzer
|
||||||
|
add_clang_executable(clang-llvm-proto-fuzzer
|
||||||
|
${DUMMY_MAIN}
|
||||||
|
ExampleClangLLVMProtoFuzzer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
set(COMMON_PROTO_FUZZ_LIBRARIES
|
set(COMMON_PROTO_FUZZ_LIBRARIES
|
||||||
${ProtobufMutator_LIBRARIES}
|
${ProtobufMutator_LIBRARIES}
|
||||||
${PROTOBUF_LIBRARIES}
|
${PROTOBUF_LIBRARIES}
|
||||||
${LLVM_LIB_FUZZING_ENGINE}
|
${LLVM_LIB_FUZZING_ENGINE}
|
||||||
clangFuzzerInitialize
|
clangFuzzerInitialize
|
||||||
clangHandleCXX
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(clang-proto-fuzzer
|
target_link_libraries(clang-proto-fuzzer
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${COMMON_PROTO_FUZZ_LIBRARIES}
|
${COMMON_PROTO_FUZZ_LIBRARIES}
|
||||||
|
clangHandleCXX
|
||||||
clangCXXProto
|
clangCXXProto
|
||||||
clangProtoToCXX
|
clangProtoToCXX
|
||||||
)
|
)
|
||||||
target_link_libraries(clang-loop-proto-fuzzer
|
target_link_libraries(clang-loop-proto-fuzzer
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${COMMON_PROTO_FUZZ_LIBRARIES}
|
${COMMON_PROTO_FUZZ_LIBRARIES}
|
||||||
|
clangHandleCXX
|
||||||
clangCXXLoopProto
|
clangCXXLoopProto
|
||||||
clangLoopProtoToCXX
|
clangLoopProtoToCXX
|
||||||
)
|
)
|
||||||
|
target_link_libraries(clang-llvm-proto-fuzzer
|
||||||
|
PRIVATE
|
||||||
|
${COMMON_PROTO_FUZZ_LIBRARIES}
|
||||||
|
clangHandleLLVM
|
||||||
|
clangCXXLoopProto
|
||||||
|
clangLoopProtoToLLVM
|
||||||
|
)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_clang_subdirectory(handle-cxx)
|
add_clang_subdirectory(handle-cxx)
|
||||||
|
add_clang_subdirectory(handle-llvm)
|
||||||
|
|
||||||
add_clang_executable(clang-fuzzer
|
add_clang_executable(clang-fuzzer
|
||||||
EXCLUDE_FROM_ALL
|
EXCLUDE_FROM_ALL
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
//===-- ExampleClangLLVMProtoFuzzer.cpp - Fuzz Clang ----------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// This file implements a function that compiles a single LLVM IR string as
|
||||||
|
/// input and uses libprotobuf-mutator to find new inputs. This function is
|
||||||
|
/// then linked into the Fuzzer library.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "cxx_loop_proto.pb.h"
|
||||||
|
#include "fuzzer-initialize/fuzzer_initialize.h"
|
||||||
|
#include "handle-llvm/handle_llvm.h"
|
||||||
|
#include "proto-to-llvm/loop_proto_to_llvm.h"
|
||||||
|
#include "src/libfuzzer/libfuzzer_macro.h"
|
||||||
|
|
||||||
|
using namespace clang_fuzzer;
|
||||||
|
|
||||||
|
DEFINE_BINARY_PROTO_FUZZER(const LoopFunction &input) {
|
||||||
|
auto S = LoopFunctionToLLVMString(input);
|
||||||
|
HandleLLVM(S, GetCLArgs());
|
||||||
|
}
|
|
@ -37,17 +37,15 @@ message BinaryOp {
|
||||||
PLUS = 0;
|
PLUS = 0;
|
||||||
MINUS = 1;
|
MINUS = 1;
|
||||||
MUL = 2;
|
MUL = 2;
|
||||||
DIV = 3;
|
XOR = 3;
|
||||||
MOD = 4;
|
AND = 4;
|
||||||
XOR = 5;
|
OR = 5;
|
||||||
AND = 6;
|
EQ = 6;
|
||||||
OR = 7;
|
NE = 7;
|
||||||
EQ = 8;
|
LE = 8;
|
||||||
NE = 9;
|
GE = 9;
|
||||||
LE = 10;
|
LT = 10;
|
||||||
GE = 11;
|
GT = 11;
|
||||||
LT = 12;
|
|
||||||
GT = 13;
|
|
||||||
};
|
};
|
||||||
required Op op = 1;
|
required Op op = 1;
|
||||||
required Rvalue left = 2;
|
required Rvalue left = 2;
|
||||||
|
@ -67,12 +65,6 @@ message AssignmentStatement {
|
||||||
required Rvalue rvalue = 2;
|
required Rvalue rvalue = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message IfElse {
|
|
||||||
required Rvalue cond = 1;
|
|
||||||
required StatementSeq if_body = 2;
|
|
||||||
required StatementSeq else_body = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Statement {
|
message Statement {
|
||||||
required AssignmentStatement assignment = 1;
|
required AssignmentStatement assignment = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "fuzzer_initialize.h"
|
#include "fuzzer_initialize.h"
|
||||||
|
|
||||||
|
#include "llvm/Support/TargetSelect.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace clang_fuzzer;
|
using namespace clang_fuzzer;
|
||||||
|
@ -31,6 +33,11 @@ const std::vector<const char *>& GetCLArgs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||||
|
llvm::InitializeAllTargets();
|
||||||
|
llvm::InitializeAllTargetMCs();
|
||||||
|
llvm::InitializeAllAsmPrinters();
|
||||||
|
llvm::InitializeAllAsmParsers();
|
||||||
|
|
||||||
CLArgs.push_back("-O2");
|
CLArgs.push_back("-O2");
|
||||||
for (int I = 1; I < *argc; I++) {
|
for (int I = 1; I < *argc; I++) {
|
||||||
if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) {
|
if (strcmp((*argv)[I], "-ignore_remaining_args=1") == 0) {
|
||||||
|
|
|
@ -18,17 +18,11 @@
|
||||||
#include "clang/Lex/PreprocessorOptions.h"
|
#include "clang/Lex/PreprocessorOptions.h"
|
||||||
#include "clang/Tooling/Tooling.h"
|
#include "clang/Tooling/Tooling.h"
|
||||||
#include "llvm/Option/Option.h"
|
#include "llvm/Option/Option.h"
|
||||||
#include "llvm/Support/TargetSelect.h"
|
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
void clang_fuzzer::HandleCXX(const std::string &S,
|
void clang_fuzzer::HandleCXX(const std::string &S,
|
||||||
const std::vector<const char *> &ExtraArgs) {
|
const std::vector<const char *> &ExtraArgs) {
|
||||||
llvm::InitializeAllTargets();
|
|
||||||
llvm::InitializeAllTargetMCs();
|
|
||||||
llvm::InitializeAllAsmPrinters();
|
|
||||||
llvm::InitializeAllAsmParsers();
|
|
||||||
|
|
||||||
llvm::opt::ArgStringList CC1Args;
|
llvm::opt::ArgStringList CC1Args;
|
||||||
CC1Args.push_back("-cc1");
|
CC1Args.push_back("-cc1");
|
||||||
for (auto &A : ExtraArgs)
|
for (auto &A : ExtraArgs)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} Support)
|
||||||
|
|
||||||
|
add_clang_library(clangHandleLLVM
|
||||||
|
handle_llvm.cpp
|
||||||
|
)
|
|
@ -0,0 +1,111 @@
|
||||||
|
//==-- handle_llvm.cpp - Helper function for Clang fuzzers -----------------==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Implements HandleLLVM for use by the Clang fuzzers. Mimics the llc tool to
|
||||||
|
// compile an LLVM IR file to X86_64 assembly.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "handle_llvm.h"
|
||||||
|
|
||||||
|
#include "llvm/ADT/Triple.h"
|
||||||
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||||
|
#include "llvm/CodeGen/CommandFlags.inc"
|
||||||
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
|
#include "llvm/IR/LegacyPassManager.h"
|
||||||
|
#include "llvm/IR/LLVMContext.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/Verifier.h"
|
||||||
|
#include "llvm/IRReader/IRReader.h"
|
||||||
|
#include "llvm/PassRegistry.h"
|
||||||
|
#include "llvm/Support/InitLLVM.h"
|
||||||
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/SourceMgr.h"
|
||||||
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
static void getOptLevel(const std::vector<const char *> &ExtraArgs,
|
||||||
|
CodeGenOpt::Level &OLvl) {
|
||||||
|
// Find the optimization level from the command line args
|
||||||
|
OLvl = CodeGenOpt::Default;
|
||||||
|
for (auto &A : ExtraArgs) {
|
||||||
|
if (A[0] == '-' && A[1] == 'O') {
|
||||||
|
switch(A[2]) {
|
||||||
|
case '0': OLvl = CodeGenOpt::None; break;
|
||||||
|
case '1': OLvl = CodeGenOpt::Less; break;
|
||||||
|
case '2': OLvl = CodeGenOpt::Default; break;
|
||||||
|
case '3': OLvl = CodeGenOpt::Aggressive; break;
|
||||||
|
default:
|
||||||
|
errs() << "error: opt level must be between 0 and 3.\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clang_fuzzer::HandleLLVM(const std::string &S,
|
||||||
|
const std::vector<const char *> &ExtraArgs) {
|
||||||
|
// Parse ExtraArgs to set the optimization level
|
||||||
|
CodeGenOpt::Level OLvl;
|
||||||
|
getOptLevel(ExtraArgs, OLvl);
|
||||||
|
|
||||||
|
// Set the Module to include the the IR code to be compiled
|
||||||
|
SMDiagnostic Err;
|
||||||
|
|
||||||
|
LLVMContext Context;
|
||||||
|
std::unique_ptr<Module> M = parseIR(MemoryBufferRef(S, "IR"), Err, Context);
|
||||||
|
if (!M) {
|
||||||
|
errs() << "error: could not parse IR!\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Target
|
||||||
|
std::string Error;
|
||||||
|
const Target *TheTarget = TargetRegistry::lookupTarget(
|
||||||
|
sys::getDefaultTargetTriple(), Error);
|
||||||
|
if (!TheTarget) {
|
||||||
|
errs() << Error;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
|
||||||
|
|
||||||
|
// Create a new Machine
|
||||||
|
std::string CPUStr = getCPUStr();
|
||||||
|
std::string FeaturesStr = getFeaturesStr();
|
||||||
|
std::unique_ptr<TargetMachine> Target(TheTarget->createTargetMachine(
|
||||||
|
sys::getDefaultTargetTriple(), CPUStr, FeaturesStr, Options,
|
||||||
|
getRelocModel(), getCodeModel(), OLvl));
|
||||||
|
|
||||||
|
// Create a new PassManager
|
||||||
|
legacy::PassManager PM;
|
||||||
|
TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
|
||||||
|
PM.add(new TargetLibraryInfoWrapperPass(TLII));
|
||||||
|
M->setDataLayout(Target->createDataLayout());
|
||||||
|
|
||||||
|
// Make sure the Module has no errors
|
||||||
|
if (verifyModule(*M, &errs())) {
|
||||||
|
errs() << "error: input module is broken!\n";
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setFunctionAttributes(CPUStr, FeaturesStr, *M);
|
||||||
|
|
||||||
|
raw_null_ostream OS;
|
||||||
|
Target->addPassesToEmitFile(PM, OS, nullptr, TargetMachine::CGFT_ObjectFile,
|
||||||
|
false);
|
||||||
|
PM.run(*M);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
//==-- handle_llvm.h - Helper function for Clang fuzzers -------------------==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Defines HandleLLVM for use by the Clang fuzzers.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
|
||||||
|
#define LLVM_CLANG_TOOLS_CLANG_FUZZER_HANDLE_LLVM_HANDLELLVM_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace clang_fuzzer {
|
||||||
|
void HandleLLVM(const std::string &S,
|
||||||
|
const std::vector<const char *> &ExtraArgs);
|
||||||
|
} // namespace clang_fuzzer
|
||||||
|
|
||||||
|
#endif
|
|
@ -67,12 +67,6 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) {
|
||||||
case BinaryOp::MUL:
|
case BinaryOp::MUL:
|
||||||
os << "*";
|
os << "*";
|
||||||
break;
|
break;
|
||||||
case BinaryOp::DIV:
|
|
||||||
os << "/";
|
|
||||||
break;
|
|
||||||
case BinaryOp::MOD:
|
|
||||||
os << "%";
|
|
||||||
break;
|
|
||||||
case BinaryOp::XOR:
|
case BinaryOp::XOR:
|
||||||
os << "^";
|
os << "^";
|
||||||
break;
|
break;
|
||||||
|
@ -106,11 +100,6 @@ std::ostream &operator<<(std::ostream &os, const BinaryOp &x) {
|
||||||
std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
|
std::ostream &operator<<(std::ostream &os, const AssignmentStatement &x) {
|
||||||
return os << x.varref() << "=" << x.rvalue() << ";\n";
|
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) {
|
std::ostream &operator<<(std::ostream &os, const Statement &x) {
|
||||||
return os << x.assignment();
|
return os << x.assignment();
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
// This is a copy and will be updated later to introduce changes
|
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -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)
|
|
@ -0,0 +1,156 @@
|
||||||
|
//==-- 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 <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
|
||||||
|
std::string get_var() {
|
||||||
|
static int ctr = 0;
|
||||||
|
return "%var" + std::to_string(ctr++);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 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 i32, i32* " << arr << ", i64 %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;
|
||||||
|
}
|
||||||
|
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\n"
|
||||||
|
<< "endloop:\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
|
|
@ -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 <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace clang_fuzzer {
|
||||||
|
class LoopFunction;
|
||||||
|
|
||||||
|
std::string LoopFunctionToLLVMString(const LoopFunction &input);
|
||||||
|
std::string LoopProtoToLLVM(const uint8_t *data, size_t size);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
//==-- loop_proto_to_llvm_main.cpp - Driver for protobuf-LLVM conversion----==//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// Implements a simple driver to print a LLVM program from a protobuf with loops
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<char>(in)),
|
||||||
|
std::istreambuf_iterator<char>());
|
||||||
|
std::cout << ";; " << argv[i] << std::endl;
|
||||||
|
std::cout << clang_fuzzer::LoopProtoToLLVM(
|
||||||
|
reinterpret_cast<const uint8_t *>(str.data()), str.size());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue