Skip to content

Commit

Permalink
#1085: Allow the user to apply LLVM optimizations (-O3, -Oz) when lif…
Browse files Browse the repository at this point in the history
…ting to LLVM
  • Loading branch information
JonathanSalwan committed Feb 14, 2022
1 parent 4e42a22 commit 0753a0c
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .build_number
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1519
1520
8 changes: 4 additions & 4 deletions src/libtriton/api/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1373,17 +1373,17 @@ namespace triton {

/* Lifters engine API ================================================================================= */

std::ostream& API::liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname) {
std::ostream& API::liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname, bool optimize) {
this->checkLifting();
#ifdef TRITON_LLVM_INTERFACE
return this->lifting->liftToLLVM(stream, node, fname);
return this->lifting->liftToLLVM(stream, node, fname, optimize);
#endif
throw triton::exceptions::API("API::liftToLLVM(): Triton not built with LLVM");
}


std::ostream& API::liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname) {
return this->liftToLLVM(stream, expr->getAst(), fname);
std::ostream& API::liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname, bool optimize) {
return this->liftToLLVM(stream, expr->getAst(), fname, optimize);
}


Expand Down
12 changes: 11 additions & 1 deletion src/libtriton/ast/llvm/tritonToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ namespace triton {
}


std::shared_ptr<llvm::Module> TritonToLLVM::convert(const triton::ast::SharedAbstractNode& node, const char* fname) {
std::shared_ptr<llvm::Module> TritonToLLVM::convert(const triton::ast::SharedAbstractNode& node, const char* fname, bool optimize) {
std::unordered_map<triton::ast::SharedAbstractNode, llvm::Value*> results;

/* Create the LLVM function */
Expand All @@ -98,6 +98,16 @@ namespace triton {
/* Create the return instruction */
this->llvmIR.CreateRet(results.at(node));

/* Apply LLVM optimizations (-03 -Oz) if enabled */
if (optimize) {
llvm::legacy::PassManager pm;
llvm::PassManagerBuilder pmb;
pmb.OptLevel = 3;
pmb.SizeLevel = 2;
pmb.populateModulePassManager(pm);
pm.run(*this->llvmModule);
}

return this->llvmModule;
}

Expand Down
26 changes: 17 additions & 9 deletions src/libtriton/bindings/python/objects/pyTritonContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,11 @@ Returns true if the taint engine is enabled.
- <b>bool isThumb(void)</b><br>
Returns true if execution mode is Thumb (only valid for ARM32).
- <b>string liftToLLVM(\ref py_AstNode_page node, string fname="__triton")</b><br>
Lifts an AST node and all its references to LLVM IR. `fname` is the name of the LLVM function, by default it's `__triton`.
- <b>string liftToLLVM(\ref py_AstNode_page node, string fname="__triton", bool optimize=False)</b><br>
Lifts an AST node and all its references to LLVM IR. `fname` is the name of the LLVM function, by default it's `__triton`. If `optimize` is true, perform optimizations (-O3 -Oz).
- <b>string liftToLLVM(\ref py_SymbolicExpression_page expr)</b><br>
Lifts a symbolic expression and all its references to LLVM IR.
- <b>string liftToLLVM(\ref py_SymbolicExpression_page expr, string fname="__triton", bool optimize=False)</b><br>
Lifts a symbolic expression and all its references to LLVM IR. `fname` is the name of the LLVM function, by default it's `__triton`. If `optimize` is true, perform optimizations (-O3 -Oz).
- <b>string liftToPython(\ref py_SymbolicExpression_page expr)</b><br>
Lifts a symbolic expression and all its references to Python format.
Expand Down Expand Up @@ -2232,17 +2232,19 @@ namespace triton {


static PyObject* TritonContext_liftToLLVM(PyObject* self, PyObject* args, PyObject* kwargs) {
PyObject* node = nullptr;
PyObject* fname = nullptr;
PyObject* node = nullptr;
PyObject* fname = nullptr;
PyObject* optimize = nullptr;

static char* keywords[] = {
(char*)"node",
(char*)"fname",
(char*)"optimize",
nullptr
};

/* Extract keywords */
if (PyArg_ParseTupleAndKeywords(args, kwargs, "|OO", keywords, &node, &fname) == false) {
if (PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO", keywords, &node, &fname, &optimize) == false) {
return PyErr_Format(PyExc_TypeError, "TritonContext::liftToLLVM(): Invalid number of arguments");
}

Expand All @@ -2252,16 +2254,22 @@ namespace triton {
if (fname != nullptr && !PyStr_Check(fname))
return PyErr_Format(PyExc_TypeError, "TritonContext::liftToLLVM(): Expects a string as fname parameter.");

if (optimize != nullptr && !PyBool_Check(optimize))
return PyErr_Format(PyExc_TypeError, "TritonContext::liftToLLVM(): Expects a boolean as optimize parameter.");

if (fname == nullptr)
fname = PyStr_FromString("__triton");

if (optimize == nullptr)
optimize = PyLong_FromUint32(false);

try {
std::ostringstream stream;
if (PySymbolicExpression_Check(node)) {
PyTritonContext_AsTritonContext(self)->liftToLLVM(stream, PySymbolicExpression_AsSymbolicExpression(node), PyStr_AsString(fname));
PyTritonContext_AsTritonContext(self)->liftToLLVM(stream, PySymbolicExpression_AsSymbolicExpression(node), PyStr_AsString(fname), PyLong_AsBool(optimize));
}
else {
PyTritonContext_AsTritonContext(self)->liftToLLVM(stream, PyAstNode_AsAstNode(node), PyStr_AsString(fname));
PyTritonContext_AsTritonContext(self)->liftToLLVM(stream, PyAstNode_AsAstNode(node), PyStr_AsString(fname), PyLong_AsBool(optimize));
}
return xPyString_FromString(stream.str().c_str());
}
Expand Down
8 changes: 4 additions & 4 deletions src/libtriton/engines/lifters/liftingToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ namespace triton {
}


std::ostream& LiftingToLLVM::liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname) {
this->liftToLLVM(stream, expr->getAst(), fname);
std::ostream& LiftingToLLVM::liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname, bool optimize) {
this->liftToLLVM(stream, expr->getAst(), fname, optimize);
return stream;
}


std::ostream& LiftingToLLVM::liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname) {
std::ostream& LiftingToLLVM::liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname, bool optimize) {
/* The LLVM context */
llvm::LLVMContext context;

/* The lifter Triton -> LLVM */
triton::ast::TritonToLLVM lifter(context);

/* Lift AST to LLVM IR */
auto llvmModule = lifter.convert(node, fname);
auto llvmModule = lifter.convert(node, fname, optimize);

/* Print the LLVM module into the stream */
std::string dump;
Expand Down
4 changes: 2 additions & 2 deletions src/libtriton/includes/triton/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,10 @@ namespace triton {
/* Lifters engine API ================================================================================= */

//! [**lifting api**] - Lifts an AST and all its references to LLVM format. `fname` represents the name of the LLVM function.
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname="__triton");
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname="__triton", bool optimize=false);

//! [**lifting api**] - Lifts a symbolic expression and all its references to LLVM format. `fname` represents the name of the LLVM function.
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname="__triton");
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname="__triton", bool optimize=false);

//! [**lifting api**] - Lifts a symbolic expression and all its references to Python format.
TRITON_EXPORT std::ostream& liftToPython(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr);
Expand Down
4 changes: 2 additions & 2 deletions src/libtriton/includes/triton/liftingToLLVM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ namespace triton {
TRITON_EXPORT LiftingToLLVM();

//! Lifts a symbolic expression and all its references to LLVM format. `fname` represents the name of the LLVM function.
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname="__triton");
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::engines::symbolic::SharedSymbolicExpression& expr, const char* fname="__triton", bool optimize=false);

//! Lifts a abstract node and all its references to LLVM format. `fname` represents the name of the LLVM function.
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname="__triton");
TRITON_EXPORT std::ostream& liftToLLVM(std::ostream& stream, const triton::ast::SharedAbstractNode& node, const char* fname="__triton", bool optimize=false);
};

/*! @} End of lifters namespace */
Expand Down
4 changes: 3 additions & 1 deletion src/libtriton/includes/triton/tritonToLLVM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/Transforms/IPO/PassManagerBuilder.h>



Expand Down Expand Up @@ -65,7 +67,7 @@ namespace triton {
TRITON_EXPORT TritonToLLVM(llvm::LLVMContext& llvmContext);

//! Lifts a symbolic expression and all its references to LLVM format. `fname` represents the name of the LLVM function.
TRITON_EXPORT std::shared_ptr<llvm::Module> convert(const triton::ast::SharedAbstractNode& node, const char* fname="__triton");
TRITON_EXPORT std::shared_ptr<llvm::Module> convert(const triton::ast::SharedAbstractNode& node, const char* fname="__triton", bool optimize=false);
};

/*! @} End of ast namespace */
Expand Down
2 changes: 1 addition & 1 deletion src/testers/unittests/test_ast_representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,4 @@ def test_lifting(self):
]

for n in nodes:
self.assertNotEqual(len(self.ctx.liftToLLVM(n, fname="test")), 0)
self.assertNotEqual(len(self.ctx.liftToLLVM(n, fname="test", optimize=True)), 0)

0 comments on commit 0753a0c

Please sign in to comment.