pin-gcc-client/0003-Pin-gcc-client-Support-build-CFG-CallOp-AssignOp-Con.patch
benniaobufeijiushiji 02a666961a [sync] Sync patch from openeuler/pin-gcc-client
Sync patch from openeuler/pin-gcc-client 2022/12/08

(cherry picked from commit ca424952fd407c6158e330c8e21d67442aec4c16)
2022-12-09 09:52:56 +08:00

1290 lines
49 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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