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