From 02138fc424b76a664ee66d55c2bafec47ba00f4e Mon Sep 17 00:00:00 2001 From: Mingchuan Wu 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 traits = []> : Op; +//===----------------------------------------------------------------------===// +// 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:$id, - OptionalAttr:$funcName, + let arguments = (ins UI64Attr:$id, + StrAttr:$funcName, OptionalAttr:$declaredInline); let regions = (region AnyRegion:$bodyRegion); @@ -74,5 +75,129 @@ def LoopOp : Plugin_Op<"loop", [NoSideEffect]> { ]; } +def CallOp : Plugin_Op<"call", [ + DeclareOpInterfaceMethods]> { + 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:$inputs); + let results = (outs Optional:$result); + let builders = [ + OpBuilderDAG<(ins "uint64_t":$id, "StringRef":$callee, + "ArrayRef":$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:$operands); + let results = (outs AnyType:$result); + let builders = [ + OpBuilderDAG<(ins "uint64_t":$id, "uint32_t":$capacity, + "uint32_t":$nArgs, "ArrayRef":$operands, + "Type":$resultType)> + ]; +} + +def AssignOp : Plugin_Op<"assign", [NoSideEffect]> { + let summary = "assign op"; + let description = [{TODO}]; + let arguments = (ins UI64Attr:$id, + IExprCodeAttr:$exprCode, + Variadic:$operands); + let results = (outs AnyType:$result); + let builders = [ + OpBuilderDAG<(ins "uint64_t":$id, "IExprCode":$exprCode, + "ArrayRef":$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:$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 traits = []> : + Plugin_Op; + +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:$trueLabel, + OptionalAttr:$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 > GetLoopExits(uint64_t) = 0; virtual std::pair 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 > GetLoopExits(uint64_t) override; std::pair 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 #include #include +#include #include "Dialect/PluginOps.h" #include "Dialect/PluginTypes.h" @@ -107,7 +108,6 @@ public: /* 获取client对象实例,有且只有一个实例对象 */ static std::shared_ptr GetInstance(void); void OpJsonSerialize(vector& data, string& out); - void LocalDeclsJsonSerialize(vector& decls, string& out); void LoopOpsJsonSerialize(vector& loops, string& out); void LoopOpJsonSerialize(mlir::Plugin::LoopOp& loop, string& out); void BoolResultJsonSerialize(bool, string&); @@ -116,6 +116,17 @@ public: void EdgesJsonSerialize(vector >&, string&); void EdgeJsonSerialize(pair&, string&); void NopJsonSerialize(string&); + void FunctionOpJsonSerialize(vector& data, string& out); + void LocalDeclsJsonSerialize(vector& 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 GetAllFunction() override; - vector GetAllDecls(uint64_t) override; - vector GetAllLoops(uint64_t) override; - LoopOp GetLoop(uint64_t) override; - bool IsBlockInside(uint64_t, uint64_t) override; - vector 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 > GetLoopExits(uint64_t) override; - std::pair GetLoopSingleExit(uint64_t) override; - LoopOp GetBlockLoopFather(uint64_t) override; + vector GetAllFunction(); + vector GetAllDecls(uint64_t); + vector GetAllLoops(uint64_t); + LoopOp GetLoop(uint64_t); + bool IsBlockInside(uint64_t, uint64_t); + vector 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 > GetLoopExits(uint64_t); + std::pair 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 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(defCode))); + if (retType) state.addTypes(retType); +} + +//===----------------------------------------------------------------------===// +// CallOp + +void CallOp::build(mlir::OpBuilder &builder, mlir::OperationState &state, + uint64_t id, StringRef callee, + ArrayRef 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("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(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 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 operands, Type resultType) +{ + state.addAttribute("id", builder.getI64IntegerAttr(id)); + state.addAttribute("exprCode", + builder.getI32IntegerAttr(static_cast(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 #include #include -#include 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& data, string& out) +void PluginClient::FunctionOpJsonSerialize(vector& data, string& out) { Json::Value root; Json::Value operationObj; @@ -122,14 +121,77 @@ void PluginClient::OpJsonSerialize(vector& 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(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(operation)) { + root = AssignOpJsonSerialize(op); + } else if (CallOp op = llvm::dyn_cast(operation)) { + root = CallOpJsonSerialize(op); + } else if (CondOp op = llvm::dyn_cast(operation)) { + root = CondOpJsonSerialize(op, bbId); + } else if (PhiOp op = llvm::dyn_cast(operation)) { + root = PhiOpJsonSerialize(op); + } else if (FallThroughOp op = llvm::dyn_cast(operation)) { + root = FallThroughOpJsonSerialize(op, bbId); + } else if (RetOp op = llvm::dyn_cast(operation)) { + root = RetOpJsonSerialize(op, bbId); + } else if (BaseOp op = llvm::dyn_cast(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& 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(); + 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(); + 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(); + 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()) { + 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(); PluginAPI::PluginClientAPI clientAPI(context); vector 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(); + 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(); + 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(); + 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(); + 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(); + 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 +#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 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 GimpleToPluginOps::GetAllFunction() { cgraph_node *node = NULL; @@ -56,14 +173,9 @@ vector GimpleToPluginOps::GetAllFunction() if (fn == NULL) continue; int64_t id = reinterpret_cast(reinterpret_cast(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(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(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(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(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( + builder.getUnknownLoc(), id, BaseOp::getOperationName()); + ret = baseOp.getOperation(); + break; + } + } + return ret; +} + +PhiOp GimpleToPluginOps::BuildPhiOp(uint64_t gphiId) +{ + gphi *stmt = reinterpret_cast(gphiId); + llvm::SmallVector 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( + reinterpret_cast(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(builder.getUnknownLoc(), + gphiId, capacity, nArgs, ops, rPluginType); + return ret; +} + +CallOp GimpleToPluginOps::BuildCallOp(uint64_t gcallId) +{ + gcall *stmt = reinterpret_cast(gcallId); + tree fndecl = gimple_call_fndecl(stmt); + if (fndecl == NULL_TREE || DECL_NAME(fndecl) == NULL_TREE) { + return nullptr; + } + llvm::SmallVector 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( + reinterpret_cast(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(builder.getUnknownLoc(), gcallId, callName, ops); + return ret; +} + +bool GimpleToPluginOps::SetGimpleCallLHS(uint64_t callId, uint64_t lhsId) +{ + gcall *stmt = reinterpret_cast(callId); + tree *lhs = reinterpret_cast(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(lhsId); + tree *rhs = reinterpret_cast(rhsId); + gcond *ret = gimple_build_cond (TranslateCmpCodeToTreeCode(iCode), + *lhs, *rhs, NULL_TREE, NULL_TREE); + return reinterpret_cast(reinterpret_cast(ret)); +} + +CondOp GimpleToPluginOps::BuildCondOp(uint64_t gcondId, uint64_t address, + Block* b1, Block* b2, uint64_t tbaddr, + uint64_t fbaddr) +{ + gcond *stmt = reinterpret_cast(gcondId); + tree *lhsPtr = gimple_cond_lhs_ptr(stmt); + uint64_t lhsId = reinterpret_cast( + reinterpret_cast(lhsPtr)); + Value LHS = TreeToValue(lhsId); + tree *rhsPtr = gimple_cond_rhs_ptr(stmt); + uint64_t rhsId = reinterpret_cast( + reinterpret_cast(rhsPtr)); + Value RHS = TreeToValue(rhsId); + Value trueLabel = nullptr; + Value falseLabel = nullptr; + IComparisonCode iCode = TranslateCmpCode(gimple_cond_code(stmt)); + CondOp ret = builder.create(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(gassignId); + llvm::SmallVector ops; + ops.reserve(gimple_num_ops(stmt)); + uint64_t lhsId = reinterpret_cast( + reinterpret_cast(gimple_assign_lhs_ptr(stmt))); + ops.push_back(TreeToValue(lhsId)); + uint64_t rhs1Id = reinterpret_cast( + reinterpret_cast(gimple_assign_rhs1_ptr(stmt))); + ops.push_back(TreeToValue(rhs1Id)); + if (gimple_assign_rhs2(stmt) != NULL_TREE) { + uint64_t rhs2Id = reinterpret_cast( + reinterpret_cast(gimple_assign_rhs2_ptr(stmt))); + ops.push_back(TreeToValue(rhs2Id)); + } + if (gimple_assign_rhs3(stmt) != NULL_TREE) { + uint64_t rhs3Id = reinterpret_cast( + reinterpret_cast(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( + builder.getUnknownLoc(), gassignId, iCode, ops, returnType); + return ret; +} + +Value GimpleToPluginOps::GetGphiResult(uint64_t id) +{ + gphi *stmt = reinterpret_cast(id); + tree ret = gimple_phi_result(stmt); + uint64_t retId = reinterpret_cast( + reinterpret_cast(ret)); + return TreeToValue(retId); +} + +Value GimpleToPluginOps::TreeToValue(uint64_t treeId) +{ + tree *t = reinterpret_cast(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( + builder.getUnknownLoc(), treeId, + IDefineCode::UNDEF, rPluginType); + return opValue; +} + +bool GimpleToPluginOps::ProcessGimpleStmt(intptr_t bbPtr, Region& rg) +{ + bool putTerminator = false; + basic_block bb = reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(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(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(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