Sync patch from openeuler/pin-gcc-client 2022/12/08 (cherry picked from commit ca424952fd407c6158e330c8e21d67442aec4c16)
1290 lines
49 KiB
Diff
1290 lines
49 KiB
Diff
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 ®ion = 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
|
||
|