13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "debuginfoDumper.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <macros.h>
193af6ab5fSopenharmony_ci
203af6ab5fSopenharmony_ci#include <sstream>
213af6ab5fSopenharmony_ci#include <string>
223af6ab5fSopenharmony_ci
233af6ab5fSopenharmony_cinamespace panda::es2panda::debuginfo {
243af6ab5fSopenharmony_ci
253af6ab5fSopenharmony_ciDebugInfoDumper::DebugInfoDumper(const pandasm::Program *prog) : prog_(prog) {}
263af6ab5fSopenharmony_ci
273af6ab5fSopenharmony_cistatic const char *PutComma(bool comma)
283af6ab5fSopenharmony_ci{
293af6ab5fSopenharmony_ci    return comma ? "," : "";
303af6ab5fSopenharmony_ci}
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_citemplate <typename T>
333af6ab5fSopenharmony_civoid DebugInfoDumper::WrapArray(const char *name, const std::vector<T> &array, bool comma)
343af6ab5fSopenharmony_ci{
353af6ab5fSopenharmony_ci    ss_ << std::endl;
363af6ab5fSopenharmony_ci    Indent();
373af6ab5fSopenharmony_ci    ss_ << "\"" << name << "\": "
383af6ab5fSopenharmony_ci        << "[";
393af6ab5fSopenharmony_ci
403af6ab5fSopenharmony_ci    if (array.empty()) {
413af6ab5fSopenharmony_ci        ss_ << "]" << PutComma(comma);
423af6ab5fSopenharmony_ci        return;
433af6ab5fSopenharmony_ci    }
443af6ab5fSopenharmony_ci
453af6ab5fSopenharmony_ci    ss_ << "\n";
463af6ab5fSopenharmony_ci    indent_++;
473af6ab5fSopenharmony_ci    // dump VariableDebugInfo in reverse order to match ts2panda
483af6ab5fSopenharmony_ci    // NOLINTNEXTLINE
493af6ab5fSopenharmony_ci    if constexpr (std::is_same_v<T, pandasm::debuginfo::LocalVariable>) {
503af6ab5fSopenharmony_ci        typename std::vector<T>::const_reverse_iterator elem;
513af6ab5fSopenharmony_ci        for (elem = array.rbegin(); elem != array.rend(); ++elem) {
523af6ab5fSopenharmony_ci            Indent();
533af6ab5fSopenharmony_ci            WriteVariableInfo(*elem);
543af6ab5fSopenharmony_ci            (std::next(elem) == array.rend()) ? ss_ << "" : ss_ << ",";
553af6ab5fSopenharmony_ci            ss_ << "\n";
563af6ab5fSopenharmony_ci        }
573af6ab5fSopenharmony_ci        // NOLINTNEXTLINE
583af6ab5fSopenharmony_ci    } else {
593af6ab5fSopenharmony_ci        typename std::vector<T>::const_iterator elem;
603af6ab5fSopenharmony_ci        for (elem = array.begin(); elem != array.end(); ++elem) {
613af6ab5fSopenharmony_ci            Indent();
623af6ab5fSopenharmony_ci            // NOLINTNEXTLINE
633af6ab5fSopenharmony_ci            if constexpr (std::is_same_v<T, pandasm::Ins>) {
643af6ab5fSopenharmony_ci                WriteIns(*elem);
653af6ab5fSopenharmony_ci                // NOLINTNEXTLINE
663af6ab5fSopenharmony_ci            } else if constexpr (std::is_same_v<T, pandasm::Function::Parameter>) {
673af6ab5fSopenharmony_ci                ss_ << "\"" << (*elem).type.GetName() << "\"";
683af6ab5fSopenharmony_ci                // NOLINTNEXTLINE
693af6ab5fSopenharmony_ci            } else if constexpr (std::is_same_v<T, std::string>) {
703af6ab5fSopenharmony_ci                ss_ << "\"" << *elem << "\"";
713af6ab5fSopenharmony_ci                // NOLINTNEXTLINE
723af6ab5fSopenharmony_ci            } else if constexpr (std::is_same_v<T, std::variant<int64_t, double>>) {
733af6ab5fSopenharmony_ci                if (std::holds_alternative<int64_t>(*elem)) {
743af6ab5fSopenharmony_ci                    ss_ << std::to_string(std::get<int64_t>(*elem));
753af6ab5fSopenharmony_ci                } else {
763af6ab5fSopenharmony_ci                    ss_ << std::to_string(std::get<double>(*elem));
773af6ab5fSopenharmony_ci                }
783af6ab5fSopenharmony_ci                // NOLINTNEXTLINE
793af6ab5fSopenharmony_ci            } else {
803af6ab5fSopenharmony_ci                ss_ << std::to_string(*elem);
813af6ab5fSopenharmony_ci            }
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ci            (std::next(elem) == array.end()) ? ss_ << "" : ss_ << ",";
843af6ab5fSopenharmony_ci            ss_ << "\n";
853af6ab5fSopenharmony_ci        }
863af6ab5fSopenharmony_ci    }
873af6ab5fSopenharmony_ci
883af6ab5fSopenharmony_ci    indent_--;
893af6ab5fSopenharmony_ci    Indent();
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_ci    ss_ << "]" << PutComma(comma);
923af6ab5fSopenharmony_ci}
933af6ab5fSopenharmony_ci
943af6ab5fSopenharmony_civoid DebugInfoDumper::WriteIns(const pandasm::Ins &ins)
953af6ab5fSopenharmony_ci{
963af6ab5fSopenharmony_ci    ss_ << "{";
973af6ab5fSopenharmony_ci    {
983af6ab5fSopenharmony_ci        pandasm::Ins insCopy;
993af6ab5fSopenharmony_ci        insCopy.opcode = ins.opcode;
1003af6ab5fSopenharmony_ci        insCopy.set_label = ins.set_label;
1013af6ab5fSopenharmony_ci        insCopy.label = ins.label;
1023af6ab5fSopenharmony_ci        WriteProperty("opcode", insCopy.ToString());
1033af6ab5fSopenharmony_ci    }
1043af6ab5fSopenharmony_ci    indent_++;
1053af6ab5fSopenharmony_ci    WrapArray("regs", ins.regs);
1063af6ab5fSopenharmony_ci    WrapArray("ids", ins.ids);
1073af6ab5fSopenharmony_ci    WrapArray("imms", ins.imms);
1083af6ab5fSopenharmony_ci    ss_ << std::endl;
1093af6ab5fSopenharmony_ci    Indent();
1103af6ab5fSopenharmony_ci    ss_ << "\"label\": "
1113af6ab5fSopenharmony_ci        << "\"" << ins.label << "\",";
1123af6ab5fSopenharmony_ci    WritePosInfo(ins.ins_debug);
1133af6ab5fSopenharmony_ci    indent_--;
1143af6ab5fSopenharmony_ci    Indent();
1153af6ab5fSopenharmony_ci    ss_ << "}";
1163af6ab5fSopenharmony_ci}
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_civoid DebugInfoDumper::WriteMetaData(const std::vector<pandasm::AnnotationData> &metaData)
1193af6ab5fSopenharmony_ci{
1203af6ab5fSopenharmony_ci    for (const auto &it : metaData) {
1213af6ab5fSopenharmony_ci        for (const auto &elem : it.GetElements()) {
1223af6ab5fSopenharmony_ci            pandasm::ScalarValue *value = elem.GetValue()->GetAsScalar();
1233af6ab5fSopenharmony_ci            if (value->GetType() == pandasm::Value::Type::STRING) {
1243af6ab5fSopenharmony_ci                WriteProperty(elem.GetName().c_str(), value->GetValue<std::string>(), false);
1253af6ab5fSopenharmony_ci            } else if (value->GetType() == pandasm::Value::Type::U32) {
1263af6ab5fSopenharmony_ci                WriteProperty(elem.GetName().c_str(), value->GetValue<size_t>());
1273af6ab5fSopenharmony_ci            }
1283af6ab5fSopenharmony_ci        }
1293af6ab5fSopenharmony_ci    }
1303af6ab5fSopenharmony_ci}
1313af6ab5fSopenharmony_ci
1323af6ab5fSopenharmony_civoid DebugInfoDumper::WritePosInfo(const pandasm::debuginfo::Ins &posInfo)
1333af6ab5fSopenharmony_ci{
1343af6ab5fSopenharmony_ci    ss_ << std::endl;
1353af6ab5fSopenharmony_ci    Indent();
1363af6ab5fSopenharmony_ci    ss_ << "\"debug_pos_info\": {";
1373af6ab5fSopenharmony_ci    WriteProperty("boundLeft", posInfo.bound_left);
1383af6ab5fSopenharmony_ci    WriteProperty("boundRight", posInfo.bound_right);
1393af6ab5fSopenharmony_ci    WriteProperty("sourceLineNum", static_cast<int32_t>(posInfo.line_number));
1403af6ab5fSopenharmony_ci    WriteProperty("wholeLine", posInfo.whole_line, false);
1413af6ab5fSopenharmony_ci    Indent();
1423af6ab5fSopenharmony_ci    ss_ << "}" << std::endl;
1433af6ab5fSopenharmony_ci}
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_civoid DebugInfoDumper::WriteVariableInfo(const pandasm::debuginfo::LocalVariable &localVariableDebug)
1463af6ab5fSopenharmony_ci{
1473af6ab5fSopenharmony_ci    ss_ << "{";
1483af6ab5fSopenharmony_ci    WriteProperty("name", localVariableDebug.name);
1493af6ab5fSopenharmony_ci    WriteProperty("signature", localVariableDebug.signature);
1503af6ab5fSopenharmony_ci    WriteProperty("signatureType", localVariableDebug.signature_type);
1513af6ab5fSopenharmony_ci    WriteProperty("reg", localVariableDebug.reg);
1523af6ab5fSopenharmony_ci    WriteProperty("start", static_cast<size_t>(localVariableDebug.start));
1533af6ab5fSopenharmony_ci    WriteProperty("length", static_cast<size_t>(localVariableDebug.length), false);
1543af6ab5fSopenharmony_ci    Indent();
1553af6ab5fSopenharmony_ci    ss_ << "}";
1563af6ab5fSopenharmony_ci}
1573af6ab5fSopenharmony_ci
1583af6ab5fSopenharmony_civoid DebugInfoDumper::Dump()
1593af6ab5fSopenharmony_ci{
1603af6ab5fSopenharmony_ci    ss_ << "{\n";
1613af6ab5fSopenharmony_ci    indent_++;
1623af6ab5fSopenharmony_ci    Indent();
1633af6ab5fSopenharmony_ci    ss_ << "\"functions\": [" << std::endl;
1643af6ab5fSopenharmony_ci
1653af6ab5fSopenharmony_ci    auto iter = prog_->function_table.begin();
1663af6ab5fSopenharmony_ci
1673af6ab5fSopenharmony_ci    for (; iter != prog_->function_table.end(); ++iter) {
1683af6ab5fSopenharmony_ci        indent_++;
1693af6ab5fSopenharmony_ci        Indent();
1703af6ab5fSopenharmony_ci        ss_ << "{";
1713af6ab5fSopenharmony_ci        WriteProperty("name", iter->first);
1723af6ab5fSopenharmony_ci        ss_ << std::endl;
1733af6ab5fSopenharmony_ci
1743af6ab5fSopenharmony_ci        indent_++;
1753af6ab5fSopenharmony_ci        Indent();
1763af6ab5fSopenharmony_ci        ss_ << "\"signature\": {";
1773af6ab5fSopenharmony_ci        WriteProperty("retType", iter->second.return_type.GetName());
1783af6ab5fSopenharmony_ci        indent_++;
1793af6ab5fSopenharmony_ci        WrapArray("params", iter->second.params, false);
1803af6ab5fSopenharmony_ci        indent_ -= 2U;
1813af6ab5fSopenharmony_ci        ss_ << std::endl;
1823af6ab5fSopenharmony_ci        Indent();
1833af6ab5fSopenharmony_ci        ss_ << "},";
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_ci        WrapArray("ins", iter->second.ins);
1863af6ab5fSopenharmony_ci        WrapArray("variables", iter->second.local_variable_debug);
1873af6ab5fSopenharmony_ci        WriteProperty("sourceFile", iter->second.source_file);
1883af6ab5fSopenharmony_ci        WriteProperty("sourceCode", iter->second.source_code);
1893af6ab5fSopenharmony_ci        // icSize - parameterLength - funcName
1903af6ab5fSopenharmony_ci        WriteMetaData(iter->second.metadata->GetAnnotations());
1913af6ab5fSopenharmony_ci
1923af6ab5fSopenharmony_ci        indent_--;
1933af6ab5fSopenharmony_ci        Indent();
1943af6ab5fSopenharmony_ci        ss_ << "}";
1953af6ab5fSopenharmony_ci
1963af6ab5fSopenharmony_ci        if (std::next(iter) != prog_->function_table.end()) {
1973af6ab5fSopenharmony_ci            ss_ << ",";
1983af6ab5fSopenharmony_ci        }
1993af6ab5fSopenharmony_ci
2003af6ab5fSopenharmony_ci        ss_ << std::endl;
2013af6ab5fSopenharmony_ci    }
2023af6ab5fSopenharmony_ci
2033af6ab5fSopenharmony_ci    indent_--;
2043af6ab5fSopenharmony_ci    Indent();
2053af6ab5fSopenharmony_ci    ss_ << "]" << std::endl;
2063af6ab5fSopenharmony_ci    ss_ << "}";
2073af6ab5fSopenharmony_ci    ss_ << std::endl;
2083af6ab5fSopenharmony_ci    std::cout << ss_.str();
2093af6ab5fSopenharmony_ci}
2103af6ab5fSopenharmony_ci
2113af6ab5fSopenharmony_civoid DebugInfoDumper::WriteProperty(const char *key, const Value &value, bool comma)
2123af6ab5fSopenharmony_ci{
2133af6ab5fSopenharmony_ci    ss_ << std::endl;
2143af6ab5fSopenharmony_ci    indent_++;
2153af6ab5fSopenharmony_ci    Indent();
2163af6ab5fSopenharmony_ci    ss_ << "\"" << key << "\": ";
2173af6ab5fSopenharmony_ci    if (std::holds_alternative<std::string>(value)) {
2183af6ab5fSopenharmony_ci        ss_ << "\"" << std::get<std::string>(value) << "\"";
2193af6ab5fSopenharmony_ci    } else if (std::holds_alternative<size_t>(value)) {
2203af6ab5fSopenharmony_ci        ss_ << std::to_string(std::get<size_t>(value));
2213af6ab5fSopenharmony_ci    } else if (std::holds_alternative<int32_t>(value)) {
2223af6ab5fSopenharmony_ci        ss_ << std::to_string(std::get<int32_t>(value));
2233af6ab5fSopenharmony_ci    }
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_ci    comma ? ss_ << "," : ss_ << std::endl;
2263af6ab5fSopenharmony_ci    indent_--;
2273af6ab5fSopenharmony_ci}
2283af6ab5fSopenharmony_ci
2293af6ab5fSopenharmony_civoid DebugInfoDumper::Indent()
2303af6ab5fSopenharmony_ci{
2313af6ab5fSopenharmony_ci    for (int32_t i = 0; i <= indent_; i++) {
2323af6ab5fSopenharmony_ci        ss_ << "  ";
2333af6ab5fSopenharmony_ci    }
2343af6ab5fSopenharmony_ci}
2353af6ab5fSopenharmony_ci
2363af6ab5fSopenharmony_ci}  // namespace panda::es2panda::debuginfo
237