From 1e14f9e453c9504cff141ce9059c0eeb405e73ed Mon Sep 17 00:00:00 2001
From: huitailangzju <804544223@qq.com>
Date: Tue, 7 Feb 2023 19:18:42 +0800
Subject: [PATCH 3/9] [Refactoring] Code refactoring of Communication Subsystem
[2/3]. Add PluginGrpcPort, PluginInputCheck and PluginJson.
diff --git a/lib/PluginClient/PluginGrpcPort.cpp b/lib/PluginClient/PluginGrpcPort.cpp
new file mode 100755
index 0000000..c6b9a1f
--- /dev/null
+++ b/lib/PluginClient/PluginGrpcPort.cpp
@@ -0,0 +1,159 @@
+/* Copyright (c) 2022-2022 Huawei Technologies Co., Ltd.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ .
+
+ Author: Mingchuan Wu and Yancheng Li
+ Create: 2022-08-18
+ Description:
+ This file contains the implementation of the PluginGrpcPort class.
+ 主要完成功能:查找未使用的端口号,并将端口号写入到共享文件中,通过文件锁控制多进程间访问,并提供
+ DeletePortFromLockFile接口在退出时删除写入的端口号
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "PluginClient/PluginLog.h"
+#include "PluginClient/PluginGrpcPort.h"
+
+namespace PinClient {
+int PluginGrpcPort::OpenFile(const char *path)
+{
+ int portFileFd = -1;
+ if (access(path, F_OK) == -1) {
+ mode_t mask = umask(0);
+ mode_t mode = 0666; // 权限是rwrwrw,跨进程时,其他用户也要可以访问
+ portFileFd = open(path, O_CREAT | O_RDWR, mode);
+ umask(mask);
+ } else {
+ portFileFd = open(path, O_RDWR);
+ }
+
+ if (portFileFd == -1) {
+ LOGE("open file %s fail\n", path);
+ }
+ return portFileFd;
+}
+
+bool PluginGrpcPort::ReadPortsFromLockFile(int fd, string& grpcPorts)
+{
+ if (flock(fd, LOCK_EX) != 0) {
+ return false;
+ }
+
+ int fileLen = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+ char *buf = new char[fileLen + 1];
+ if (buf == NULL) {
+ return false;
+ }
+ if (read(fd, buf, fileLen) < 0) {
+ return false;
+ }
+ buf[fileLen] = '\0';
+ grpcPorts = buf;
+ delete[] buf;
+ return true;
+}
+
+bool PluginGrpcPort::FindUnusedPort()
+{
+ unsigned short basePort = GetBasePort();
+ int portFileFd = OpenFile(lockFilePath.c_str());
+ if (portFileFd == -1) {
+ return false;
+ }
+
+ string grpcPorts = "";
+ if (!ReadPortsFromLockFile(portFileFd, grpcPorts)) {
+ close(portFileFd);
+ return false;
+ }
+
+ // 不使用UINT16_MAX端口号,端口号为UINT16_MAX时作异常处理
+ while (++basePort < UINT16_MAX) {
+ int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ struct sockaddr_in serverAddr;
+ memset(&serverAddr, 0, sizeof(serverAddr));
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_addr.s_addr = inet_addr("0.0.0.0");
+ serverAddr.sin_port = htons(basePort);
+ int ret = connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
+ if (sock != -1) {
+ close(sock);
+ }
+ if ((ret == -1) && (errno == ECONNREFUSED)) {
+ string strPort = std::to_string(basePort) + "\n";
+ if (grpcPorts.find(strPort) == grpcPorts.npos) {
+ port = basePort;
+ LOGI("found port:%d\n", port);
+ lseek(portFileFd, 0, SEEK_END);
+ write(portFileFd, strPort.c_str(), strPort.size());
+ break;
+ }
+ }
+ }
+
+ if (basePort == UINT16_MAX) {
+ ftruncate(portFileFd, 0); // 清空锁文件,避免异常未删除释放的端口号,导致无端口使用
+ lseek(portFileFd, 0, SEEK_SET);
+ close(portFileFd); // 关闭文件fd会同时释放文件锁
+ return false;
+ }
+
+ close(portFileFd); // 关闭文件fd会同时释放文件锁
+ return true;
+}
+
+bool PluginGrpcPort::DeletePortFromLockFile()
+{
+ if (port == 0) {
+ return true;
+ }
+ int portFileFd = open(lockFilePath.c_str(), O_RDWR);
+ if (portFileFd == -1) {
+ LOGE("%s open file %s fail\n", __func__, lockFilePath.c_str());
+ return false;
+ }
+ LOGI("delete port:%d\n", port);
+
+ string grpcPorts = "";
+ if (!ReadPortsFromLockFile(portFileFd, grpcPorts)) {
+ close(portFileFd);
+ port = 0;
+ return false;
+ }
+
+ string portStr = std::to_string(port) + "\n";
+ string::size_type pos = grpcPorts.find(portStr);
+ if (pos == string::npos) {
+ close(portFileFd);
+ port = 0;
+ return true;
+ }
+ grpcPorts = grpcPorts.erase(pos, portStr.size());
+
+ ftruncate(portFileFd, 0);
+ lseek(portFileFd, 0, SEEK_SET);
+ write(portFileFd, grpcPorts.c_str(), grpcPorts.size());
+ close(portFileFd);
+ port = 0;
+ return true;
+}
+} // namespace PinClient
diff --git a/lib/PluginClient/PluginInputCheck.cpp b/lib/PluginClient/PluginInputCheck.cpp
new file mode 100755
index 0000000..12cfcdc
--- /dev/null
+++ b/lib/PluginClient/PluginInputCheck.cpp
@@ -0,0 +1,194 @@
+/* Copyright (c) 2022-2022 Huawei Technologies Co., Ltd.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ .
+
+ Author: Mingchuan Wu and Yancheng Li
+ Create: 2022-08-18
+ Description:
+ This file contains the implementation of the PluginInputCheck class.
+*/
+
+#include
+#include "PluginClient/PluginInputCheck.h"
+
+namespace PinClient {
+// 对server可执行文件进行检查,后续可以在此函数中扩展是否可执行,文件权限等检查
+int PluginInputCheck::CheckServerFile()
+{
+ int ret = access(serverPath.c_str(), F_OK);
+ return ret;
+}
+
+// 对sha256文件进行检查,后续可以在此函数中扩展文件权限、是否为空等检查
+int PluginInputCheck::CheckShaFile()
+{
+ int ret = access(shaPath.c_str(), F_OK);
+ return ret;
+}
+
+bool PluginInputCheck::ReadConfigfile(Json::Value& root)
+{
+ Json::Reader reader;
+ std::ifstream ifs(configFilePath.c_str());
+ if (!ifs.is_open()) {
+ LOGW("open %s fail! use default sha256file:%s\n", configFilePath.c_str(), shaPath.c_str());
+ return false;
+ }
+
+ if (!reader.parse(ifs, root)) {
+ printf("parse %s fail! check the file format!\n", configFilePath.c_str());
+ ifs.close();
+ return false;
+ }
+
+ ifs.close();
+ return true;
+}
+
+void PluginInputCheck::SetTimeout(int time)
+{
+ const int timeoutMin = 50;
+ const int timeoutMax = 5000;
+ if ((time >= timeoutMin) && (time <= timeoutMax)) { // 不在50~5000ms范围内,使用默认值
+ timeout = time;
+ LOGI("the timeout is:%d\n", timeout);
+ return;
+ }
+ LOGW("SetTimeout:%d,should be 50~5000,use default:%d\n", time, timeout);
+}
+
+int PluginInputCheck::GetInitInfo()
+{
+ Json::Value root;
+ if (!ReadConfigfile(root)) {
+ return -1;
+ }
+
+ if (serverPath == "") {
+ if (root[jsonkey[PATH]].isString()) {
+ serverPath = root[jsonkey[PATH]].asString();
+ } else {
+ LOGW("serverPath in config.json is not string!\n");
+ }
+ }
+ if (CheckServerFile() != 0) {
+ LOGE("serverPath:%s not exist!\n", serverPath.c_str());
+ serverPath = "";
+ return -1;
+ }
+
+ if (root[jsonkey[TIMEOUT]].isInt()) {
+ int timeoutJson = root[jsonkey[TIMEOUT]].asInt();
+ SetTimeout(timeoutJson);
+ }
+
+ if (root[jsonkey[SHA256]].isString()) {
+ shaPath = root[jsonkey[SHA256]].asString();
+ } else {
+ LOGW("sha256file int config.json is not string!\n");
+ }
+
+ if ((shaPath == "") || (CheckShaFile() != 0)) {
+ shaPath = GetServerDir() + shaFile; // sha256文件默认和server在同一目录
+ LOGW("sha256 file not found,use default:%s\n", shaPath.c_str());
+ }
+ return 0;
+}
+
+std::map g_keyMap {
+ {"server_path", KEY_SERVER_PATH},
+ {"log_level", KEY_LOG_LEVEL},
+};
+void PluginInputCheck::GetInputArgs(struct plugin_name_args *pluginInfo)
+{
+ Json::Value root;
+ map compileArgs;
+
+ for (int i = 0; i < pluginInfo->argc; i++) {
+ string key = pluginInfo->argv[i].key;
+ int keyTag = -1;
+ auto it = g_keyMap.find(key);
+ if (it != g_keyMap.end()) {
+ keyTag = it->second;
+ }
+ switch (keyTag) {
+ case KEY_SERVER_PATH:
+ serverPath = pluginInfo->argv[i].value;
+ if (serverPath != "") {
+ configFilePath = GetServerDir() + "/pin-gcc-client.json"; // 配置文件和server在同一目录
+ shaPath = GetServerDir() + shaFile; // sha256文件默认和server在同一目录
+ }
+ break;
+ case KEY_LOG_LEVEL:
+ logLevel = (LogPriority)atoi(pluginInfo->argv[i].value);
+ SetLogPriority(logLevel);
+ break;
+ default:
+ string value = pluginInfo->argv[i].value;
+ compileArgs[key] = value;
+ root[key] = value;
+ break;
+ }
+ }
+
+ args = root.toStyledString();
+ for (auto it = compileArgs.begin(); it != compileArgs.end(); it++) {
+ CheckSafeCompileFlag(it->first, it->second);
+ }
+}
+
+int PluginInputCheck::CheckSHA256()
+{
+ if (shaPath == "") {
+ LOGE("sha256file Path is NULL!\n");
+ return -1;
+ }
+ int index = shaPath.find_last_of("/");
+ string dir = shaPath.substr(0, index);
+ string filename = shaPath.substr(index+1, -1);
+
+ string cmd = "cd " + dir + " && " + "sha256sum -c " + filename + " --quiet";
+ int ret = system(cmd.c_str());
+ return ret;
+}
+
+void PluginInputCheck::CheckSafeCompileFlag(const string& argName, const string& param)
+{
+ for (auto& compileFlag : safeCompileFlags) {
+ if (param.find(compileFlag) != string::npos) {
+ LOGW("%s:%s have safe compile parameter:%s !!!\n", argName.c_str(), param.c_str(), compileFlag.c_str());
+ }
+ }
+}
+
+PluginInputCheck::PluginInputCheck()
+{
+ shaPath = "";
+ serverPath = "";
+ logLevel = PRIORITY_WARN;
+ timeout = 200; // 默认超时时间200ms
+ SetConfigPath("/usr/local/bin/pin-gcc-client.json");
+ safeCompileFlags.push_back("-z noexecstack");
+ safeCompileFlags.push_back("-fno-stack-protector");
+ safeCompileFlags.push_back("-fstack-protector-all");
+ safeCompileFlags.push_back("-D_FORTIFY_SOURCE");
+ safeCompileFlags.push_back("-fPic");
+ safeCompileFlags.push_back("-fPIE");
+ safeCompileFlags.push_back("-fstack-protector-strong");
+ safeCompileFlags.push_back("-fvisibility");
+ safeCompileFlags.push_back("-ftrapv");
+ safeCompileFlags.push_back("-fstack-check");
+}
+} // namespace PinClient
diff --git a/lib/PluginClient/PluginJson.cpp b/lib/PluginClient/PluginJson.cpp
new file mode 100755
index 0000000..22cd489
--- /dev/null
+++ b/lib/PluginClient/PluginJson.cpp
@@ -0,0 +1,458 @@
+/* Copyright (c) 2022-2022 Huawei Technologies Co., Ltd.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING3. If not see
+ .
+
+ Author: Mingchuan Wu and Yancheng Li
+ Create: 2022-08-18
+ Description:
+ This file contains the implementation of the PluginJson class.
+*/
+
+#include
+#include "PluginAPI/PluginClientAPI.h"
+#include "PluginClient/PluginLog.h"
+#include "PluginClient/PluginJson.h"
+
+namespace PinClient {
+using std::map;
+using namespace mlir::Plugin;
+using namespace mlir;
+
+static uintptr_t GetID(Json::Value node)
+{
+ string id = node.asString();
+ return atol(id.c_str());
+}
+
+Json::Value PluginJson::TypeJsonSerialize(PluginIR::PluginTypeBase& type)
+{
+ Json::Value root;
+ Json::Value operationObj;
+ Json::Value item;
+
+ uint64_t ReTypeId;
+ uint64_t ReTypeWidth;
+
+ ReTypeId = static_cast(type.getPluginTypeID());
+ item["id"] = std::to_string(ReTypeId);
+
+ if (auto elemTy = type.dyn_cast()) {
+ auto baseTy = elemTy.getElementType().dyn_cast();
+ item["elementType"] = TypeJsonSerialize(baseTy);
+ if (elemTy.isReadOnlyElem()) {
+ item["elemConst"] = "1";
+ } else {
+ item["elemConst"] = "0";
+ }
+ }
+
+ if (type.getPluginIntOrFloatBitWidth() != 0) {
+ ReTypeWidth = type.getPluginIntOrFloatBitWidth();
+ item["width"] = std::to_string(ReTypeWidth);
+ }
+
+ if (type.isSignedPluginInteger()) {
+ item["signed"] = "1";
+ }
+
+ if (type.isUnsignedPluginInteger()) {
+ item["signed"] = "0";
+ }
+
+ root["type"] = item;
+ return root;
+}
+
+PluginIR::PluginTypeBase PluginJson::TypeJsonDeSerialize(const string& data, mlir::MLIRContext &context)
+{
+ Json::Value root;
+ Json::Reader reader;
+ Json::Value node;
+ reader.parse(data, root);
+
+ PluginIR::PluginTypeBase baseType;
+
+ Json::Value type = root["type"];
+ uint64_t id = GetID(type["id"]);
+ PluginIR::PluginTypeID PluginTypeId = static_cast(id);
+
+ if (type["signed"] && (id >= static_cast(PluginIR::UIntegerTy1ID)
+ && id <= static_cast(PluginIR::IntegerTy64ID))) {
+ string s = type["signed"].asString();
+ uint64_t width = GetID(type["width"]);
+ if (s == "1") {
+ baseType = PluginIR::PluginIntegerType::get(&context, width, PluginIR::PluginIntegerType::Signed);
+ } else {
+ baseType = PluginIR::PluginIntegerType::get(&context, width, PluginIR::PluginIntegerType::Unsigned);
+ }
+ } else if (type["width"] && (id == static_cast(PluginIR::FloatTyID)
+ || id == static_cast(PluginIR::DoubleTyID))) {
+ uint64_t width = GetID(type["width"]);
+ baseType = PluginIR::PluginFloatType::get(&context, width);
+ } else if (id == static_cast(PluginIR::PointerTyID)) {
+ mlir::Type elemTy = TypeJsonDeSerialize(type["elementType"].toStyledString(), context);
+ baseType = PluginIR::PluginPointerType::get(&context, elemTy, type["elemConst"].asString() == "1" ? 1 : 0);
+ } else {
+ if (PluginTypeId == PluginIR::VoidTyID) {
+ baseType = PluginIR::PluginVoidType::get(&context);
+ }
+ if (PluginTypeId == PluginIR::BooleanTyID) {
+ baseType = PluginIR::PluginBooleanType::get(&context);
+ }
+ if (PluginTypeId == PluginIR::UndefTyID) {
+ baseType = PluginIR::PluginUndefType::get(&context);
+ }
+ }
+
+ return baseType;
+}
+
+void PluginJson::FunctionOpJsonSerialize(vector& data, string& out)
+{
+ Json::Value root;
+ Json::Value operationObj;
+ Json::Value item;
+
+ int i = 0;
+ string operation;
+
+ for (auto& d: data) {
+ item["id"] = std::to_string(d.idAttr().getInt());
+ if (d.declaredInlineAttr().getValue()) {
+ item["attributes"]["declaredInline"] = "1";
+ } else {
+ item["attributes"]["declaredInline"] = "0";
+ }
+ 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 (isa(inst)) {
+ continue;
+ } else if (isa(inst)) {
+ continue;
+ } else if (isa(inst)) {
+ continue;
+ } else if (isa(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 PluginJson::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 PluginJson::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 PluginJson::RetOpJsonSerialize(RetOp data, uint64_t &bbId)
+{
+ Json::Value root;
+ bbId = data.addressAttr().getInt();
+ root["address"] = std::to_string(bbId);
+ return root;
+}
+
+Json::Value PluginJson::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 PluginJson::LocalDeclsJsonSerialize(vector& decls, string& out)
+{
+ Json::Value root;
+ Json::Value operationObj;
+ Json::Value item;
+ int i = 0;
+ string operation;
+
+ for (auto& decl: decls) {
+ item["id"] = std::to_string(decl.idAttr().getInt());
+ item["attributes"]["symName"] = decl.symNameAttr().getValue().str().c_str();
+ item["attributes"]["typeID"] = decl.typeIDAttr().getInt();
+ item["attributes"]["typeWidth"] = decl.typeWidthAttr().getInt();
+ operation = "localDecl" + std::to_string(i++);
+ root[operation] = item;
+ item.clear();
+ }
+ out = root.toStyledString();
+}
+
+void PluginJson::LoopOpsJsonSerialize(vector& loops, string& out)
+{
+ Json::Value root;
+ Json::Value operationObj;
+ Json::Value item;
+ int i = 0;
+ string operation;
+
+ for (auto& loop: loops) {
+ item["id"] = std::to_string(loop.idAttr().getInt());
+ item["index"] = std::to_string(loop.indexAttr().getInt());
+ item["attributes"]["innerLoopId"] = std::to_string(loop.innerLoopIdAttr().getInt());
+ item["attributes"]["outerLoopId"] = std::to_string(loop.outerLoopIdAttr().getInt());
+ item["attributes"]["numBlock"] = std::to_string(loop.numBlockAttr().getInt());
+ operation = "loopOp" + std::to_string(i++);
+ root[operation] = item;
+ item.clear();
+ }
+ out = root.toStyledString();
+}
+
+void PluginJson::LoopOpJsonSerialize(mlir::Plugin::LoopOp& loop, string& out)
+{
+ Json::Value root;
+ root["id"] = std::to_string(loop.idAttr().getInt());
+ root["index"] = std::to_string(loop.indexAttr().getInt());
+ root["attributes"]["innerLoopId"] = std::to_string(loop.innerLoopIdAttr().getInt());
+ root["attributes"]["outerLoopId"] = std::to_string(loop.outerLoopIdAttr().getInt());
+ root["attributes"]["numBlock"] = std::to_string(loop.numBlockAttr().getInt());
+ out = root.toStyledString();
+}
+
+void PluginJson::BlocksJsonSerialize(vector& blocks, string& out)
+{
+ Json::Value root;
+ Json::Value item;
+ int i = 0;
+ string index;
+
+ for (auto& block : blocks) {
+ item["id"] = std::to_string(block);
+ index = "block" + std::to_string(i++);
+ root[index] = item;
+ item.clear();
+ }
+ out = root.toStyledString();
+}
+
+void PluginJson::EdgesJsonSerialize(vector >& edges, string& out)
+{
+ Json::Value root;
+ Json::Value item;
+ int i = 0;
+ string index;
+
+ for (auto& edge : edges) {
+ item["src"] = std::to_string(edge.first);
+ item["dest"] = std::to_string(edge.second);
+ index = "edge" + std::to_string(i++);
+ root[index] = item;
+ item.clear();
+ }
+ out = root.toStyledString();
+}
+
+void PluginJson::EdgeJsonSerialize(std::pair& edge, string& out)
+{
+ Json::Value root;
+ root["src"] = std::to_string(edge.first);
+ root["dest"] = std::to_string(edge.second);
+ out = root.toStyledString();
+}
+
+// void类型的Json序列化
+void PluginJson::NopJsonSerialize(string& out)
+{
+ Json::Value root;
+ out = root.toStyledString();
+}
+
+void PluginJson::GetPhiOpsJsonSerialize(vector phiOps, string & out)
+{
+ Json::Value root;
+ Json::Value item;
+ int i = 0;
+ string operation;
+ uint64_t placeholder = 0;
+ for (auto phi : phiOps) {
+ item = OperationJsonSerialize(phi.getOperation(), placeholder);
+ operation = "operation" + std::to_string(i++);
+ root[operation] = item;
+ item.clear();
+ }
+ out = root.toStyledString();
+}
+
+Json::Value PluginJson::CallOpJsonSerialize(CallOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["callee"] = data.callee().str();
+ item["OperationName"] = data.getOperation()->getName().getStringRef().str();
+ size_t opIdx = 0;
+ for (mlir::Value v : data.getArgOperands()) {
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input] = ValueJsonSerialize(v);
+ }
+
+ return item;
+}
+
+Json::Value PluginJson::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 PluginJson::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());
+ item["OperationName"] = data.getOperation()->getName().getStringRef().str();
+ size_t opIdx = 0;
+ for (mlir::Value v : data.operands()) {
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input] = ValueJsonSerialize(v);
+ }
+
+ return item;
+}
+
+Json::Value PluginJson::SSAOpJsonSerialize(SSAOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["defCode"] = std::to_string(data.defCodeAttr().getInt());
+ item["readOnly"] = std::to_string(data.readOnlyAttr().getValue());
+ item["nameVarId"] = std::to_string(data.nameVarIdAttr().getInt());
+ item["ssaParmDecl"] = std::to_string(data.ssaParmDeclAttr().getInt());
+ item["version"] = std::to_string(data.versionAttr().getInt());
+ item["definingId"] = std::to_string(data.definingIdAttr().getInt());
+ auto retTy = data.getResultType().dyn_cast();
+ item["retType"] = TypeJsonSerialize(retTy);
+ return item;
+}
+
+Json::Value PluginJson::AssignOpJsonSerialize(AssignOp& data)
+{
+ Json::Value item;
+ item["id"] = std::to_string(data.idAttr().getInt());
+ item["exprCode"] = std::to_string(data.exprCodeAttr().getInt());
+ item["OperationName"] = data.getOperation()->getName().getStringRef().str();
+ size_t opIdx = 0;
+ for (mlir::Value v : data.operands()) {
+ string input = "input" + std::to_string(opIdx++);
+ item["operands"][input] = ValueJsonSerialize(v);
+ }
+
+ return item;
+}
+
+Json::Value PluginJson::ValueJsonSerialize(mlir::Value data)
+{
+ Json::Value root;
+ if (ConstOp cOp = data.getDefiningOp()) {
+ auto retTy = data.getType().dyn_cast();
+ root["retType"] = TypeJsonSerialize(retTy);
+ root["id"] = std::to_string(cOp.idAttr().getInt());
+ root["defCode"] = std::to_string(static_cast(IDefineCode::IntCST));
+ root["value"] = std::to_string(cOp.initAttr().cast().getInt());
+ } else if (MemOp mOp = data.getDefiningOp()) {
+ root = MemOpJsonSerialize(mOp);
+ } else if (SSAOp sOp = data.getDefiningOp()) {
+ root = SSAOpJsonSerialize(sOp);
+ } else if (PlaceholderOp phOp = data.getDefiningOp()) {
+ root["id"] = std::to_string(phOp.idAttr().getInt());
+ root["defCode"] = std::to_string(phOp.defCodeAttr().getInt());
+ auto retTy = phOp.getResultType().dyn_cast();
+ root["retType"] = TypeJsonSerialize(retTy);
+ } else {
+ LOGE("ERROR: Can't Serialize!");
+ }
+ return root;
+}
+
+Json::Value PluginJson::MemOpJsonSerialize(MemOp& data)
+{
+ Json::Value root;
+ root["id"] = std::to_string(data.idAttr().getInt());
+ root["defCode"] = std::to_string(data.defCodeAttr().getInt());
+ root["readOnly"] = std::to_string(data.readOnlyAttr().getValue());
+ mlir::Value base = data.GetBase();
+ mlir::Value offset = data.GetOffset();
+ root["base"] = ValueJsonSerialize(base);
+ root["offset"] = ValueJsonSerialize(offset);
+ auto retTy = data.getResultType().dyn_cast();
+ root["retType"] = TypeJsonSerialize(retTy);
+ return root;
+}
+
+void PluginJson::IntegerSerialize(int64_t data, string& out)
+{
+ Json::Value root;
+ root["integerData"] = data;
+ out = root.toStyledString();
+}
+
+void PluginJson::StringSerialize(const string& data, string& out)
+{
+ Json::Value root;
+ root["stringData"] = data;
+ out = root.toStyledString();
+}
+} // namespace PinClient
--
2.27.0.windows.1