/* * Copyright (c) 2021 - 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "debuginfoDumper.h" #include "macros.h" #include <sstream> #include <string> namespace panda::es2panda::debuginfo { DebugInfoDumper::DebugInfoDumper(const pandasm::Program *prog) : prog_(prog) {} static const char *PutComma(bool comma) { return comma ? "," : ""; } template <typename T> void DebugInfoDumper::WrapArray(const char *name, const std::vector<T> &array, bool comma) { ss_ << std::endl; Indent(); ss_ << "\"" << name << "\": " << "["; if (array.empty()) { ss_ << "]" << PutComma(comma); return; } ss_ << "\n"; indent_++; // dump VariableDebugInfo in reverse order to match ts2panda // NOLINTNEXTLINE if constexpr (std::is_same_v<T, pandasm::debuginfo::LocalVariable>) { typename std::vector<T>::const_reverse_iterator elem; for (elem = array.rbegin(); elem != array.rend(); ++elem) { Indent(); WriteVariableInfo(*elem); (std::next(elem) == array.rend()) ? ss_ << "" : ss_ << ","; ss_ << "\n"; } // NOLINTNEXTLINE } else { typename std::vector<T>::const_iterator elem; for (elem = array.begin(); elem != array.end(); ++elem) { Indent(); // NOLINTNEXTLINE if constexpr (std::is_same_v<T, pandasm::Ins>) { WriteIns(*elem); // NOLINTNEXTLINE } else if constexpr (std::is_same_v<T, pandasm::Function::Parameter>) { ss_ << "\"" << (*elem).type.GetName() << "\""; // NOLINTNEXTLINE } else if constexpr (std::is_same_v<T, std::string>) { ss_ << "\"" << *elem << "\""; // NOLINTNEXTLINE } else if constexpr (std::is_same_v<T, std::variant<int64_t, double>>) { ss_ << (std::holds_alternative<int64_t>(*elem) ? std::to_string(std::get<int64_t>(*elem)) : std::to_string(std::get<double>(*elem))); // NOLINTNEXTLINE } else { ss_ << std::to_string(*elem); } (std::next(elem) == array.end()) ? ss_ << "" : ss_ << ","; ss_ << "\n"; } } indent_--; Indent(); ss_ << "]" << PutComma(comma); } void DebugInfoDumper::WriteIns(const pandasm::Ins &ins) { ss_ << "{"; { pandasm::Ins insCopy; insCopy.opcode = ins.opcode; insCopy.setLabel = ins.setLabel; insCopy.label = ins.label; WriteProperty("opcode", insCopy.ToString()); } indent_++; WrapArray("regs", ins.regs); WrapArray("ids", ins.ids); WrapArray("imms", ins.imms); ss_ << std::endl; Indent(); ss_ << "\"label\": " << "\"" << ins.label << "\","; WritePosInfo(ins.insDebug); indent_--; Indent(); ss_ << "}"; } void DebugInfoDumper::WriteMetaData(const std::vector<pandasm::AnnotationData> &metaData) { for (const auto &it : metaData) { for (const auto &elem : it.GetElements()) { pandasm::ScalarValue *value = elem.GetValue()->GetAsScalar(); if (value->GetType() == pandasm::Value::Type::STRING) { WriteProperty(elem.GetName().c_str(), value->GetValue<std::string>(), false); } else if (value->GetType() == pandasm::Value::Type::U32) { WriteProperty(elem.GetName().c_str(), value->GetValue<size_t>()); } } } } void DebugInfoDumper::WritePosInfo(const pandasm::debuginfo::Ins &posInfo) { ss_ << std::endl; Indent(); ss_ << "\"debug_pos_info\": {"; WriteProperty("boundLeft", posInfo.boundLeft); WriteProperty("boundRight", posInfo.boundRight); WriteProperty("sourceLineNum", static_cast<int32_t>(posInfo.lineNumber)); WriteProperty("wholeLine", posInfo.wholeLine, false); Indent(); ss_ << "}" << std::endl; } void DebugInfoDumper::WriteVariableInfo(const pandasm::debuginfo::LocalVariable &localVariableDebug) { ss_ << "{"; WriteProperty("name", localVariableDebug.name); WriteProperty("signature", localVariableDebug.signature); WriteProperty("signatureType", localVariableDebug.signatureType); WriteProperty("reg", localVariableDebug.reg); WriteProperty("start", static_cast<size_t>(localVariableDebug.start)); WriteProperty("length", static_cast<size_t>(localVariableDebug.length), false); Indent(); ss_ << "}"; } void DebugInfoDumper::Dump() { ss_ << "{\n"; indent_++; Indent(); ss_ << "\"functions\": [" << std::endl; auto iter = prog_->functionTable.begin(); for (; iter != prog_->functionTable.end(); ++iter) { indent_++; Indent(); ss_ << "{"; WriteProperty("name", iter->first); ss_ << std::endl; indent_++; Indent(); ss_ << "\"signature\": {"; WriteProperty("retType", iter->second.returnType.GetName()); indent_++; WrapArray("params", iter->second.params, false); indent_ -= 2U; ss_ << std::endl; Indent(); ss_ << "},"; WrapArray("ins", iter->second.ins); WrapArray("variables", iter->second.localVariableDebug); WriteProperty("sourceFile", iter->second.sourceFile); WriteProperty("sourceCode", iter->second.sourceCode); // icSize - parameterLength - funcName WriteMetaData(iter->second.metadata->GetAnnotations()); indent_--; Indent(); ss_ << "}"; if (std::next(iter) != prog_->functionTable.end()) { ss_ << ","; } ss_ << std::endl; } indent_--; Indent(); ss_ << "]" << std::endl; ss_ << "}"; ss_ << std::endl; std::cout << ss_.str(); } void DebugInfoDumper::WriteProperty(const char *key, const Value &value, bool comma) { ss_ << std::endl; indent_++; Indent(); ss_ << "\"" << key << "\": "; if (std::holds_alternative<std::string>(value)) { ss_ << "\"" << std::get<std::string>(value) << "\""; } else if (std::holds_alternative<size_t>(value)) { ss_ << std::to_string(std::get<size_t>(value)); } else if (std::holds_alternative<int32_t>(value)) { ss_ << std::to_string(std::get<int32_t>(value)); } comma ? ss_ << "," : ss_ << std::endl; indent_--; } void DebugInfoDumper::Indent() { for (int32_t i = 0; i <= indent_; i++) { ss_ << " "; } } } // namespace panda::es2panda::debuginfo