pin-gcc-client/0003-Pin-gcc-client-Support-build-CFG-CallOp-AssignOp-Con.patch

1290 lines
49 KiB
Diff
Raw Normal View History

From 02138fc424b76a664ee66d55c2bafec47ba00f4e Mon Sep 17 00:00:00 2001
From: Mingchuan Wu <wumingchuan1992@foxmail.com>
Date: Thu, 8 Dec 2022 20:06:58 +0800
Subject: [PATCH 3/4] [Pin-gcc-client] Support build CFG, CallOp, AssignOp,
CondOp and PhiOp. Add CallOp, AssignOp, CondOp and PhiOp for PluginDialect.
Now we can support CFG.
---
include/Dialect/CMakeLists.txt | 3 +
include/Dialect/PluginDialect.td | 39 +++
include/Dialect/PluginOps.h | 4 +
include/Dialect/PluginOps.td | 129 ++++++++-
include/Dialect/PluginTypes.h | 4 +
include/PluginAPI/BasicPluginOpsAPI.h | 5 +
include/PluginAPI/PluginClientAPI.h | 7 +
include/PluginClient/PluginClient.h | 13 +-
include/Translate/GimpleToPluginOps.h | 64 ++--
lib/Dialect/PluginOps.cpp | 134 +++++++++
lib/PluginAPI/PluginClientAPI.cpp | 25 ++
lib/PluginClient/PluginClient.cpp | 185 +++++++++++-
lib/Translate/GimpleToPluginOps.cpp | 401 +++++++++++++++++++++++++-
13 files changed, 978 insertions(+), 35 deletions(-)
diff --git a/include/Dialect/CMakeLists.txt b/include/Dialect/CMakeLists.txt
index f0dfc58..f44e77c 100644
--- a/include/Dialect/CMakeLists.txt
+++ b/include/Dialect/CMakeLists.txt
@@ -1,5 +1,8 @@
# Add for the dialect operations. arg:(dialect dialect_namespace)
file(COPY /usr/bin/mlir-tblgen DESTINATION ./)
+set(LLVM_TARGET_DEFINITIONS PluginOps.td)
+mlir_tablegen(PluginOpsEnums.h.inc -gen-enum-decls)
+mlir_tablegen(PluginOpsEnums.cpp.inc -gen-enum-defs)
add_mlir_dialect(PluginOps Plugin)
# Necessary to generate documentation. arg:(doc_filename command output_file output_directory)
diff --git a/include/Dialect/PluginDialect.td b/include/Dialect/PluginDialect.td
index 603f2fc..b6bf728 100644
--- a/include/Dialect/PluginDialect.td
+++ b/include/Dialect/PluginDialect.td
@@ -48,4 +48,43 @@ def Plugin_Dialect : Dialect {
class Plugin_Op<string mnemonic, list<OpTrait> traits = []> :
Op<Plugin_Dialect, mnemonic, traits>;
+//===----------------------------------------------------------------------===//
+// PluginDialect enum definitions
+//===----------------------------------------------------------------------===//
+
+def IComparisonLT : I32EnumAttrCase<"lt", 0>;
+def IComparisonLE : I32EnumAttrCase<"le", 1>;
+def IComparisonGT : I32EnumAttrCase<"gt", 2>;
+def IComparisonGE : I32EnumAttrCase<"ge", 3>;
+def IComparisonLTGT : I32EnumAttrCase<"ltgt", 4>;
+def IComparisonEQ : I32EnumAttrCase<"eq", 5>;
+def IComparisonNE : I32EnumAttrCase<"ne", 6>;
+def IComparisonUNDEF : I32EnumAttrCase<"UNDEF", 7>;
+def IComparisonAttr : I32EnumAttr<
+ "IComparisonCode", "plugin comparison code",
+ [IComparisonLT, IComparisonLE, IComparisonGT, IComparisonGE,
+ IComparisonLTGT, IComparisonEQ, IComparisonNE, IComparisonUNDEF]>{
+ let cppNamespace = "::mlir::Plugin";
+}
+
+def IDefineCodeMemRef : I32EnumAttrCase<"MemRef", 0>;
+def IDefineCodeIntCST : I32EnumAttrCase<"IntCST", 1>;
+def IDefineCodeSSA : I32EnumAttrCase<"SSA", 2>;
+def IDefineCodeUNDEF : I32EnumAttrCase<"UNDEF", 3>;
+def IDefineCodeAttr : I32EnumAttr<
+ "IDefineCode", "plugin define code",
+ [IDefineCodeMemRef, IDefineCodeIntCST, IDefineCodeUNDEF]>{
+ let cppNamespace = "::mlir::Plugin";
+}
+
+def IExprCodePlus : I32EnumAttrCase<"Plus", 0>;
+def IExprCodeMinus : I32EnumAttrCase<"Minus", 1>;
+def IExprCodeNop : I32EnumAttrCase<"Nop", 2>;
+def IExprCodeUNDEF : I32EnumAttrCase<"UNDEF", 3>;
+def IExprCodeAttr : I32EnumAttr<
+ "IExprCode", "plugin expr code",
+ [IExprCodePlus, IExprCodeMinus, IExprCodeNop, IExprCodeUNDEF]>{
+ let cppNamespace = "::mlir::Plugin";
+}
+
#endif // PLUGIN_DIALECT_TD
\ No newline at end of file
diff --git a/include/Dialect/PluginOps.h b/include/Dialect/PluginOps.h
index 825310a..25089fe 100644
--- a/include/Dialect/PluginOps.h
+++ b/include/Dialect/PluginOps.h
@@ -29,6 +29,10 @@
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
+#include "mlir/Interfaces/CallInterfaces.h"
+
+// Pull in all enum type definitions and utility function declarations.
+#include "Dialect/PluginOpsEnums.h.inc"
#define GET_OP_CLASSES
#include "Dialect/PluginOps.h.inc"
diff --git a/include/Dialect/PluginOps.td b/include/Dialect/PluginOps.td
index 8264555..6f4a399 100644
--- a/include/Dialect/PluginOps.td
+++ b/include/Dialect/PluginOps.td
@@ -22,6 +22,7 @@
include "PluginDialect.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
+include "mlir/Interfaces/CallInterfaces.td"
def FunctionOp : Plugin_Op<"function", [NoSideEffect]> {
let summary = "function with a region";
@@ -29,8 +30,8 @@ def FunctionOp : Plugin_Op<"function", [NoSideEffect]> {
TODO.
}];
- let arguments = (ins OptionalAttr<UI64Attr>:$id,
- OptionalAttr<StrAttr>:$funcName,
+ let arguments = (ins UI64Attr:$id,
+ StrAttr:$funcName,
OptionalAttr<BoolAttr>:$declaredInline);
let regions = (region AnyRegion:$bodyRegion);
@@ -74,5 +75,129 @@ def LoopOp : Plugin_Op<"loop", [NoSideEffect]> {
];
}
+def CallOp : Plugin_Op<"call", [
+ DeclareOpInterfaceMethods<CallOpInterface>]> {
+ let summary = "call operation";
+ let description = [{
+ CallOp represent calls to a user defined function that needs to
+ be specialized for the shape of its arguments.
+ The callee name is attached as a symbol reference via an attribute.
+ The arguments list must match the arguments expected by the callee.
+ }];
+ let arguments = (ins UI64Attr:$id,
+ FlatSymbolRefAttr:$callee,
+ Variadic<AnyType>:$inputs);
+ let results = (outs Optional<AnyType>:$result);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "StringRef":$callee,
+ "ArrayRef<Value>":$arguments)>
+ ];
+ let assemblyFormat = [{
+ $callee `(` $inputs `)` attr-dict `:` functional-type($inputs, results)
+ }];
+}
+
+def PhiOp : Plugin_Op<"phi", [NoSideEffect]> {
+ let summary = "phi op";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$id,
+ UI32Attr:$capacity,
+ UI32Attr:$nArgs,
+ Variadic<AnyType>:$operands);
+ let results = (outs AnyType:$result);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "uint32_t":$capacity,
+ "uint32_t":$nArgs, "ArrayRef<Value>":$operands,
+ "Type":$resultType)>
+ ];
+}
+
+def AssignOp : Plugin_Op<"assign", [NoSideEffect]> {
+ let summary = "assign op";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$id,
+ IExprCodeAttr:$exprCode,
+ Variadic<AnyType>:$operands);
+ let results = (outs AnyType:$result);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "IExprCode":$exprCode,
+ "ArrayRef<Value>":$operands, "Type":$resultType)>
+ ];
+ // Specify a parser and printer method.
+ // let parser = [{ return ::parseAssignOp(parser, result); }];
+ // let printer = [{ return ::print(p, *this); }];
+}
+
+def PlaceholderOp : Plugin_Op<"placeholder", [NoSideEffect]> {
+ let summary = "PlaceHolder.";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$id,
+ OptionalAttr<IDefineCodeAttr>:$defCode);
+ let results = (outs AnyType);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "IDefineCode":$defCode, "Type":$retType)>
+ ];
+}
+
+def BaseOp : Plugin_Op<"statement_base", [NoSideEffect]> {
+ let summary = "Base operation, just like placeholder for statement.";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$id, StrAttr:$opCode);
+ let results = (outs AnyType);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "StringRef":$opCode)>
+ ];
+}
+
+// Terminators
+// Opaque builder used for terminator operations that contain successors.
+
+class Plugin_TerminatorOp<string mnemonic, list<OpTrait> traits = []> :
+ Plugin_Op<mnemonic, !listconcat(traits, [Terminator])>;
+
+def FallThroughOp : Plugin_TerminatorOp<"fallthrough", [NoSideEffect]> {
+ let summary = "FallThroughOp";
+ let description = [{TODO}];
+ let successors = (successor AnySuccessor:$dest);
+ // for bb address
+ let arguments = (ins UI64Attr:$address, UI64Attr:$destaddr);
+ let results = (outs AnyType);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$address, "Block*":$dest, "uint64_t":$destaddr)>
+ ];
+}
+
+def CondOp : Plugin_TerminatorOp<"condition", [NoSideEffect]> {
+ let summary = "condition op";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$id, UI64Attr:$address,
+ IComparisonAttr:$condCode,
+ AnyType:$LHS, AnyType:$RHS,
+ UI64Attr:$tbaddr, UI64Attr:$fbaddr,
+ OptionalAttr<TypeAttr>:$trueLabel,
+ OptionalAttr<TypeAttr>:$falseLabel);
+ let successors = (successor AnySuccessor:$tb, AnySuccessor:$fb);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$id, "uint64_t":$address, "IComparisonCode":$condCode,
+ "Value":$lhs, "Value":$rhs, "Block*":$tb, "Block*":$fb,
+ "uint64_t":$tbaddr, "uint64_t":$fbaddr, "Value":$trueLabel,
+ "Value":$falseLabel)>
+ ];
+ let extraClassDeclaration = [{
+ Value GetLHS() { return getOperand(0); }
+ Value GetRHS() { return getOperand(1); }
+ }];
+}
+
+// todo: currently RetOp do not have a correct assemblyFormat
+def RetOp : Plugin_TerminatorOp<"ret", [NoSideEffect]> {
+ let summary = "RetOp";
+ let description = [{TODO}];
+ let arguments = (ins UI64Attr:$address); // for bb address
+ let results = (outs AnyType);
+ let builders = [
+ OpBuilderDAG<(ins "uint64_t":$address)>
+ ];
+}
#endif // PLUGIN_OPS_TD
\ No newline at end of file
diff --git a/include/Dialect/PluginTypes.h b/include/Dialect/PluginTypes.h
index 1b4883f..e0ef867 100644
--- a/include/Dialect/PluginTypes.h
+++ b/include/Dialect/PluginTypes.h
@@ -141,6 +141,10 @@ public:
}; // class PluginBooleanType
+//===----------------------------------------------------------------------===//
+// Printing and parsing. TODO
+//===----------------------------------------------------------------------===//
+
} // namespace PluginIR
#endif // MLIR_DIALECT_PLUGINIR_PLUGINTYPES_H_
\ No newline at end of file
diff --git a/include/PluginAPI/BasicPluginOpsAPI.h b/include/PluginAPI/BasicPluginOpsAPI.h
index 1037bf5..f5d7e91 100644
--- a/include/PluginAPI/BasicPluginOpsAPI.h
+++ b/include/PluginAPI/BasicPluginOpsAPI.h
@@ -55,6 +55,11 @@ public:
virtual vector<std::pair<uint64_t, uint64_t> > GetLoopExits(uint64_t) = 0;
virtual std::pair<uint64_t, uint64_t> GetLoopSingleExit(uint64_t) = 0;
virtual LoopOp GetBlockLoopFather(uint64_t) = 0;
+ virtual PhiOp GetPhiOp(uint64_t) = 0;
+ virtual CallOp GetCallOp(uint64_t) = 0;
+ virtual bool SetLhsInCallOp(uint64_t, uint64_t) = 0;
+ virtual uint64_t CreateCondOp(IComparisonCode, uint64_t, uint64_t) = 0;
+ virtual mlir::Value GetResultFromPhi(uint64_t) = 0;
}; // class BasicPluginOpsAPI
} // namespace PluginAPI
diff --git a/include/PluginAPI/PluginClientAPI.h b/include/PluginAPI/PluginClientAPI.h
index 42d56ee..b33fdcb 100644
--- a/include/PluginAPI/PluginClientAPI.h
+++ b/include/PluginAPI/PluginClientAPI.h
@@ -47,6 +47,13 @@ public:
vector<std::pair<uint64_t, uint64_t> > GetLoopExits(uint64_t) override;
std::pair<uint64_t, uint64_t> GetLoopSingleExit(uint64_t) override;
LoopOp GetBlockLoopFather(uint64_t) override;
+ PhiOp GetPhiOp(uint64_t) override;
+ CallOp GetCallOp(uint64_t) override;
+ /* Plugin API for CallOp. */
+ bool SetLhsInCallOp(uint64_t, uint64_t) override;
+ /* Plugin API for CondOp. */
+ uint64_t CreateCondOp(IComparisonCode, uint64_t, uint64_t) override;
+ mlir::Value GetResultFromPhi(uint64_t) override;
private:
PluginIR::GimpleToPluginOps gimpleConversion;
diff --git a/include/PluginClient/PluginClient.h b/include/PluginClient/PluginClient.h
index 3e48c44..b18ecc0 100644
--- a/include/PluginClient/PluginClient.h
+++ b/include/PluginClient/PluginClient.h
@@ -28,6 +28,7 @@
#include <vector>
#include <time.h>
#include <signal.h>
+#include <json/json.h>
#include "Dialect/PluginOps.h"
#include "Dialect/PluginTypes.h"
@@ -107,7 +108,6 @@ public:
/* 获取client对象实例,有且只有一个实例对象 */
static std::shared_ptr<PluginClient> GetInstance(void);
void OpJsonSerialize(vector<mlir::Plugin::FunctionOp>& data, string& out);
- void LocalDeclsJsonSerialize(vector<mlir::Plugin::LocalDeclOp>& decls, string& out);
void LoopOpsJsonSerialize(vector<mlir::Plugin::LoopOp>& loops, string& out);
void LoopOpJsonSerialize(mlir::Plugin::LoopOp& loop, string& out);
void BoolResultJsonSerialize(bool, string&);
@@ -116,6 +116,17 @@ public:
void EdgesJsonSerialize(vector<pair<uint64_t, uint64_t> >&, string&);
void EdgeJsonSerialize(pair<uint64_t, uint64_t>&, string&);
void NopJsonSerialize(string&);
+ void FunctionOpJsonSerialize(vector<mlir::Plugin::FunctionOp>& data, string& out);
+ void LocalDeclsJsonSerialize(vector<mlir::Plugin::LocalDeclOp>& decls, string& out);
+ Json::Value OperationJsonSerialize(mlir::Operation *, uint64_t&);
+ Json::Value CallOpJsonSerialize(mlir::Plugin::CallOp& data);
+ Json::Value CondOpJsonSerialize(mlir::Plugin::CondOp& data, uint64_t&);
+ Json::Value PhiOpJsonSerialize(mlir::Plugin::PhiOp& data);
+ Json::Value AssignOpJsonSerialize(mlir::Plugin::AssignOp& data);
+ Json::Value BaseOpJsonSerialize(mlir::Plugin::BaseOp data);
+ Json::Value FallThroughOpJsonSerialize(mlir::Plugin::FallThroughOp data, uint64_t&);
+ Json::Value RetOpJsonSerialize(mlir::Plugin::RetOp data, uint64_t&);
+ Json::Value ValueJsonSerialize(mlir::Value value);
/* 将Type类型数据序列化 */
void TypeJsonSerialize(PluginIR::PluginTypeBase& type, string& out);
/* 获取gcc插件数据并进行IR转换将转换后的数据序列化返回给server。param函数入参序列化后的数据 */
diff --git a/include/Translate/GimpleToPluginOps.h b/include/Translate/GimpleToPluginOps.h
index 3f4f96a..0fd2fd2 100644
--- a/include/Translate/GimpleToPluginOps.h
+++ b/include/Translate/GimpleToPluginOps.h
@@ -23,7 +23,7 @@
#ifndef GIMPLE_TO_PLUGINOPS_H
#define GIMPLE_TO_PLUGINOPS_H
-#include "Translate/ToPluginOpsInterface.h"
+#include "Dialect/PluginOps.h"
#include "Translate/TypeTranslation.h"
#include "mlir/IR/Attributes.h"
@@ -31,35 +31,59 @@
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/Block.h"
+#include "mlir/IR/Region.h"
namespace PluginIR {
using std::vector;
+using namespace mlir::Plugin;
-class GimpleToPluginOps : public ToPluginOpsInterface {
+namespace detail {
+ class BlockFromGimpleTranslatorImpl;
+ // class BlockToPluginIRTranslatorImpl;
+} // namespace detail
+
+class GimpleToPluginOps {
public:
- GimpleToPluginOps (mlir::MLIRContext &context) : builder(&context) , typeTranslator(context) {}
- GimpleToPluginOps () = default;
- ~GimpleToPluginOps () = default;
+ GimpleToPluginOps (mlir::MLIRContext &);
+ ~GimpleToPluginOps ();
/* ToPluginInterface */
- vector<mlir::Plugin::FunctionOp> GetAllFunction() override;
- vector<mlir::Plugin::LocalDeclOp> GetAllDecls(uint64_t) override;
- vector<mlir::Plugin::LoopOp> GetAllLoops(uint64_t) override;
- LoopOp GetLoop(uint64_t) override;
- bool IsBlockInside(uint64_t, uint64_t) override;
- vector<uint64_t> GetBlocksInLoop(uint64_t) override;
- uint64_t AllocateNewLoop(void) override;
- void DeleteLoop(uint64_t) override;
- void AddLoop (uint64_t, uint64_t, uint64_t) override;
- uint64_t GetHeader(uint64_t) override;
- uint64_t GetLatch(uint64_t) override;
- vector<std::pair<uint64_t, uint64_t> > GetLoopExits(uint64_t) override;
- std::pair<uint64_t, uint64_t> GetLoopSingleExit(uint64_t) override;
- LoopOp GetBlockLoopFather(uint64_t) override;
+ vector<mlir::Plugin::FunctionOp> GetAllFunction();
+ vector<mlir::Plugin::LocalDeclOp> GetAllDecls(uint64_t);
+ vector<mlir::Plugin::LoopOp> GetAllLoops(uint64_t);
+ LoopOp GetLoop(uint64_t);
+ bool IsBlockInside(uint64_t, uint64_t);
+ vector<uint64_t> GetBlocksInLoop(uint64_t);
+ uint64_t AllocateNewLoop(void);
+ void DeleteLoop(uint64_t);
+ void AddLoop (uint64_t, uint64_t, uint64_t);
+ uint64_t GetHeader(uint64_t);
+ uint64_t GetLatch(uint64_t);
+ vector<std::pair<uint64_t, uint64_t> > GetLoopExits(uint64_t);
+ std::pair<uint64_t, uint64_t> GetLoopSingleExit(uint64_t);
+ LoopOp GetBlockLoopFather(uint64_t);
+ CallOp BuildCallOp(uint64_t);
+ bool SetGimpleCallLHS(uint64_t, uint64_t);
+ uint64_t CreateGcond(IComparisonCode, uint64_t, uint64_t);
+ FunctionOp BuildFunctionOp(uint64_t);
+ Operation *BuildOperation(uint64_t);
+ CondOp BuildCondOp(uint64_t, uint64_t, Block*, Block*, uint64_t, uint64_t);
+ AssignOp BuildAssignOp(uint64_t);
+ PhiOp BuildPhiOp(uint64_t);
+ mlir::Value GetGphiResult(uint64_t);
+ mlir::Value TreeToValue(uint64_t);
+
private:
+ GimpleToPluginOps () = delete;
mlir::OpBuilder builder;
TypeFromPluginIRTranslator typeTranslator;
+
+ // process basic_block
+ std::unique_ptr<detail::BlockFromGimpleTranslatorImpl> bbTranslator;
+ bool ProcessBasicBlock(intptr_t, Region&);
+ bool ProcessGimpleStmt(intptr_t, Region&);
};
} // namespace PluginIR
-#endif // GIMPLE_TO_PLUGINOPS_H
\ No newline at end of file
+#endif // GIMPLE_TO_PLUGINOPS_H
diff --git a/lib/Dialect/PluginOps.cpp b/lib/Dialect/PluginOps.cpp
index adf7ca6..de5cd11 100644
--- a/lib/Dialect/PluginOps.cpp
+++ b/lib/Dialect/PluginOps.cpp
@@ -61,6 +61,140 @@ void LoopOp::build(mlir::OpBuilder &builder, mlir::OperationState &state,
builder.getI32IntegerAttr(numBlock));
}
+//===----------------------------------------------------------------------===//
+// PlaceholderOp
+
+void PlaceholderOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t id, IDefineCode defCode, Type retType) {
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addAttribute("defCode",
+ builder.getI32IntegerAttr(static_cast<int32_t>(defCode)));
+ if (retType) state.addTypes(retType);
+}
+
+//===----------------------------------------------------------------------===//
+// CallOp
+
+void CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &state,
+ uint64_t id, StringRef callee,
+ ArrayRef<mlir::Value> arguments) {
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addOperands(arguments);
+ state.addAttribute("callee", builder.getSymbolRefAttr(callee));
+}
+
+/// Return the callee of the generic call operation, this is required by the
+/// call interface.
+CallInterfaceCallable CallOp::getCallableForCallee() {
+ return (*this)->getAttrOfType<SymbolRefAttr>("callee");
+}
+
+/// Get the argument operands to the called function, this is required by the
+/// call interface.
+Operation::operand_range CallOp::getArgOperands() { return inputs(); }
+
+//===----------------------------------------------------------------------===//
+// CondOp
+
+void CondOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t id, uint64_t address, IComparisonCode condCode,
+ Value lhs, Value rhs, Block* tb, Block* fb, uint64_t tbaddr,
+ uint64_t fbaddr, Value trueLabel, Value falseLabel) {
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addAttribute("address", builder.getI64IntegerAttr(address));
+ state.addOperands({lhs, rhs});
+ state.addAttribute("tbaddr", builder.getI64IntegerAttr(tbaddr));
+ state.addAttribute("fbaddr", builder.getI64IntegerAttr(fbaddr));
+ state.addSuccessors(tb);
+ state.addSuccessors(fb);
+ state.addAttribute("condCode",
+ builder.getI32IntegerAttr(static_cast<int32_t>(condCode)));
+ if (trueLabel != nullptr) state.addOperands(trueLabel);
+ if (falseLabel != nullptr) state.addOperands(falseLabel);
+}
+
+//===----------------------------------------------------------------------===//
+// PhiOp
+
+void PhiOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t id, uint32_t capacity, uint32_t nArgs,
+ ArrayRef<Value> operands, Type resultType) {
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addAttribute("capacity", builder.getI32IntegerAttr(capacity));
+ state.addAttribute("nArgs", builder.getI32IntegerAttr(nArgs));
+ state.addOperands(operands);
+ if (resultType) state.addTypes(resultType);
+}
+
+//===----------------------------------------------------------------------===//
+// AssignOp
+
+void AssignOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t id, IExprCode exprCode,
+ ArrayRef<Value> operands, Type resultType)
+{
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addAttribute("exprCode",
+ builder.getI32IntegerAttr(static_cast<int32_t>(exprCode)));
+ state.addOperands(operands);
+ if (resultType) state.addTypes(resultType);
+}
+
+/// The 'OpAsmParser' class provides a collection of methods for parsing
+/// various punctuation, as well as attributes, operands, types, etc. Each of
+/// these methods returns a `ParseResult`. This class is a wrapper around
+/// `LogicalResult` that can be converted to a boolean `true` value on failure,
+/// or `false` on success. This allows for easily chaining together a set of
+/// parser rules. These rules are used to populate an `mlir::OperationState`
+/// similarly to the `build` methods described above.
+static mlir::ParseResult parseAssignOp(mlir::OpAsmParser &parser,
+ mlir::OperationState &result) {
+ mlir::DenseElementsAttr value;
+ if (parser.parseOptionalAttrDict(result.attributes) ||
+ parser.parseAttribute(value, "value", result.attributes))
+ return failure();
+
+ result.addTypes(value.getType());
+ return success();
+}
+
+/// The 'OpAsmPrinter' class is a stream that allows for formatting
+/// strings, attributes, operands, types, etc.
+static void print(mlir::OpAsmPrinter &printer, AssignOp op) {
+ printer << "assign ";
+ printer.printType(op.getType());
+// printer << op.value();
+}
+
+//===----------------------------------------------------------------------===//
+// BaseOp
+
+void BaseOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t id, StringRef opCode)
+{
+ state.addAttribute("id", builder.getI64IntegerAttr(id));
+ state.addAttribute("opCode", builder.getStringAttr(opCode));
+}
+
+//===----------------------------------------------------------------------===//
+// FallThroughOp
+
+void FallThroughOp::build(OpBuilder &builder, OperationState &state,
+ uint64_t address, Block* dest, uint64_t destaddr)
+{
+ state.addAttribute("address", builder.getI64IntegerAttr(address));
+ state.addAttribute("destaddr", builder.getI64IntegerAttr(destaddr));
+ state.addSuccessors(dest);
+}
+
+//===----------------------------------------------------------------------===//
+// RetOp
+
+void RetOp::build(OpBuilder &builder, OperationState &state, uint64_t address)
+{
+ state.addAttribute("address", builder.getI64IntegerAttr(address));
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/lib/PluginAPI/PluginClientAPI.cpp b/lib/PluginAPI/PluginClientAPI.cpp
index d268c1e..ece137f 100644
--- a/lib/PluginAPI/PluginClientAPI.cpp
+++ b/lib/PluginAPI/PluginClientAPI.cpp
@@ -86,5 +86,30 @@ LoopOp PluginClientAPI::GetBlockLoopFather(uint64_t blockId)
{
return gimpleConversion.GetBlockLoopFather(blockId);
}
+PhiOp PluginClientAPI::GetPhiOp(uint64_t id)
+{
+ return gimpleConversion.BuildPhiOp(id);
+}
+
+CallOp PluginClientAPI::GetCallOp(uint64_t id)
+{
+ return gimpleConversion.BuildCallOp(id);
+}
+
+bool PluginClientAPI::SetLhsInCallOp(uint64_t callId, uint64_t lhsId)
+{
+ return gimpleConversion.SetGimpleCallLHS(callId, lhsId);
+}
+
+uint64_t PluginClientAPI::CreateCondOp(IComparisonCode iCode,
+ uint64_t LHS, uint64_t RHS)
+{
+ return gimpleConversion.CreateGcond(iCode, LHS, RHS);
+}
+
+mlir::Value PluginClientAPI::GetResultFromPhi(uint64_t id)
+{
+ return gimpleConversion.GetGphiResult(id);
+}
} // namespace PluginAPI
\ No newline at end of file
diff --git a/lib/PluginClient/PluginClient.cpp b/lib/PluginClient/PluginClient.cpp
index c57d36c..e8a7d7d 100644
--- a/lib/PluginClient/PluginClient.cpp
+++ b/lib/PluginClient/PluginClient.cpp
@@ -31,7 +31,6 @@
#include <sys/socket.h>
#include <sys/file.h>
#include <unistd.h>
-#include <json/json.h>
namespace PinClient {
using namespace mlir::Plugin;
@@ -106,7 +105,7 @@ void PluginClient::TypeJsonSerialize (PluginIR::PluginTypeBase& type, string& ou
out = root.toStyledString();
}
-void PluginClient::OpJsonSerialize(vector<FunctionOp>& data, string& out)
+void PluginClient::FunctionOpJsonSerialize(vector<FunctionOp>& data, string& out)
{
Json::Value root;
Json::Value operationObj;
@@ -122,14 +121,77 @@ void PluginClient::OpJsonSerialize(vector<FunctionOp>& data, string& out)
item["attributes"]["declaredInline"] = "1";
else
item["attributes"]["declaredInline"] = "0";
- item["attributes"]["funcName"] = d.funcNameAttr().getValue().str();
- operation = "operation" + std::to_string(i++);
+ item["attributes"]["funcName"] = d.funcNameAttr().getValue().str().c_str();
+ auto &region = d.getRegion();
+ size_t bbIdx = 0;
+ for (auto &b : region) {
+ string blockStr = "block" + std::to_string(bbIdx++);
+ uint64_t bbAddress = 0;
+ size_t opIdx = 0;
+ for (auto &inst : b) {
+ if (auto phOp = llvm::dyn_cast<PlaceholderOp>(inst)) continue;
+ string opStr = "Operation" + std::to_string(opIdx++);
+ item["region"][blockStr]["ops"][opStr] = OperationJsonSerialize(&inst, bbAddress);
+ }
+ assert(bbAddress != 0);
+ item["region"][blockStr]["address"] = std::to_string(bbAddress);
+ }
+ operation = "FunctionOp" + std::to_string(i++);
root[operation] = item;
item.clear();
}
out = root.toStyledString();
}
+Json::Value PluginClient::OperationJsonSerialize(mlir::Operation *operation,
+ uint64_t &bbId)
+{
+ Json::Value root;
+ if (AssignOp op = llvm::dyn_cast<AssignOp>(operation)) {
+ root = AssignOpJsonSerialize(op);
+ } else if (CallOp op = llvm::dyn_cast<CallOp>(operation)) {
+ root = CallOpJsonSerialize(op);
+ } else if (CondOp op = llvm::dyn_cast<CondOp>(operation)) {
+ root = CondOpJsonSerialize(op, bbId);
+ } else if (PhiOp op = llvm::dyn_cast<PhiOp>(operation)) {
+ root = PhiOpJsonSerialize(op);
+ } else if (FallThroughOp op = llvm::dyn_cast<FallThroughOp>(operation)) {
+ root = FallThroughOpJsonSerialize(op, bbId);
+ } else if (RetOp op = llvm::dyn_cast<RetOp>(operation)) {
+ root = RetOpJsonSerialize(op, bbId);
+ } else if (BaseOp op = llvm::dyn_cast<BaseOp>(operation)) {
+ root = BaseOpJsonSerialize(op);
+ }
+ root["OperationName"] = operation->getName().getStringRef().str();
+ return root;
+}
+
+Json::Value PluginClient::BaseOpJsonSerialize(BaseOp data)
+{
+ Json::Value root;
+ root["id"] = std::to_string(data.idAttr().getInt());
+ root["opCode"] = data.opCodeAttr().getValue().str().c_str();
+ return root;
+}
+
+Json::Value PluginClient::RetOpJsonSerialize(RetOp data, uint64_t &bbId)
+{
+ Json::Value root;
+ bbId = data.addressAttr().getInt();
+ root["address"] = std::to_string(bbId);
+ return root;
+}
+
+Json::Value PluginClient::FallThroughOpJsonSerialize(FallThroughOp data,
+ uint64_t &bbId)
+{
+ Json::Value root;
+ bbId = data.addressAttr().getInt();
+ root["address"] = std::to_string(bbId);
+ root["destaddr"] = std::to_string(data.destaddrAttr().getInt());
+ return root;
+}
+
void PluginClient::LocalDeclsJsonSerialize(vector<LocalDeclOp>& decls, string& out)
{
Json::Value root;
@@ -245,6 +307,78 @@ void PluginClient::NopJsonSerialize(string& out)
out = root.toStyledString();
}
+Json::Value PluginClient::CallOpJsonSerialize(CallOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["callee"] = data.callee().str();
+ size_t opIdx = 0;
+ for (mlir::Value v : data.getArgOperands()) {
+ PlaceholderOp phOp = v.getDefiningOp<PlaceholderOp>();
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input]["id"] = std::to_string(phOp.idAttr().getInt());
+ item["operands"][input]["defCode"] = std::to_string(phOp.defCodeAttr().getInt());
+ }
+ return item;
+}
+
+Json::Value PluginClient::CondOpJsonSerialize(CondOp& data, uint64_t &bbId)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["condCode"] = std::to_string(data.condCodeAttr().getInt());
+ item["lhs"] = ValueJsonSerialize(data.GetLHS());
+ item["rhs"] = ValueJsonSerialize(data.GetRHS());
+ bbId = data.addressAttr().getInt();
+ item["address"] = std::to_string(bbId);
+ item["tbaddr"] = std::to_string(data.tbaddrAttr().getInt());
+ item["fbaddr"] = std::to_string(data.fbaddrAttr().getInt());
+ return item;
+}
+
+Json::Value PluginClient::PhiOpJsonSerialize(PhiOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["capacity"] = std::to_string(data.capacityAttr().getInt());
+ item["nArgs"] = std::to_string(data.nArgsAttr().getInt());
+ size_t opIdx = 0;
+ for (mlir::Value v : data.operands()) {
+ PlaceholderOp phOp = v.getDefiningOp<PlaceholderOp>();
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input]["id"] = std::to_string(phOp.idAttr().getInt());
+ item["operands"][input]["defCode"] = std::to_string(phOp.defCodeAttr().getInt());
+ }
+ return item;
+}
+
+Json::Value PluginClient::AssignOpJsonSerialize(AssignOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["exprCode"] = std::to_string(data.exprCodeAttr().getInt());
+ size_t opIdx = 0;
+ for (mlir::Value v : data.operands()) {
+ PlaceholderOp phOp = v.getDefiningOp<PlaceholderOp>();
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input]["id"] = std::to_string(phOp.idAttr().getInt());
+ item["operands"][input]["defCode"] = std::to_string(phOp.defCodeAttr().getInt());
+ }
+ return item;
+}
+
+Json::Value PluginClient::ValueJsonSerialize(mlir::Value data)
+{
+ Json::Value root;
+ if (PlaceholderOp phOp = data.getDefiningOp<PlaceholderOp>()) {
+ root["id"] = std::to_string(phOp.idAttr().getInt());
+ root["defCode"] = std::to_string(phOp.defCodeAttr().getInt());
+ } else {
+ LOGE("ERROR: Can't Serialize!");
+ }
+ return root;
+}
+
void PluginClient::IRTransBegin(const string& funcName, const string& param)
{
string result;
@@ -260,7 +394,7 @@ void PluginClient::IRTransBegin(const string& funcName, const string& param)
context.getOrLoadDialect<PluginDialect>();
PluginAPI::PluginClientAPI clientAPI(context);
vector<FunctionOp> allFuncOps = clientAPI.GetAllFunc();
- OpJsonSerialize(allFuncOps, result);
+ FunctionOpJsonSerialize(allFuncOps, result);
this->ReceiveSendMsg("FuncOpResult", result);
} else if (funcName == "GetLocalDecls") {
/// Json格式
@@ -436,6 +570,47 @@ void PluginClient::IRTransBegin(const string& funcName, const string& param)
LoopOp loopFather = clientAPI.GetBlockLoopFather(blockId);
LoopOpJsonSerialize(loopFather, result);
this->ReceiveSendMsg("LoopOpResult", result);
+ } else if (funcName == "GetPhiOp") {
+ mlir::MLIRContext context;
+ context.getOrLoadDialect<PluginDialect>();
+ PluginAPI::PluginClientAPI clientAPI(context);
+ uint64_t id = atol(root[std::to_string(0)].asString().c_str());
+ PhiOp op = clientAPI.GetPhiOp(id);
+ Json::Value result = PhiOpJsonSerialize(op);
+ this->ReceiveSendMsg("OpsResult", result.toStyledString());
+ } else if (funcName == "GetCallOp") {
+ mlir::MLIRContext context;
+ context.getOrLoadDialect<PluginDialect>();
+ PluginAPI::PluginClientAPI clientAPI(context);
+ uint64_t id = atol(root[std::to_string(0)].asString().c_str());
+ CallOp op = clientAPI.GetCallOp(id);
+ Json::Value result = CallOpJsonSerialize(op);
+ this->ReceiveSendMsg("OpsResult", result.toStyledString());
+ } else if (funcName == "SetLhsInCallOp") {
+ mlir::MLIRContext context;
+ context.getOrLoadDialect<PluginDialect>();
+ PluginAPI::PluginClientAPI clientAPI(context);
+ uint64_t callId = atol(root["callId"].asString().c_str());
+ uint64_t lhsId = atol(root["lhsId"].asString().c_str());
+ bool ret = clientAPI.SetLhsInCallOp(callId, lhsId);
+ this->ReceiveSendMsg("BoolResult", std::to_string(ret));
+ } else if (funcName == "CreateCondOp") {
+ mlir::MLIRContext context;
+ context.getOrLoadDialect<PluginDialect>();
+ PluginAPI::PluginClientAPI clientAPI(context);
+ int condCode = atol(root["condCode"].asString().c_str());
+ uint64_t lhsId = atol(root["lhsId"].asString().c_str());
+ uint64_t rhsId = atol(root["rhsId"].asString().c_str());
+ uint64_t ret = clientAPI.CreateCondOp(IComparisonCode(condCode),
+ lhsId, rhsId);
+ this->ReceiveSendMsg("IdResult", std::to_string(ret));
+ } else if (funcName == "GetResultFromPhi") {
+ mlir::MLIRContext context;
+ context.getOrLoadDialect<PluginDialect>();
+ PluginAPI::PluginClientAPI clientAPI(context);
+ uint64_t id = atol(root["id"].asString().c_str());
+ mlir::Value ret = clientAPI.GetResultFromPhi(id);
+ this->ReceiveSendMsg("ValueResult", ValueJsonSerialize(ret).toStyledString());
} else {
LOGW("function: %s not found!\n", funcName.c_str());
}
diff --git a/lib/Translate/GimpleToPluginOps.cpp b/lib/Translate/GimpleToPluginOps.cpp
index 273a214..1f9988b 100644
--- a/lib/Translate/GimpleToPluginOps.cpp
+++ b/lib/Translate/GimpleToPluginOps.cpp
@@ -20,6 +20,8 @@
#include "Dialect/PluginTypes.h"
#include <cstdio>
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
#include "gcc-plugin.h"
#include "plugin-version.h"
@@ -46,6 +48,121 @@
namespace PluginIR {
using namespace mlir::Plugin;
+using namespace mlir;
+
+namespace detail {
+class BlockFromGimpleTranslatorImpl {
+public:
+ std::map<basic_block, Block*> blockMaps;
+ /* Constructs a class creating types in the given MLIR context. */
+ BlockFromGimpleTranslatorImpl(mlir::MLIRContext &context) : context(context) {}
+
+private:
+ /* The context in which MLIR types are created. */
+ mlir::MLIRContext &context;
+};
+
+} // namespace detail
+
+GimpleToPluginOps::GimpleToPluginOps (mlir::MLIRContext &context) :
+ builder(&context), typeTranslator(context), bbTranslator(new detail::BlockFromGimpleTranslatorImpl(context))
+{}
+
+GimpleToPluginOps::~GimpleToPluginOps ()
+{}
+
+static IComparisonCode TranslateCmpCode(enum tree_code ccode)
+{
+ switch (ccode) {
+ case LT_EXPR:
+ return IComparisonCode::lt;
+ case LE_EXPR:
+ return IComparisonCode::le;
+ case GT_EXPR:
+ return IComparisonCode::gt;
+ case GE_EXPR:
+ return IComparisonCode::ge;
+ case LTGT_EXPR:
+ return IComparisonCode::ltgt;
+ case EQ_EXPR:
+ return IComparisonCode::eq;
+ case NE_EXPR:
+ return IComparisonCode::ne;
+ default:
+ printf("tcc_comparison: %d not suppoted!\n", ccode);
+ break;
+ }
+ return IComparisonCode::UNDEF;
+}
+
+static enum tree_code TranslateCmpCodeToTreeCode(IComparisonCode iCode)
+{
+ switch (iCode) {
+ case IComparisonCode::lt:
+ return LT_EXPR;
+ case IComparisonCode::le:
+ return LE_EXPR;
+ case IComparisonCode::gt:
+ return GT_EXPR;
+ case IComparisonCode::ge:
+ return GE_EXPR;
+ case IComparisonCode::ltgt:
+ return LTGT_EXPR;
+ case IComparisonCode::eq:
+ return EQ_EXPR;
+ case IComparisonCode::ne:
+ return NE_EXPR;
+ default:
+ printf("tcc_comparison not suppoted!\n");
+ break;
+ }
+ return LT_EXPR;
+}
+
+static IExprCode TranslateExprCode(enum tree_code ccode)
+{
+ switch (ccode) {
+ case PLUS_EXPR:
+ return IExprCode::Plus;
+ case MINUS_EXPR:
+ return IExprCode::Minus;
+ case NOP_EXPR:
+ return IExprCode::Nop;
+ default:
+ // printf("tcc_binary: %d not suppoted!\n", ccode);
+ break;
+ }
+ return IExprCode::UNDEF;
+}
+
+static StringRef GimpleCodeToOperationName(enum gimple_code tcode)
+{
+ StringRef ret;
+ switch (tcode) {
+ case GIMPLE_PHI: {
+ ret = PhiOp::getOperationName();
+ break;
+ }
+ case GIMPLE_ASSIGN: {
+ ret = AssignOp::getOperationName();
+ break;
+ }
+ case GIMPLE_CALL: {
+ ret = CallOp::getOperationName();
+ break;
+ }
+ case GIMPLE_COND: {
+ ret = CondOp::getOperationName();
+ break;
+ }
+ default: {
+ ret = BaseOp::getOperationName();
+ break;
+ }
+ }
+ return ret;
+}
+
vector<FunctionOp> GimpleToPluginOps::GetAllFunction()
{
cgraph_node *node = NULL;
@@ -56,14 +173,9 @@ vector<FunctionOp> GimpleToPluginOps::GetAllFunction()
if (fn == NULL)
continue;
int64_t id = reinterpret_cast<int64_t>(reinterpret_cast<void*>(fn));
- FunctionOp irFunc;
- mlir::StringRef funcName(function_name(fn));
- bool declaredInline = false;
- if (DECL_DECLARED_INLINE_P(fn->decl))
- declaredInline = true;
- auto location = builder.getUnknownLoc();
- irFunc = builder.create<FunctionOp>(location, id, funcName, declaredInline);
+ FunctionOp irFunc = BuildFunctionOp(id);
functions.push_back(irFunc);
+ builder.setInsertionPointAfter(irFunc.getOperation());
}
return functions;
}
@@ -229,4 +341,279 @@ LoopOp GimpleToPluginOps::GetBlockLoopFather(uint64_t blockID)
return pluginLoop;
}
+FunctionOp GimpleToPluginOps::BuildFunctionOp(uint64_t functionId)
+{
+ function *fn = reinterpret_cast<function*>(functionId);
+ mlir::StringRef funcName(function_name(fn));
+ bool declaredInline = false;
+ if (DECL_DECLARED_INLINE_P(fn->decl))
+ declaredInline = true;
+ auto location = builder.getUnknownLoc();
+ FunctionOp retOp = builder.create<FunctionOp>(location, functionId,
+ funcName, declaredInline);
+ auto& fr = retOp.bodyRegion();
+ if (!ProcessBasicBlock((intptr_t)ENTRY_BLOCK_PTR_FOR_FN(fn), fr)) {
+ // handle error
+ return retOp;
+ }
+ return retOp;
+}
+
+Operation *GimpleToPluginOps::BuildOperation(uint64_t id)
+{
+ gimple *stmt = reinterpret_cast<gimple*>(id);
+ Operation *ret = nullptr;
+ switch (gimple_code(stmt)) {
+ case GIMPLE_PHI: {
+ PhiOp phiOp = BuildPhiOp(id);
+ ret = phiOp.getOperation();
+ break;
+ }
+ case GIMPLE_ASSIGN: {
+ AssignOp assignOp = BuildAssignOp(id);
+ ret = assignOp.getOperation();
+ break;
+ }
+ case GIMPLE_CALL: {
+ CallOp callOp = BuildCallOp(id);
+ ret = callOp.getOperation();
+ break;
+ }
+ case GIMPLE_COND: {
+ assert(EDGE_COUNT (stmt->bb->succs) == 2);
+ Block* trueBlock = bbTranslator->blockMaps[EDGE_SUCC(stmt->bb, 0)->dest];
+ Block* falseBlock = bbTranslator->blockMaps[EDGE_SUCC(stmt->bb, 1)->dest];
+ CondOp condOp = BuildCondOp(id, (uint64_t)stmt->bb,
+ trueBlock, falseBlock,
+ (uint64_t)EDGE_SUCC(stmt->bb, 0)->dest,
+ (uint64_t)EDGE_SUCC(stmt->bb, 1)->dest);
+ ret = condOp.getOperation();
+ break;
+ }
+ default: {
+ BaseOp baseOp = builder.create<BaseOp>(
+ builder.getUnknownLoc(), id, BaseOp::getOperationName());
+ ret = baseOp.getOperation();
+ break;
+ }
+ }
+ return ret;
+}
+
+PhiOp GimpleToPluginOps::BuildPhiOp(uint64_t gphiId)
+{
+ gphi *stmt = reinterpret_cast<gphi*>(gphiId);
+ llvm::SmallVector<Value, 4> ops;
+ ops.reserve(gimple_phi_num_args(stmt));
+ for (unsigned i = 0; i < gimple_phi_num_args(stmt); i++) {
+ tree *argTree = gimple_phi_arg_def_ptr(stmt, i);
+ uint64_t argId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(argTree));
+ Value arg = TreeToValue(argId);
+ ops.push_back(arg);
+ }
+ tree returnType = TREE_TYPE(gimple_phi_result(stmt));
+ PluginTypeBase rPluginType = typeTranslator.translateType((intptr_t)returnType);
+ uint32_t capacity = gimple_phi_capacity(stmt);
+ uint32_t nArgs = gimple_phi_num_args(stmt);
+ PhiOp ret = builder.create<PhiOp>(builder.getUnknownLoc(),
+ gphiId, capacity, nArgs, ops, rPluginType);
+ return ret;
+}
+
+CallOp GimpleToPluginOps::BuildCallOp(uint64_t gcallId)
+{
+ gcall *stmt = reinterpret_cast<gcall*>(gcallId);
+ tree fndecl = gimple_call_fndecl(stmt);
+ if (fndecl == NULL_TREE || DECL_NAME(fndecl) == NULL_TREE) {
+ return nullptr;
+ }
+ llvm::SmallVector<Value, 4> ops;
+ ops.reserve(gimple_call_num_args(stmt));
+ for (unsigned i = 0; i < gimple_call_num_args(stmt); i++) {
+ tree *callArg = gimple_call_arg_ptr(stmt, i);
+ uint64_t argId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(callArg));
+ Value arg = TreeToValue(argId);
+ ops.push_back(arg);
+ }
+ StringRef callName(IDENTIFIER_POINTER(DECL_NAME(fndecl)));
+ tree returnType = gimple_call_return_type(stmt);
+ PluginTypeBase rPluginType = typeTranslator.translateType((intptr_t)returnType);
+ CallOp ret = builder.create<CallOp>(builder.getUnknownLoc(), gcallId, callName, ops);
+ return ret;
+}
+
+bool GimpleToPluginOps::SetGimpleCallLHS(uint64_t callId, uint64_t lhsId)
+{
+ gcall *stmt = reinterpret_cast<gcall*>(callId);
+ tree *lhs = reinterpret_cast<tree*>(callId);
+ gimple_call_set_lhs (stmt, *lhs);
+ return true;
+}
+
+uint64_t GimpleToPluginOps::CreateGcond(IComparisonCode iCode,
+ uint64_t lhsId, uint64_t rhsId)
+{
+ tree *lhs = reinterpret_cast<tree*>(lhsId);
+ tree *rhs = reinterpret_cast<tree*>(rhsId);
+ gcond *ret = gimple_build_cond (TranslateCmpCodeToTreeCode(iCode),
+ *lhs, *rhs, NULL_TREE, NULL_TREE);
+ return reinterpret_cast<uint64_t>(reinterpret_cast<void*>(ret));
+}
+
+CondOp GimpleToPluginOps::BuildCondOp(uint64_t gcondId, uint64_t address,
+ Block* b1, Block* b2, uint64_t tbaddr,
+ uint64_t fbaddr)
+{
+ gcond *stmt = reinterpret_cast<gcond*>(gcondId);
+ tree *lhsPtr = gimple_cond_lhs_ptr(stmt);
+ uint64_t lhsId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(lhsPtr));
+ Value LHS = TreeToValue(lhsId);
+ tree *rhsPtr = gimple_cond_rhs_ptr(stmt);
+ uint64_t rhsId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(rhsPtr));
+ Value RHS = TreeToValue(rhsId);
+ Value trueLabel = nullptr;
+ Value falseLabel = nullptr;
+ IComparisonCode iCode = TranslateCmpCode(gimple_cond_code(stmt));
+ CondOp ret = builder.create<CondOp>(builder.getUnknownLoc(), gcondId,
+ address, iCode, LHS, RHS, b1, b2,
+ tbaddr, fbaddr, trueLabel, falseLabel);
+ return ret;
+}
+
+AssignOp GimpleToPluginOps::BuildAssignOp(uint64_t gassignId)
+{
+ gassign *stmt = reinterpret_cast<gassign*>(gassignId);
+ llvm::SmallVector<Value, 4> ops;
+ ops.reserve(gimple_num_ops(stmt));
+ uint64_t lhsId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(gimple_assign_lhs_ptr(stmt)));
+ ops.push_back(TreeToValue(lhsId));
+ uint64_t rhs1Id = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(gimple_assign_rhs1_ptr(stmt)));
+ ops.push_back(TreeToValue(rhs1Id));
+ if (gimple_assign_rhs2(stmt) != NULL_TREE) {
+ uint64_t rhs2Id = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(gimple_assign_rhs2_ptr(stmt)));
+ ops.push_back(TreeToValue(rhs2Id));
+ }
+ if (gimple_assign_rhs3(stmt) != NULL_TREE) {
+ uint64_t rhs3Id = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(gimple_assign_rhs3_ptr(stmt)));
+ ops.push_back(TreeToValue(rhs3Id));
+ }
+ IExprCode iCode = TranslateExprCode(gimple_assign_rhs_code(stmt));
+ mlir::Type returnType = nullptr;
+ AssignOp ret = builder.create<AssignOp>(
+ builder.getUnknownLoc(), gassignId, iCode, ops, returnType);
+ return ret;
+}
+
+Value GimpleToPluginOps::GetGphiResult(uint64_t id)
+{
+ gphi *stmt = reinterpret_cast<gphi*>(id);
+ tree ret = gimple_phi_result(stmt);
+ uint64_t retId = reinterpret_cast<uint64_t>(
+ reinterpret_cast<void*>(ret));
+ return TreeToValue(retId);
+}
+
+Value GimpleToPluginOps::TreeToValue(uint64_t treeId)
+{
+ tree *t = reinterpret_cast<tree*>(treeId);
+ tree treeType = TREE_TYPE(*t);
+ PluginTypeBase rPluginType = typeTranslator.translateType((intptr_t)treeType);
+ switch (TREE_CODE(*t)) {
+ case MEM_REF : {
+ break;
+ }
+ case INTEGER_CST : {
+ break;
+ }
+ case SSA_NAME : {
+ break;
+ }
+ default:
+ break;
+ }
+ mlir::Value opValue = builder.create<PlaceholderOp>(
+ builder.getUnknownLoc(), treeId,
+ IDefineCode::UNDEF, rPluginType);
+ return opValue;
+}
+
+bool GimpleToPluginOps::ProcessGimpleStmt(intptr_t bbPtr, Region& rg)
+{
+ bool putTerminator = false;
+ basic_block bb = reinterpret_cast<basic_block>(bbPtr);
+ for (gphi_iterator si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si)) {
+ gphi *p = si.phi ();
+ uint64_t id = reinterpret_cast<uint64_t>(reinterpret_cast<void*>(p));
+ BuildPhiOp(id); // FIXME: Check result.
+ }
+
+ for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) {
+ gimple *stmt = gsi_stmt (si);
+ uint64_t id = reinterpret_cast<uint64_t>(reinterpret_cast<void*>(stmt));
+ if (BuildOperation(id) == nullptr) {
+ printf("ERROR: BuildOperation!");
+ }
+ if(gimple_code(stmt) == GIMPLE_COND) {
+ putTerminator = true;
+ }
+ }
+
+ if (!putTerminator) {
+ // Process fallthrough, todo: process goto
+ if (EDGE_COUNT (bb->succs) == 1) {
+ builder.create<FallThroughOp>(builder.getUnknownLoc(), (uint64_t)bb,
+ bbTranslator->blockMaps[EDGE_SUCC(bb, 0)->dest],
+ (uint64_t)(EDGE_SUCC(bb, 0)->dest));
+ } else if (!EDGE_COUNT (bb->succs)) {
+ // Process other condition, such as return
+ builder.create<RetOp>(builder.getUnknownLoc(), (uint64_t)bb);
+ } else {
+ // Should unreachable;
+ assert(false);
+ }
+ }
+
+ return true;
+}
+
+bool GimpleToPluginOps::ProcessBasicBlock(intptr_t bbPtr, Region& rg)
+{
+ basic_block bb = reinterpret_cast<basic_block>(bbPtr);
+ // handled, skip process
+ if (bbTranslator->blockMaps.find(bb) != bbTranslator->blockMaps.end()) {
+ return true;
+ }
+ // fprintf(stderr,"processing bb[%d]\n", bb->index);
+
+ // create basic block
+ Block* block = builder.createBlock(&rg, rg.begin());
+ bbTranslator->blockMaps.insert({bb, block});
+ // todo process func return type
+ // todo isDeclaration
+
+ // process succ
+ for (unsigned int i = 0; i < EDGE_COUNT (bb->succs); i++) {
+ // fprintf(stderr,"-->[%d]\n", EDGE_SUCC(bb, i)->dest->index);
+ if (!ProcessBasicBlock((intptr_t)(EDGE_SUCC(bb, i)->dest), rg)) {
+ return false;
+ }
+ }
+ // process each stmt
+ builder.setInsertionPointToStart(block);
+ if (!ProcessGimpleStmt(bbPtr, rg)) {
+ return false;
+ }
+ // block->dump();
+ // fprintf(stderr, "[bb%d] succ: %d\n", bb->index,block->getNumSuccessors());
+ return true;
+}
+
} // namespace PluginIR
\ No newline at end of file
--
2.27.0.windows.1