diff --git a/Makefile b/Makefile index 1a7f7df7f22855a15dcf3c3ca54291932791e771..3e14acbf5bed8b5637a9154ac6f6d830b66a9893 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. +# Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. # # OpenArkCompiler is licensed under Mulan PSL v2. # You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -66,6 +66,10 @@ maple: maplegendef irbuild: $(call build_gn, $(GN_OPTIONS), irbuild) +.PHONY: mpldbg +mpldbg: + $(call build_gn, $(GN_OPTIONS), mpldbg) + .PHONY: ast2mpl ast2mpl: $(call build_gn, $(GN_OPTIONS), ast2mpl) diff --git a/src/mapleall/maple_be/BUILD.gn b/src/mapleall/maple_be/BUILD.gn index e399e2b24f42c1f9e93e4b8580ce1dd7e87aca55..cca08739f79ec04e666c6434dee504bf549d2089 100644 --- a/src/mapleall/maple_be/BUILD.gn +++ b/src/mapleall/maple_be/BUILD.gn @@ -26,6 +26,7 @@ include_directories = [ "${MAPLEALL_ROOT}/maple_ipa/include", "${MAPLEALL_ROOT}/maple_phase/include", "${MAPLE_ROOT}/third_party/bounds_checking_function/include", + "${MAPLE_ROOT}/third_party/dwarf/include", ] deps_libcg = [] diff --git a/src/mapleall/maple_driver/BUILD.gn b/src/mapleall/maple_driver/BUILD.gn index 35ed290dfdacff0f311dd38a4c1318ef9fc143f1..1c69cb1dd484d454283975e045e62195434fe32f 100644 --- a/src/mapleall/maple_driver/BUILD.gn +++ b/src/mapleall/maple_driver/BUILD.gn @@ -35,6 +35,7 @@ include_directories = [ "${MAPLEALL_ROOT}/maple_ir/include", "${MAPLEALL_ROOT}/mempool/include", "${MAPLE_ROOT}/third_party/bounds_checking_function/include", + "${MAPLE_ROOT}/third_party/dwarf/include", ] executable("maple") { diff --git a/src/mapleall/maple_driver/include/driver_runner.h b/src/mapleall/maple_driver/include/driver_runner.h index 854de244256f744ee22dbb9918d2964ef549631c..9e0b134222c2ddea9cca568cc414e056fb32f709 100644 --- a/src/mapleall/maple_driver/include/driver_runner.h +++ b/src/mapleall/maple_driver/include/driver_runner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2019-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -116,6 +116,7 @@ class DriverRunner final { std::string baseName; std::string outputFile; InputFileType inputFileType; + bool hasDebugFlag = false; }; } // namespace maple diff --git a/src/mapleall/maple_driver/src/driver_runner.cpp b/src/mapleall/maple_driver/src/driver_runner.cpp index 6d377bef875f866d4d47a2e1f452a780224cab00..6bff84bbd9cce18b50c750480350850639a1d5d6 100644 --- a/src/mapleall/maple_driver/src/driver_runner.cpp +++ b/src/mapleall/maple_driver/src/driver_runner.cpp @@ -21,6 +21,7 @@ #include "mir_function.h" #include "mir_parser.h" #include "file_utils.h" +#include "debug_info.h" #include "lower.h" #if TARGAARCH64 @@ -196,6 +197,12 @@ ErrorCode DriverRunner::ParseInput() const { void DriverRunner::ProcessMpl2mplAndMePhases(const std::string &outputFile, const std::string &vtableImplFile) const { CHECK_MODULE(); theMIRModule = theModule; + + if (hasDebugFlag) { + std::cout << "set up debug info " << std::endl; + theMIRModule->GetDbgInfo()->BuildDebugInfo(); + } + if (mpl2mplOptions != nullptr || meOptions != nullptr) { LogInfo::MapleLogger() << "Processing maplecomb" << '\n'; diff --git a/src/mapleall/maple_ir/BUILD.gn b/src/mapleall/maple_ir/BUILD.gn index cd556422cb2dfb40bf32d056cedc8ae5aacb2f01..adb50c2a4377574afeb406e424ae9bd544858989 100755 --- a/src/mapleall/maple_ir/BUILD.gn +++ b/src/mapleall/maple_ir/BUILD.gn @@ -22,6 +22,7 @@ include_directories = [ "${MAPLEALL_ROOT}/maple_ipa/include", "${MAPLEALL_ROOT}/maple_me/include", "${MAPLEALL_ROOT}/maple_phase/include", + "${MAPLE_ROOT}/third_party/dwarf/include", ] src_libmplir = [ @@ -51,6 +52,8 @@ src_libmplir = [ "src/bin_mpl_import.cpp", "src/bin_mpl_export.cpp", "${MAPLEALL_ROOT}/maple_ipa/src/ea_connection_graph.cpp", + "src/debug_info.cpp", + "src/debug_info_util.cpp", ] src_irbuild = [ "src/driver.cpp" ] @@ -83,3 +86,19 @@ executable("irbuild") { "${MAPLEALL_ROOT}/maple_util:libmplutil", ] } + +src_mpldbg = [ "src/mpl_dbg.cpp" ] + +executable("mpldbg") { + sources = src_mpldbg + include_dirs = include_directories + deps = [ + ":libmplir", + "${MAPLE_ROOT}/third_party/bounds_checking_function:libHWSecureC", + "${MAPLEALL_ROOT}/maple_driver:liboption_parser", + "${MAPLEALL_ROOT}/mpl2mpl:libmpl2mpl", + "${MAPLEALL_ROOT}/maple_phase:libmplphase", + "${MAPLEALL_ROOT}/mempool:libmempool", + "${MAPLEALL_ROOT}/maple_util:libmplutil", + ] +} diff --git a/src/mapleall/maple_ir/include/debug_info.h b/src/mapleall/maple_ir/include/debug_info.h new file mode 100644 index 0000000000000000000000000000000000000000..a794a8ea2a7ebeff260bfd3bcefadeb582604bb0 --- /dev/null +++ b/src/mapleall/maple_ir/include/debug_info.h @@ -0,0 +1,713 @@ +/* + * Copyright (C) [2021] Futurewei Technologies, Inc. All rights reverved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the MulanPSL - 2.0 for more details. + */ + +#ifndef MAPLE_IR_INCLUDE_DBG_INFO_H +#define MAPLE_IR_INCLUDE_DBG_INFO_H +#include + +#include "mpl_logging.h" +#include "types_def.h" +#include "prim_types.h" +#include "mir_nodes.h" +#include "lexer.h" +#include "Dwarf.h" + +using namespace maple; + +namespace maple { + +// for more color code: http://ascii-table.com/ansi-escape-sequences.php +#define RESET "\x1B[0m" +#define BOLD "\x1B[1m" +#define RED "\x1B[31m" +#define GRN "\x1B[32m" +#define YEL "\x1B[33m" + +const uint32 kDbgDefaultVal = 0xdeadbeef; +#define HEX(val) std::hex << "0x" << val << std::dec + +class MIRModule; +class MIRType; +class MIRSymbol; +class MIRSymbolTable; +class MIRTypeNameTable; +class DBGBuilder; +class DBGCompileMsgInfo; +class MIRLexer; + +// for compiletime warnings +class DBGLine { + public: + DBGLine(uint32 lnum, const char *l) : lineNum(lnum), codeLine(l) {} + + void Dump() { + LogInfo::MapleLogger() << "LINE: " << lineNum << " " << codeLine << std::endl; + } + + private: + uint32 lineNum; + const char *codeLine; +}; + +#define MAXLINELEN 4096 + +class DBGCompileMsgInfo { + public: + DBGCompileMsgInfo(); + virtual ~DBGCompileMsgInfo() {} + void ClearLine(uint32 n); + void SetErrPos(uint32 lnum, uint32 cnum); + void UpdateMsg(uint32 lnum, const char *line); + void EmitMsg(); + + private: + uint32 startLine; // mod 3 + uint32 errLNum; + uint32 errCNum; + uint32 errPos; + uint32 lineNum[3]; + uint8 codeLine[3][MAXLINELEN]; // 3 round-robin line buffers +}; + +enum DBGDieKind { kDwTag, kDwAt, kDwOp, kDwAte, kDwForm, kDwCfa }; + +typedef uint32 DwTag; // for DW_TAG_* +typedef uint32 DwAt; // for DW_AT_* +typedef uint32 DwOp; // for DW_OP_* +typedef uint32 DwAte; // for DW_ATE_* +typedef uint32 DwForm; // for DW_FORM_* +typedef uint32 DwCfa; // for DW_CFA_* + +class DBGDieAttr; + +class DBGExpr { + public: + DBGExpr(MIRModule *m) : dwOp(0), value(kDbgDefaultVal), opnds(m->GetMPAllocator().Adapter()) {} + + DBGExpr(MIRModule *m, DwOp op) : dwOp(op), value(kDbgDefaultVal), opnds(m->GetMPAllocator().Adapter()) {} + + virtual ~DBGExpr() {} + + void AddOpnd(uint64 val) { + opnds.push_back(val); + } + + int GetVal() const { + return value; + } + + void SetVal(int v) { + value = v; + } + + DwOp GetDwOp() const { + return dwOp; + } + + void SetDwOp(DwOp op) { + dwOp = op; + } + + MapleVector &GetOpnd() { + return opnds; + } + + int GetOpndSize() const { + return opnds.size(); + } + + void Clear() { + return opnds.clear(); + } + + private: + DwOp dwOp; + // for local var fboffset, global var strIdx + int value; + MapleVector opnds; +}; + +class DBGExprLoc { + public: + DBGExprLoc(MIRModule *m) : module(m), exprVec(m->GetMPAllocator().Adapter()), symLoc(nullptr) { + simpLoc = m->GetMemPool()->New(module); + } + + DBGExprLoc(MIRModule *m, DwOp op) : module(m), exprVec(m->GetMPAllocator().Adapter()), symLoc(nullptr) { + simpLoc = m->GetMemPool()->New(module, op); + } + + virtual ~DBGExprLoc() {} + + bool IsSimp() const { + return (exprVec.size() == 0 && simpLoc->GetVal() != (int)kDbgDefaultVal); + } + + int GetFboffset() const { + return simpLoc->GetVal(); + } + + void SetFboffset(int offset) { + simpLoc->SetVal(offset); + } + + int GetGvarStridx() const { + return simpLoc->GetVal(); + } + + void SetGvarStridx(int idx) { + simpLoc->SetVal(idx); + } + + DwOp GetOp() const { + return simpLoc->GetDwOp(); + } + + uint32 GetSize() const { + return simpLoc->GetOpndSize(); + } + + void ClearOpnd() { + simpLoc->Clear(); + } + + void AddSimpLocOpnd(uint64 val) { + simpLoc->AddOpnd(val); + } + + void *GetSymLoc() { + return symLoc; + } + + void Dump(); + + private: + MIRModule *module; + DBGExpr *simpLoc; + MapleVector exprVec; + void *symLoc; +}; + +class DBGDieAttr { + public: + uint32 SizeOf(DBGDieAttr *attr); + DBGDieAttr(DBGDieKind k) : dieKind(k), dwAttr(DW_AT_deleted), dwForm(DW_FORM_GNU_strp_alt) { + value.u = kDbgDefaultVal; + } + + virtual ~DBGDieAttr() {} + + void AddSimpLocOpnd(uint64 val) { + value.ptr->AddSimpLocOpnd(val); + } + + void ClearSimpLocOpnd() { + value.ptr->ClearOpnd(); + } + + void Dump(int indent); + + DBGDieKind GetKind() { + return dieKind; + } + + void SetKind(DBGDieKind kind) { + dieKind = kind; + } + + DwAt GetDwAt() { + return dwAttr; + } + + void SetDwAt(DwAt at) { + dwAttr = at; + } + + DwForm GetDwForm() { + return dwForm; + } + + void SetDwForm(DwForm form) { + dwForm = form; + } + + int32 GetI() { + return value.i; + } + + void SetI(int32 val) { + value.i = val; + } + + uint32 GetId() { + return value.id; + } + + void SetId(uint32 val) { + value.id = val; + } + + int64 GetJ() { + return value.j; + } + + void SetJ(int64 val) { + value.j = val; + } + + uint64 GetU() { + return value.u; + } + + void SetU(uint64 val) { + value.u = val; + } + + float GetF() { + return value.f; + } + + void SetF(float val) { + value.f = val; + } + + double GetD() { + return value.d; + } + + void SetD(double val) { + value.d = val; + } + + DBGExprLoc *GetPtr() { + return value.ptr; + } + + void SetPtr(DBGExprLoc *val) { + value.ptr = val; + } + + private: + DBGDieKind dieKind; + DwAt dwAttr; + DwForm dwForm; // type for the attribute value + union { + int32 i; + uint32 id; // dieId when dwForm is of DW_FORM_ref + // strIdx when dwForm is of DW_FORM_string + int64 j; + uint64 u; + float f; + double d; + + DBGExprLoc *ptr; + } value; +}; + +class DBGDie { + public: + DBGDie(MIRModule *m, DwTag tag); + virtual ~DBGDie() {} + void AddAttr(DBGDieAttr *attr); + void AddSubVec(DBGDie *die); + + DBGDieAttr *AddAttr(DwAt attr, DwForm form, uint64 val); + DBGDieAttr *AddSimpLocAttr(DwAt at, DwForm form, uint64 val); + DBGDieAttr *AddGlobalLocAttr(DwAt at, DwForm form, uint64 val); + DBGDieAttr *AddFrmBaseAttr(DwAt at, DwForm form, uint64 val); + DBGExprLoc *GetExprLoc(); + bool SetAttr(DwAt attr, uint64 val); + bool SetAttr(DwAt attr, int64 val); + bool SetAttr(DwAt attr, uint32 val); + bool SetAttr(DwAt attr, int32 val); + bool SetAttr(DwAt attr, float val); + bool SetAttr(DwAt attr, double val); + bool SetSimpLocAttr(DwAt attr, int64 val); + bool SetAttr(DwAt attr, DBGExprLoc *ptr); + void ResetParentDie(); + void Dump(int indent); + + uint32 GetId() const { + return id; + } + + void SetId(uint32 val) { + id = val; + } + + DwTag GetTag() const { + return tag; + } + + void SetTag(DwTag val) { + tag = val; + } + + bool GetWithChildren() const { + return withChildren; + } + + void SetWithChildren(bool val) { + withChildren = val; + } + + DBGDie *GetParent() const { + return parent; + } + + void SetParent(DBGDie *val) { + parent = val; + } + + DBGDie *GetSibling() const { + return sibling; + } + + void SetSibling(DBGDie *val) { + sibling = val; + } + + DBGDie *GetFirstChild() const { + return firstChild; + } + + void SetFirstChild(DBGDie *val) { + firstChild = val; + } + + uint32 GetAbbrevId() const { + return abbrevId; + } + + void SetAbbrevId(uint32 val) { + abbrevId = val; + } + + uint32 GetTyIdx() const { + return tyIdx; + } + + void SetTyIdx(uint32 val) { + tyIdx = val; + } + + uint32 GetOffset() const { + return offset; + } + + void SetOffset(uint32 val) { + offset = val; + } + + uint32 GetSize() const { + return size; + } + + void SetSize(uint32 val) { + size = val; + } + + const MapleVector &GetAttrVec() const { + return attrVec; + } + + MapleVector &GetAttrVec() { + return attrVec; + } + + const MapleVector &GetSubDieVec() const { + return subDieVec; + } + + MapleVector &GetSubDieVec() { + return subDieVec; + } + + uint32 GetSubDieVecSize() const { + return subDieVec.size(); + } + + DBGDie *GetSubDieVecAt(uint32 i) const { + return subDieVec[i]; + } + + private: + MIRModule *module; + DwTag tag; + uint32 id; // starts from 1 which is root die compUnit + bool withChildren; + DBGDie *parent; + DBGDie *sibling; + DBGDie *firstChild; + uint32 abbrevId; // id in .debug_abbrev + uint32 tyIdx; // for type TAG + uint32 offset; // Dwarf CU relative offset + uint32 size; // DIE Size in .debug_info + MapleVector attrVec; + MapleVector subDieVec; +}; + +class DBGAbbrevEntry { + public: + DBGAbbrevEntry(MIRModule *m, DBGDie *die); + virtual ~DBGAbbrevEntry() {} + bool Equalto(DBGAbbrevEntry *entry); + void Dump(int indent); + + DwTag GetTag() const { + return tag; + } + + void SetTag(DwTag val) { + tag = val; + } + + uint32 GetAbbrevId() const { + return abbrevId; + } + + void SetAbbrevId(uint32 val) { + abbrevId = val; + } + + bool GetWithChildren() const { + return withChildren; + } + + void SetWithChildren(bool val) { + withChildren = val; + } + + private: + DwTag tag; + uint32 abbrevId; + bool withChildren; + MapleVector attrPairs; // kDwAt kDwForm pairs +}; + +class DBGAbbrevEntryVec { + public: + DBGAbbrevEntryVec(MIRModule *m, DwTag tag) : tag(tag), entryVec(m->GetMPAllocator().Adapter()) {} + + virtual ~DBGAbbrevEntryVec() {} + + uint32 GetId(MapleVector &attrs); + void Dump(int indent); + + DwTag GetTag() const { + return tag; + } + + void SetTag(DwTag val) { + tag = val; + } + + const MapleVector &GetEntryvec() const { + return entryVec; + } + + MapleVector &GetEntryvec() { + return entryVec; + } + + private: + DwTag tag; + MapleVector entryVec; +}; + +class DebugInfo { + public: + DebugInfo(MIRModule *m) + : module(m), + compUnit(nullptr), + dummyTypeDie(nullptr), + lexer(nullptr), + maxId(1), + builder(nullptr), + mplSrcIdx(0), + debugInfoLength(0), + compileMsg(nullptr), + parentDieStack(m->GetMPAllocator().Adapter()), + idDieMap(std::less(), m->GetMPAllocator().Adapter()), + abbrevVec(m->GetMPAllocator().Adapter()), + tagAbbrevMap(std::less(), m->GetMPAllocator().Adapter()), + tyIdxDieIdMap(std::less(), m->GetMPAllocator().Adapter()), + stridxDieIdMap(std::less(), m->GetMPAllocator().Adapter()), + funcDefStrIdxDieIdMap(std::less(), m->GetMPAllocator().Adapter()), + typeDefTyIdxMap(std::less(), m->GetMPAllocator().Adapter()), + pointedPointerMap(std::less(), m->GetMPAllocator().Adapter()), + funcLstrIdxDieIdMap(std::less(), m->GetMPAllocator().Adapter()), + funcLstrIdxLabIdxMap(std::less(), m->GetMPAllocator().Adapter()), + strps(std::less(), m->GetMPAllocator().Adapter()) { + // valid entry starting from index 1 as abbrevid starting from 1 as well + abbrevVec.push_back(nullptr); + InitMsg(); + } + + virtual ~DebugInfo() {} + + void InitMsg() { + compileMsg = module->GetMemPool()->New(); + } + + void UpdateMsg(uint32 lnum, const char *line) { + compileMsg->UpdateMsg(lnum, line); + } + + void SetErrPos(uint32 lnum, uint32 cnum) { + compileMsg->SetErrPos(lnum, cnum); + } + + void EmitMsg() { + compileMsg->EmitMsg(); + } + + DBGDie *GetDie(uint32 id) { + return idDieMap[id]; + } + + DBGDie *GetDie(const MIRFunction *func); + + void Init(); + void Finish(); + void SetupCU(); + void BuildDebugInfo(); + void BuildAliasDIEs(); + void Dump(int indent); + + // build tree to populate withChildren, sibling, firstChild + // also insert DW_AT_sibling attributes when needed + void BuildDieTree(); + + // replace type idx with die id in DW_AT_type attributes + void FillTypeAttrWithDieId(); + + void BuildAbbrev(); + uint32 GetAbbrevId(DBGAbbrevEntryVec *, DBGAbbrevEntry *); + + void SetLocalDie(GStrIdx strIdx, const DBGDie *die); + void SetLocalDie(MIRFunction *func, GStrIdx strIdx, const DBGDie *die); + DBGDie *GetLocalDie(GStrIdx strIdx); + DBGDie *GetLocalDie(MIRFunction *func, GStrIdx strIdx); + + LabelIdx GetLabelIdx(GStrIdx strIdx); + LabelIdx GetLabelIdx(MIRFunction *func, GStrIdx strIdx); + void SetLabelIdx(GStrIdx strIdx, LabelIdx idx); + void SetLabelIdx(MIRFunction *func, GStrIdx strIdx, LabelIdx idx); + + uint32 GetMaxId() const { + return maxId; + } + + uint32 GetIncMaxId() { + return maxId++; + } + + DBGDie *GetIdDieMapAt(uint32 i) { + return idDieMap[i]; + } + + void SetIdDieMap(uint32 i, DBGDie *die) { + idDieMap[i] = die; + } + + uint32 GetParentDieSize() const { + return parentDieStack.size(); + } + + DBGDie *GetParentDie() { + return parentDieStack.top(); + } + + void PushParentDie(DBGDie *die) { + parentDieStack.push(die); + } + + void PopParentDie() { + parentDieStack.pop(); + } + + void ResetParentDie() { + parentDieStack.clear(); + parentDieStack.push(compUnit); + } + + void AddStrps(uint32 val) { + strps.insert(val); + } + + void SetTyidxDieIdMap(TyIdx tyIdx, const DBGDie *die) { + tyIdxDieIdMap[tyIdx.GetIdx()] = die->GetId(); + } + + DBGDieAttr *CreateAttr(DwAt attr, DwForm form, uint64 val); + + DBGDie *CreateVarDie(MIRSymbol *sym, uint32 lnum); + DBGDie *CreateFormalParaDie(MIRFunction *func, MIRType *type, MIRSymbol *sym); + DBGDie *CreateFieldDie(maple::FieldPair pair, uint32 lnum); + DBGDie *CreateBitfieldDie(MIRBitFieldType *type, GStrIdx idx); + DBGDie *CreateStructTypeDie(GStrIdx strIdx, const MIRStructType *type, bool update = false); + DBGDie *CreateClassTypeDie(GStrIdx strIdx, const MIRClassType *type); + DBGDie *CreateInterfaceTypeDie(GStrIdx strIdx, const MIRInterfaceType *type); + DBGDie *CreatePointedFuncTypeDie(MIRFuncType *func); + + DBGDie *GetOrCreateLabelDie(LabelIdx labid); + DBGDie *GetOrCreateTypeAttrDie(MIRSymbol *sym); + DBGDie *GetOrCreateConstTypeDie(TypeAttrs attr, DBGDie *typedie); + DBGDie *GetOrCreateVolatileTypeDie(TypeAttrs attr, DBGDie *typedie); + DBGDie *GetOrCreateFuncDeclDie(MIRFunction *func, uint32 lnum); + DBGDie *GetOrCreateFuncDefDie(MIRFunction *func, uint32 lnum); + DBGDie *GetOrCreatePrimTypeDie(PrimType pty); + DBGDie *GetOrCreateTypeDie(MIRType *type); + DBGDie *GetOrCreatePointTypeDie(const MIRPtrType *type); + DBGDie *GetOrCreateArrayTypeDie(const MIRArrayType *type); + DBGDie *GetOrCreateStructTypeDie(const MIRType *type); + + // Functions for calculating the size and offset of each DW_TAG_xxx and DW_AT_xxx + void ComputeSizeAndOffsets(); + void ComputeSizeAndOffset(DBGDie *die, uint32 &offset); + + private: + MIRModule *module; + DBGDie *compUnit; // root die: compilation unit + DBGDie *dummyTypeDie; // workaround for unknown types + MIRLexer *lexer; + uint32 maxId; + DBGBuilder *builder; + GStrIdx mplSrcIdx; + uint32 debugInfoLength; + + // for compilation messages + DBGCompileMsgInfo *compileMsg; + + MapleStack parentDieStack; + MapleMap idDieMap; + MapleVector abbrevVec; // valid entry starting from index 1 + MapleMap tagAbbrevMap; + + // to be used when derived type references a base type die + MapleMap tyIdxDieIdMap; + MapleMap stridxDieIdMap; + MapleMap funcDefStrIdxDieIdMap; + MapleMap typeDefTyIdxMap; // prevtyIdxtypidx_map + MapleMap pointedPointerMap; + MapleMap> funcLstrIdxDieIdMap; + MapleMap> funcLstrIdxLabIdxMap; + MapleSet strps; +}; + +} // namespace maple + +#endif // MAPLE_IR_INCLUDE_DBG_INFO_H diff --git a/src/mapleall/maple_ir/include/mir_module.h b/src/mapleall/maple_ir/include/mir_module.h index 1de78ffb7db1a852c90b7a4ffe6735b038754871..bf037b5877c4533a7786a2390f61dcb5eeff9325 100644 --- a/src/mapleall/maple_ir/include/mir_module.h +++ b/src/mapleall/maple_ir/include/mir_module.h @@ -548,6 +548,16 @@ class MIRModule { eaSummary[funcNameIdx] = eaCg; } + DebugInfo *GetDbgInfo() { + return dbgInfo; + } + void SetWithDbgInfo(bool v) { + withDbgInfo = v; + } + bool IsWithDbgInfo() { + return withDbgInfo; + } + private: void DumpTypeTreeToCxxHeaderFile(MIRType &ty, std::unordered_set &dumpedClasses) const; @@ -574,6 +584,10 @@ class MIRModule { std::string fileName; TyIdx throwableTyIdx{0}; // a special type that is the base of java exception type. only used for java bool withProfileInfo = false; + + DebugInfo *dbgInfo; + bool withDbgInfo = false; + // for cg in mplt BinaryMplt *binMplt = nullptr; bool inIPA = false; diff --git a/src/mapleall/maple_ir/src/debug_info.cpp b/src/mapleall/maple_ir/src/debug_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..13a139ec3411daa369ccf8c8ab7b65316a1a77da --- /dev/null +++ b/src/mapleall/maple_ir/src/debug_info.cpp @@ -0,0 +1,1384 @@ +/* + * Copyright (C) [2021] Futurewei Technologies, Inc. All rights reverved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the MulanPSL - 2.0 for more details. + */ + +#include "mir_builder.h" +#include "printing.h" +#include "maple_string.h" +#include "namemangler.h" +#include "debug_info.h" +#include "global_tables.h" +#include "mir_type.h" +#include +#include "securec.h" +#include "mpl_logging.h" + +namespace maple { + +extern const char *GetDwTagName(unsigned n); +extern const char *GetDwFormName(unsigned n); +extern const char *GetDwAtName(unsigned n); +extern const char *GetDwOpName(unsigned n); +extern const char *GetDwAteName(unsigned n); +extern const char *GetDwCfaName(unsigned n); +extern DwAte GetAteFromPTY(PrimType pty); + +// DBGDie methods +DBGDie::DBGDie(MIRModule *m, DwTag tag) + : module(m), + tag(tag), + id(m->GetDbgInfo()->GetMaxId()), + withChildren(false), + sibling(nullptr), + firstChild(nullptr), + abbrevId(0), + tyIdx(0), + offset(0), + size(0), + attrVec(m->GetMPAllocator().Adapter()), + subDieVec(m->GetMPAllocator().Adapter()) { + if (module->GetDbgInfo()->GetParentDieSize()) { + parent = module->GetDbgInfo()->GetParentDie(); + } else { + parent = nullptr; + } + m->GetDbgInfo()->SetIdDieMap(m->GetDbgInfo()->GetIncMaxId(), this); + attrVec.clear(); + subDieVec.clear(); +} + +void DBGDie::ResetParentDie() { + module->GetDbgInfo()->ResetParentDie(); +} + +DBGDieAttr *DBGDie::AddAttr(DwAt at, DwForm form, uint64 val) { + // collect strps which need label + if (form == DW_FORM_strp) { + module->GetDbgInfo()->AddStrps(val); + } + DBGDieAttr *attr = module->GetDbgInfo()->CreateAttr(at, form, val); + AddAttr(attr); + return attr; +} + +DBGDieAttr *DBGDie::AddSimpLocAttr(DwAt at, DwForm form, uint64 val) { + DBGExprLoc *p = module->GetMemPool()->New(module, DW_OP_fbreg); + if (val != kDbgDefaultVal) { + p->AddSimpLocOpnd(val); + } + DBGDieAttr *attr = module->GetDbgInfo()->CreateAttr(at, form, reinterpret_cast(p)); + AddAttr(attr); + return attr; +} + +DBGDieAttr *DBGDie::AddGlobalLocAttr(DwAt at, DwForm form, uint64 val) { + DBGExprLoc *p = module->GetMemPool()->New(module, DW_OP_addr); + p->SetGvarStridx(val); + DBGDieAttr *attr = module->GetDbgInfo()->CreateAttr(at, form, reinterpret_cast(p)); + AddAttr(attr); + return attr; +} + +DBGDieAttr *DBGDie::AddFrmBaseAttr(DwAt at, DwForm form, uint64 val) { + DBGExprLoc *p = module->GetMemPool()->New(module, DW_OP_call_frame_cfa); + DBGDieAttr *attr = module->GetDbgInfo()->CreateAttr(at, form, reinterpret_cast(p)); + AddAttr(attr); + return attr; +} + +DBGExprLoc *DBGDie::GetExprLoc() { + for (auto it : attrVec) { + if (it->GetDwAt() == DW_AT_location) { + return it->GetPtr(); + } + } + return nullptr; +} + +bool DBGDie::SetAttr(DwAt attr, uint64 val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetU(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, int val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetI(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, uint32 val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetId(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, int64 val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetJ(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, float val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetF(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, double val) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetD(val); + return true; + } + } + return false; +} + +bool DBGDie::SetAttr(DwAt attr, DBGExprLoc *ptr) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr) { + it->SetPtr(ptr); + return true; + } + } + return false; +} + +void DBGDie::AddAttr(DBGDieAttr *attr) { + for (auto it : attrVec) { + if (it->GetDwAt() == attr->GetDwAt()) { + return; + } + } + attrVec.push_back(attr); +} + +void DBGDie::AddSubVec(DBGDie *die) { + if (!die) return; + for (auto it : subDieVec) { + if (it->GetId() == die->GetId()) { + return; + } + } + subDieVec.push_back(die); + die->parent = this; +} + +// DBGAbbrevEntry methods +DBGAbbrevEntry::DBGAbbrevEntry(MIRModule *m, DBGDie *die) : attrPairs(m->GetMPAllocator().Adapter()) { + tag = die->GetTag(); + abbrevId = 0; + withChildren = die->GetWithChildren(); + for (auto it : die->GetAttrVec()) { + attrPairs.push_back(it->GetDwAt()); + attrPairs.push_back(it->GetDwForm()); + } +} + +bool DBGAbbrevEntry::Equalto(DBGAbbrevEntry *entry) { + if (attrPairs.size() != entry->attrPairs.size()) { + return false; + } + if (withChildren != entry->GetWithChildren()) { + return false; + } + for (uint32 i = 0; i < attrPairs.size(); i++) { + if (attrPairs[i] != entry->attrPairs[i]) { + return false; + } + } + return true; +} + +// DebugInfo methods +void DebugInfo::Init() { + mplSrcIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(module->GetFileName()); + compUnit = module->GetMemPool()->New(module, DW_TAG_compile_unit); + module->SetWithDbgInfo(true); + ResetParentDie(); +} + +void DebugInfo::SetupCU() { + compUnit->SetWithChildren(true); + /* Add the Producer (Compiler) Information */ + const char *producer = "Maple Version 0.5.0 (tags/RELEASE-xxx/final)"; + GStrIdx strIdx = module->GetMIRBuilder()->GetOrCreateStringIndex(producer); + compUnit->AddAttr(DW_AT_producer, DW_FORM_strp, strIdx.GetIdx()); + + /* Source Languate */ + compUnit->AddAttr(DW_AT_language, DW_FORM_data4, DW_LANG_C99); + + /* Add the compiled source file information */ + compUnit->AddAttr(DW_AT_name, DW_FORM_strp, mplSrcIdx.GetIdx()); + strIdx = module->GetMIRBuilder()->GetOrCreateStringIndex("/to/be/done/current/path"); + compUnit->AddAttr(DW_AT_comp_dir, DW_FORM_strp, strIdx.GetIdx()); + + compUnit->AddAttr(DW_AT_low_pc, DW_FORM_addr, kDbgDefaultVal); + compUnit->AddAttr(DW_AT_high_pc, DW_FORM_data8, kDbgDefaultVal); + + compUnit->AddAttr(DW_AT_stmt_list, DW_FORM_sec_offset, kDbgDefaultVal); +} + +void DebugInfo::BuildAliasDIEs() { + for (auto it : funcLstrIdxDieIdMap) { + MIRFunction *func = it.first; + for (std::pair i : func->GetAliasVarMap()) { + DBGDie *die = GetLocalDie(func, i.second.memPoolStrIdx); + // this local mpl variable does not exist because it is optimized away + // by register renameing. please use mplme -O1 instead of -O2 + if (!die) { + continue; + } + DBGDie *aliasdie = module->GetMemPool()->New(module, DW_TAG_variable); + + // clone attributes, note DBGExprLoc pointer is copied as well + // so the fboffset are the same as aliased maple variable + for (auto attr : die->GetAttrVec()) { + aliasdie->AddAttr(attr->GetDwAt(), attr->GetDwForm(), attr->GetU()); + } + // update name with aliased src variable name + aliasdie->SetAttr(DW_AT_name, i.first.GetIdx()); + aliasdie->SetParent(die->GetParent()); + + // add alias var name to debug_str section + strps.insert(i.first.GetIdx()); + + uint32 funcdieid = stridxDieIdMap[func->GetNameStrIdx().GetIdx()]; + DBGDie *funcdie = idDieMap[funcdieid]; + funcdie->AddSubVec(aliasdie); + } + } +} + +void DebugInfo::Finish() { + SetupCU(); + FillTypeAttrWithDieId(); + BuildAliasDIEs(); + // build tree from root DIE compUnit + BuildDieTree(); + BuildAbbrev(); + ComputeSizeAndOffsets(); +} + +void DebugInfo::BuildDebugInfo() { + ASSERT(module->GetDbgInfo(), "null dbgInfo"); + + Init(); + + // containner types + for (auto it : module->GetTypeNameTab()->GetGStrIdxToTyIdxMap()) { + GStrIdx strIdx = it.first; + TyIdx tyIdx = it.second; + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx.GetIdx()); + + switch (type->GetKind()) { + case kTypeClass: + case kTypeClassIncomplete: + case kTypeInterface: + case kTypeInterfaceIncomplete: + case kTypeStruct: + case kTypeStructIncomplete: + case kTypeUnion: + { + (void) GetOrCreateStructTypeDie(type); + break; + } + default: + std::cout << "named type " << GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx).c_str() << "\n"; + break; + } + } + + // setup debug info for functions + for (auto func : GlobalTables::GetFunctionTable().GetFuncTable()) { + // the first one in funcTable is nullptr + if (!func) { + continue; + } + // function decl + if (stridxDieIdMap.find(func->GetNameStrIdx().GetIdx()) == stridxDieIdMap.end()) { + DBGDie *fdie = GetOrCreateFuncDeclDie(func, 0); + if (!func->GetClassTyIdx().GetIdx() && func->GetBody()) { + compUnit->AddSubVec(fdie); + } + } + // function def + if (funcDefStrIdxDieIdMap.find(func->GetNameStrIdx().GetIdx()) == funcDefStrIdxDieIdMap.end()) { + DBGDie *fdie = GetOrCreateFuncDefDie(func, 0); + if (!func->GetClassTyIdx().GetIdx() && func->GetBody()) { + compUnit->AddSubVec(fdie); + } + } + } + + // finalize debug info + Finish(); +} + +DBGDieAttr *DebugInfo::CreateAttr(DwAt at, DwForm form, uint64 val) { + DBGDieAttr *attr = module->GetMemPool()->New(kDwAt); + attr->SetDwAt(at); + attr->SetDwForm(form); + attr->SetU(val); + return attr; +} + +void DebugInfo::SetLocalDie(MIRFunction *func, GStrIdx strIdx, const DBGDie *die) { + (funcLstrIdxDieIdMap[func])[strIdx.GetIdx()] = die->GetId(); +} + +DBGDie *DebugInfo::GetLocalDie(MIRFunction *func, GStrIdx strIdx) { + uint32 id = (funcLstrIdxDieIdMap[func])[strIdx.GetIdx()]; + return idDieMap[id]; +} + +void DebugInfo::SetLocalDie(GStrIdx strIdx, const DBGDie *die) { + (funcLstrIdxDieIdMap[module->CurFunction()])[strIdx.GetIdx()] = die->GetId(); +} + +DBGDie *DebugInfo::GetLocalDie(GStrIdx strIdx) { + uint32 id = (funcLstrIdxDieIdMap[module->CurFunction()])[strIdx.GetIdx()]; + return idDieMap[id]; +} + +void DebugInfo::SetLabelIdx(MIRFunction *func, GStrIdx strIdx, LabelIdx labidx) { + (funcLstrIdxLabIdxMap[func])[strIdx.GetIdx()] = labidx; +} + +LabelIdx DebugInfo::GetLabelIdx(MIRFunction *func, GStrIdx strIdx) { + LabelIdx labidx = (funcLstrIdxLabIdxMap[func])[strIdx.GetIdx()]; + return labidx; +} + +void DebugInfo::SetLabelIdx(GStrIdx strIdx, LabelIdx labidx) { + (funcLstrIdxLabIdxMap[module->CurFunction()])[strIdx.GetIdx()] = labidx; +} + +LabelIdx DebugInfo::GetLabelIdx(GStrIdx strIdx) { + LabelIdx labidx = (funcLstrIdxLabIdxMap[module->CurFunction()])[strIdx.GetIdx()]; + return labidx; +} + +DBGDie *DebugInfo::CreateFormalParaDie(MIRFunction *func, MIRType *type, MIRSymbol *sym) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_formal_parameter); + + (void)GetOrCreateTypeDie(type); + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + + /* var Name */ + if (sym) { + die->AddAttr(DW_AT_name, DW_FORM_strp, sym->GetNameStrIdx().GetIdx()); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, sym->GetSrcPosition().FileNum()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, sym->GetSrcPosition().LineNum()); + die->AddAttr(DW_AT_decl_column, DW_FORM_data4, sym->GetSrcPosition().Column()); + die->AddSimpLocAttr(DW_AT_location, DW_FORM_exprloc, kDbgDefaultVal); + SetLocalDie(func, sym->GetNameStrIdx(), die); + } + return die; +} + +DBGDie *DebugInfo::GetOrCreateLabelDie(LabelIdx labid) { + MIRFunction *func = module->CurFunction(); + CHECK(labid < func->GetLabelTab()->GetLabelTableSize(), "index out of range in DebugInfo::GetOrCreateLabelDie"); + GStrIdx strid = func->GetLabelTab()->GetSymbolFromStIdx(labid); + if ((funcLstrIdxDieIdMap[func]).size() && + (funcLstrIdxDieIdMap[func]).find(strid.GetIdx()) != (funcLstrIdxDieIdMap[func]).end()) { + return GetLocalDie(strid); + } + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_label); + die->AddAttr(DW_AT_name, DW_FORM_strp, strid.GetIdx()); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, mplSrcIdx.GetIdx()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, lexer->GetLineNum()); + die->AddAttr(DW_AT_low_pc, DW_FORM_addr, kDbgDefaultVal); + GetParentDie()->AddSubVec(die); + SetLocalDie(strid, die); + SetLabelIdx(strid, labid); + return die; +} + +DBGDie *DebugInfo::CreateVarDie(MIRSymbol *sym, uint32 lnum) { + // filter vtab + if (sym->GetName().find(VTAB_PREFIX_STR) == 0) { + return nullptr; + } + + if (sym->GetName().find(GCTIB_PREFIX_STR) == 0) { + return nullptr; + } + + if (sym->GetStorageClass() == kScFormal) { + return nullptr; + } + + bool isLocal = sym->IsLocal(); + + if (isLocal) { + MIRFunction *func = module->CurFunction(); + if ((funcLstrIdxDieIdMap[func]).size() && + (funcLstrIdxDieIdMap[func]).find(sym->GetNameStrIdx().GetIdx()) != (funcLstrIdxDieIdMap[func]).end()) { + return GetLocalDie(sym->GetNameStrIdx()); + } + } else { + if (stridxDieIdMap.find(sym->GetNameStrIdx().GetIdx()) != stridxDieIdMap.end()) { + uint32 id = stridxDieIdMap[sym->GetNameStrIdx().GetIdx()]; + return idDieMap[id]; + } + } + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_variable); + + /* var Name */ + die->AddAttr(DW_AT_name, DW_FORM_strp, sym->GetNameStrIdx().GetIdx()); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, sym->GetSrcPosition().FileNum()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, sym->GetSrcPosition().LineNum()); + die->AddAttr(DW_AT_decl_column, DW_FORM_data4, sym->GetSrcPosition().Column()); + + if (isLocal) { + die->AddSimpLocAttr(DW_AT_location, DW_FORM_exprloc, kDbgDefaultVal); + } else { + // global var just use its name as address in .s + uint64 idx = sym->GetNameStrIdx().GetIdx(); + if ((sym->IsReflectionClassInfo() && !sym->IsReflectionArrayClassInfo()) || sym->IsStatic()) { + std::string ptrName = std::string(namemangler::kPtrPrefixStr) + sym->GetName(); + idx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(ptrName).GetIdx(); + } + die->AddGlobalLocAttr(DW_AT_location, DW_FORM_exprloc, idx); + } + + MIRType *type = sym->GetType(); + (void)GetOrCreateTypeDie(type); + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + + GetParentDie()->AddSubVec(die); + if (isLocal) { + SetLocalDie(sym->GetNameStrIdx(), die); + } else { + stridxDieIdMap[sym->GetNameStrIdx().GetIdx()] = die->GetId(); + } + return die; +} + +DBGDie *DebugInfo::GetOrCreateFuncDeclDie(MIRFunction *func, uint32 lnum) { + uint32 funcnameidx = func->GetNameStrIdx().GetIdx(); + if (stridxDieIdMap.find(funcnameidx) != stridxDieIdMap.end()) { + uint32 id = stridxDieIdMap[funcnameidx]; + return idDieMap[id]; + } + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_subprogram); + stridxDieIdMap[funcnameidx] = die->GetId(); + + die->AddAttr(DW_AT_external, DW_FORM_flag_present, 1); + + // Function Name + MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(func->GetStIdx().Idx()); + + die->AddAttr(DW_AT_name, DW_FORM_strp, funcnameidx); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, sym->GetSrcPosition().FileNum()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, sym->GetSrcPosition().LineNum()); + die->AddAttr(DW_AT_decl_column, DW_FORM_data4, sym->GetSrcPosition().Column()); + + // Attributes for DW_AT_accessibility + uint32 access = 0; + if (func->IsPublic()) { + access = DW_ACCESS_public; + } else if (func->IsPrivate()) { + access = DW_ACCESS_private; + } else if (func->IsProtected()) { + access = DW_ACCESS_protected; + } + if (access) { + die->AddAttr(DW_AT_accessibility, DW_FORM_data4, access); + } + + die->AddAttr(DW_AT_GNU_all_tail_call_sites, DW_FORM_flag_present, kDbgDefaultVal); + + PushParentDie(die); + + // formal parameter + for (uint32 i = 0; i < func->GetFormalCount(); i++) { + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(func->GetFormalDefAt(i).formalTyIdx); + DBGDie *param = CreateFormalParaDie(func, type, nullptr); + die->AddSubVec(param); + } + + PopParentDie(); + + return die; +} + +bool LIsCompilerGenerated(const MIRFunction *func) { + return ((func->GetName().c_str())[0] != 'L'); +} + +DBGDie *DebugInfo::GetOrCreateFuncDefDie(MIRFunction *func, uint32 lnum) { + uint32 funcnameidx = func->GetNameStrIdx().GetIdx(); + if (funcDefStrIdxDieIdMap.find(funcnameidx) != funcDefStrIdxDieIdMap.end()) { + uint32 id = funcDefStrIdxDieIdMap[funcnameidx]; + return idDieMap[id]; + } + + DBGDie *funcdecldie = GetOrCreateFuncDeclDie(func, lnum); + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_subprogram); + // update funcDefStrIdxDieIdMap and leave stridxDieIdMap for the func decl + funcDefStrIdxDieIdMap[funcnameidx] = die->GetId(); + + die->AddAttr(DW_AT_specification, DW_FORM_ref4, funcdecldie->GetId()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, lnum); + die->AddAttr(DW_AT_low_pc, DW_FORM_addr, kDbgDefaultVal); + die->AddAttr(DW_AT_high_pc, DW_FORM_data8, kDbgDefaultVal); + die->AddFrmBaseAttr(DW_AT_frame_base, DW_FORM_exprloc, kDbgDefaultVal); + if (!func->IsStatic() && !LIsCompilerGenerated(func)) { + die->AddAttr(DW_AT_object_pointer, DW_FORM_ref4, kDbgDefaultVal); + } + die->AddAttr(DW_AT_GNU_all_tail_call_sites, DW_FORM_flag_present, kDbgDefaultVal); + + PushParentDie(die); + + // formal parameter + for (uint32 i = 0; i < func->GetFormalCount(); i++) { + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(func->GetFormalDefAt(i).formalTyIdx); + DBGDie *pdie = CreateFormalParaDie(func, type, func->GetFormalDefAt(i).formalSym); + die->AddSubVec(pdie); + } + + if (func->GetSymTab()) { + // local variables, start from 1 + for (uint32 i = 1; i < func->GetSymTab()->GetSymbolTableSize(); i++) { + MIRSymbol *var = func->GetSymTab()->GetSymbolFromStIdx(i); + DBGDie *vdie = CreateVarDie(var, 0); + die->AddSubVec(vdie); + } + } + + PopParentDie(); + + return die; +} + +DBGDie *DebugInfo::GetOrCreatePrimTypeDie(PrimType pty) { + uint32 tid = static_cast(pty); + if (tyIdxDieIdMap.find(tid) != tyIdxDieIdMap.end()) { + uint32 id = tyIdxDieIdMap[tid]; + return idDieMap[id]; + } + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_base_type); + die->SetTyIdx(static_cast(pty)); + + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, GetPrimTypeSize(pty)); + die->AddAttr(DW_AT_encoding, DW_FORM_data4, GetAteFromPTY(pty)); + + compUnit->AddSubVec(die); + tyIdxDieIdMap[static_cast(pty)] = die->GetId(); + return die; +} + +DBGDie *DebugInfo::CreatePointedFuncTypeDie(MIRFuncType *ftype) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_subroutine_type); + + die->AddAttr(DW_AT_prototyped, DW_FORM_data4, (int)(ftype->GetParamTypeList().size()>0)); + MIRType *rtype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ftype->GetRetTyIdx()); + (void)GetOrCreateTypeDie(rtype); + die->AddAttr(DW_AT_type, DW_FORM_ref4, ftype->GetRetTyIdx().GetIdx()); + + compUnit->AddSubVec(die); + + for (uint32 i = 0; i < ftype->GetParamTypeList().size(); i++) { + DBGDie *paramdie = module->GetMemPool()->New(module, DW_TAG_formal_parameter); + MIRType *ptype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ftype->GetNthParamType(i)); + (void)GetOrCreateTypeDie(ptype); + paramdie->AddAttr(DW_AT_type, DW_FORM_ref4, ftype->GetNthParamType(i).GetIdx()); + die->AddSubVec(paramdie); + } + + tyIdxDieIdMap[ftype->GetTypeIndex().GetIdx()] = die->GetId(); + return die; +} + +DBGDie *DebugInfo::GetOrCreateTypeDie(MIRType *type) { + if (!type) { + return nullptr; + } + + uint32 tid = type->GetTypeIndex().GetIdx(); + if (tyIdxDieIdMap.find(tid) != tyIdxDieIdMap.end()) { + uint32 id = tyIdxDieIdMap[tid]; + return idDieMap[id]; + } + + uint32 sid = type->GetNameStrIdx().GetIdx(); + if (sid) + if (stridxDieIdMap.find(sid) != stridxDieIdMap.end()) { + uint32 id = stridxDieIdMap[sid]; + return idDieMap[id]; + } + + if (type && type->GetTypeIndex() == static_cast(type->GetPrimType())) { + return GetOrCreatePrimTypeDie(type->GetPrimType()); + } + + DBGDie *die = nullptr; + switch (type->GetKind()) { + case kTypePointer: { + MIRPtrType *ptype = static_cast(type); + die = GetOrCreatePointTypeDie(ptype); + break; + } + case kTypeFunction: { + MIRFuncType *ftype = static_cast(type); + die = CreatePointedFuncTypeDie(ftype); + break; + } + case kTypeArray: + case kTypeFArray: + case kTypeJArray: { + MIRArrayType *atype = static_cast(type); + die = GetOrCreateArrayTypeDie(atype); + break; + } + case kTypeUnion: + case kTypeStruct: + case kTypeStructIncomplete: + case kTypeClass: + case kTypeClassIncomplete: + case kTypeInterface: + case kTypeInterfaceIncomplete: { + die = GetOrCreateStructTypeDie(type); + break; + } + case kTypeBitField: + break; + default: + CHECK_FATAL(false, "TODO: support type"); + break; + } + + return die; +} + +DBGDie *DebugInfo::GetOrCreatePointTypeDie(const MIRPtrType *ptrtype) { + uint32 tid = ptrtype->GetTypeIndex().GetIdx(); + if (tyIdxDieIdMap.find(tid) != tyIdxDieIdMap.end()) { + uint32 id = tyIdxDieIdMap[tid]; + return idDieMap[id]; + } + + MIRType *type = ptrtype->GetPointedType(); + // for <* void> + if (type && + (type->GetPrimType() == PTY_void || type->GetKind() == kTypeFunction)) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_pointer_type); + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, 8); + if (type->GetKind() == kTypeFunction) { + DBGDie *pdie = GetOrCreateTypeDie(type); + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + tyIdxDieIdMap[type->GetTypeIndex().GetIdx()] = pdie->GetId(); + } + tyIdxDieIdMap[ptrtype->GetTypeIndex().GetIdx()] = die->GetId(); + compUnit->AddSubVec(die); + return die; + } + + (void)GetOrCreateTypeDie(type); + if (typeDefTyIdxMap.find(type->GetTypeIndex().GetIdx()) != typeDefTyIdxMap.end()) { + uint32 tid = typeDefTyIdxMap[type->GetTypeIndex().GetIdx()]; + if (pointedPointerMap.find(tid) != pointedPointerMap.end()) { + uint32 tyid = pointedPointerMap[tid]; + if (tyIdxDieIdMap.find(tyid) != tyIdxDieIdMap.end()) { + uint32 dieid = tyIdxDieIdMap[tyid]; + DBGDie *die = idDieMap[dieid]; + return die; + } + } + } + + // update incomplete type from stridxDieIdMap to tyIdxDieIdMap + MIRStructType *stype = dynamic_cast(type); + if (stype && stype->IsIncomplete()) { + uint32 sid = stype->GetNameStrIdx().GetIdx(); + if (stridxDieIdMap.find(sid) != stridxDieIdMap.end()) { + uint32 dieid = stridxDieIdMap[sid]; + if (dieid) { + tyIdxDieIdMap[stype->GetTypeIndex().GetIdx()] = dieid; + } + } + } + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_pointer_type); + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, 8); + // fill with type idx instead of typedie->id to avoid nullptr typedie of + // forward reference of class types + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + tyIdxDieIdMap[ptrtype->GetTypeIndex().GetIdx()] = die->GetId(); + + compUnit->AddSubVec(die); + + return die; +} + +DBGDie *DebugInfo::GetOrCreateArrayTypeDie(const MIRArrayType *arraytype) { + uint32 tid = arraytype->GetTypeIndex().GetIdx(); + if (tyIdxDieIdMap.find(tid) != tyIdxDieIdMap.end()) { + uint32 id = tyIdxDieIdMap[tid]; + return idDieMap[id]; + } + + MIRType *type = arraytype->GetElemType(); + (void)GetOrCreateTypeDie(type); + + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_array_type); + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, 8); + // fill with type idx instead of typedie->id to avoid nullptr typedie of + // forward reference of class types + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + tyIdxDieIdMap[arraytype->GetTypeIndex().GetIdx()] = die->GetId(); + + compUnit->AddSubVec(die); + + // maple uses array of 1D array to represent 2D array + // so only one DW_TAG_subrange_type entry is needed + DBGDie *rangedie = module->GetMemPool()->New(module, DW_TAG_subrange_type); + PrimType prmtype = PTY_u32; + (void)GetOrCreatePrimTypeDie(prmtype); + rangedie->AddAttr(DW_AT_type, DW_FORM_ref4, PTY_u32); + rangedie->AddAttr(DW_AT_upper_bound, DW_FORM_data4, arraytype->GetSizeArrayItem(0)); + + die->AddSubVec(rangedie); + + return die; +} + +DBGDie *DebugInfo::CreateFieldDie(maple::FieldPair pair, uint32 lnum) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_member); + + die->AddAttr(DW_AT_name, DW_FORM_strp, pair.first.GetIdx()); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, mplSrcIdx.GetIdx()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, lnum); + + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pair.second.first); + (void)GetOrCreateTypeDie(type); + // fill with type idx instead of typedie->id to avoid nullptr typedie of + // forward reference of class types + die->AddAttr(DW_AT_type, DW_FORM_ref4, type->GetTypeIndex().GetIdx()); + + die->AddAttr(DW_AT_data_member_location, DW_FORM_data4, kDbgDefaultVal); + + return die; +} + +DBGDie *DebugInfo::CreateBitfieldDie(MIRBitFieldType *type, GStrIdx sidx) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_member); + + die->AddAttr(DW_AT_name, DW_FORM_strp, sidx.GetIdx()); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, mplSrcIdx.GetIdx()); + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, 0); + + MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(type->GetPrimType()); + (void)GetOrCreateTypeDie(ty); + die->AddAttr(DW_AT_type, DW_FORM_ref4, ty->GetTypeIndex().GetIdx()); + + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, GetPrimTypeSize(type->GetPrimType())); + die->AddAttr(DW_AT_bit_size, DW_FORM_data4, type->GetFieldSize()); + die->AddAttr(DW_AT_bit_offset, DW_FORM_data4, GetPrimTypeSize(type->GetPrimType())*8-type->GetFieldSize()); + + die->AddAttr(DW_AT_data_member_location, DW_FORM_data4, 0); + + return die; +} + +DBGDie *DebugInfo::GetOrCreateStructTypeDie(const MIRType *type) { + ASSERT(type, "null struture type"); + GStrIdx strIdx = type->GetNameStrIdx(); + ASSERT(strIdx.GetIdx(), "struture type missing name"); + + if (tyIdxDieIdMap.find(type->GetTypeIndex().GetIdx()) != tyIdxDieIdMap.end()) { + uint32 id = tyIdxDieIdMap[type->GetTypeIndex().GetIdx()]; + return idDieMap[id]; + } + + DBGDie *die = nullptr; + switch (type->GetKind()) { + case kTypeClass: + case kTypeClassIncomplete: + { + const MIRClassType *classtype = static_cast(type); + die = CreateClassTypeDie(strIdx, classtype); + break; + } + case kTypeInterface: + case kTypeInterfaceIncomplete: + { + const MIRInterfaceType *interfacetype = static_cast(type); + die = CreateInterfaceTypeDie(strIdx, interfacetype); + break; + } + case kTypeStruct: + case kTypeStructIncomplete: + case kTypeUnion: + { + const MIRStructType *stype = static_cast(type); + die = CreateStructTypeDie(strIdx, stype, false); + break; + } + default: + std::cout << "named type " << GlobalTables::GetStrTable().GetStringFromStrIdx(strIdx).c_str() << "\n"; + break; + } + + GlobalTables::GetTypeNameTable().SetGStrIdxToTyIdx(strIdx, type->GetTypeIndex()); + return die; +} + +// shared between struct and union +DBGDie *DebugInfo::CreateStructTypeDie(GStrIdx strIdx, const MIRStructType *structtype, bool update) { + DBGDie *die = nullptr; + + if (update) { + uint32 id = tyIdxDieIdMap[structtype->GetTypeIndex().GetIdx()]; + die = idDieMap[id]; + ASSERT(die, "update type die not exist"); + } else { + DwTag tag = structtype->GetKind() == kTypeStruct ? DW_TAG_structure_type : DW_TAG_union_type; + die = module->GetMemPool()->New(module, tag); + tyIdxDieIdMap[structtype->GetTypeIndex().GetIdx()] = die->GetId(); + } + + if (strIdx.GetIdx()) { + stridxDieIdMap[strIdx.GetIdx()] = die->GetId(); + } + + compUnit->AddSubVec(die); + + die->AddAttr(DW_AT_decl_line, DW_FORM_data4, 8888); + die->AddAttr(DW_AT_name, DW_FORM_strp, strIdx.GetIdx()); + die->AddAttr(DW_AT_byte_size, DW_FORM_data4, kDbgDefaultVal); + die->AddAttr(DW_AT_decl_file, DW_FORM_data4, mplSrcIdx.GetIdx()); + + PushParentDie(die); + + // fields + for (int64 i = 0; i < structtype->GetFieldsSize(); i++) { + MIRType *ety = structtype->GetElemType(i); + FieldPair fp = structtype->GetFieldsElemt(i); + if (MIRBitFieldType *bfty = dynamic_cast(ety)) { + DBGDie *bfdie = CreateBitfieldDie(bfty, fp.first); + die->AddSubVec(bfdie); + } else { + DBGDie *fdie = CreateFieldDie(fp, 0); + die->AddSubVec(fdie); + } + } + + // parentFields + for (int64 i = 0; i < structtype->GetParentFieldsSize(); i++) { + FieldPair fp = structtype->GetParentFieldsElemt(i); + DBGDie *fdie = CreateFieldDie(fp, 0); + die->AddSubVec(fdie); + } + + // member functions decl + for (auto fp : structtype->GetMethods()) { + MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(fp.first.Idx()); + ASSERT(symbol && symbol->GetSKind() == kStFunc, "member function symbol not exist"); + MIRFunction *func = symbol->GetValue().mirFunc; + ASSERT(func, "member function not exist"); + DBGDie *fdie = GetOrCreateFuncDeclDie(func, 0); + die->AddSubVec(fdie); + } + + PopParentDie(); + + // member functions defination, these die are global + for (auto fp : structtype->GetMethods()) { + MIRSymbol *symbol = GlobalTables::GetGsymTable().GetSymbolFromStidx(fp.first.Idx()); + ASSERT(symbol && symbol->GetSKind() == kStFunc, "member function symbol not exist"); + MIRFunction *func = symbol->GetValue().mirFunc; + if (!func->GetBody()) { + continue; + } + ASSERT(func, "member function not exist"); + DBGDie *fdie = GetOrCreateFuncDefDie(func, 0); + compUnit->AddSubVec(fdie); + } + + return die; +} + +DBGDie *DebugInfo::CreateClassTypeDie(GStrIdx strIdx, const MIRClassType *classtype) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_class_type); + + PushParentDie(die); + + // parent + uint32 ptid = classtype->GetParentTyIdx().GetIdx(); + if (ptid) { + MIRType *parenttype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(classtype->GetParentTyIdx()); + DBGDie *parentdie = GetOrCreateTypeDie(parenttype); + if (parentdie) { + parentdie = module->GetMemPool()->New(module, DW_TAG_inheritance); + parentdie->AddAttr(DW_AT_name, DW_FORM_strp, parenttype->GetNameStrIdx().GetIdx()); + parentdie->AddAttr(DW_AT_type, DW_FORM_ref4, ptid); + + // set to DW_ACCESS_public for now + parentdie->AddAttr(DW_AT_accessibility, DW_FORM_data4, DW_ACCESS_public); + die->AddSubVec(parentdie); + } + } + + PopParentDie(); + + // update common fields + tyIdxDieIdMap[classtype->GetTypeIndex().GetIdx()] = die->GetId(); + DBGDie *die1 = CreateStructTypeDie(strIdx, classtype, true); + ASSERT(die == die1, "ClassTypeDie update wrong die"); + + return die1; +} + +DBGDie *DebugInfo::CreateInterfaceTypeDie(GStrIdx strIdx, const MIRInterfaceType *interfacetype) { + DBGDie *die = module->GetMemPool()->New(module, DW_TAG_interface_type); + + PushParentDie(die); + + // parents + for (auto it : interfacetype->GetParentsTyIdx()) { + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(it); + DBGDie *parentdie = GetOrCreateTypeDie(type); + if (parentdie) { + continue; + } + parentdie = module->GetMemPool()->New(module, DW_TAG_inheritance); + parentdie->AddAttr(DW_AT_name, DW_FORM_strp, type->GetNameStrIdx().GetIdx()); + parentdie->AddAttr(DW_AT_type, DW_FORM_ref4, it.GetIdx()); + parentdie->AddAttr(DW_AT_data_member_location, DW_FORM_data4, kDbgDefaultVal); + + // set to DW_ACCESS_public for now + parentdie->AddAttr(DW_AT_accessibility, DW_FORM_data4, DW_ACCESS_public); + die->AddSubVec(parentdie); + } + + PopParentDie(); + + // update common fields + tyIdxDieIdMap[interfacetype->GetTypeIndex().GetIdx()] = die->GetId(); + DBGDie *die1 = CreateStructTypeDie(strIdx, interfacetype, true); + ASSERT(die == die1, "InterfaceTypeDie update wrong die"); + + return die1; +} + +uint32 DebugInfo::GetAbbrevId(DBGAbbrevEntryVec *vec, DBGAbbrevEntry *entry) { + for (auto it : vec->GetEntryvec()) { + if (it->Equalto(entry)) { + return it->GetAbbrevId();; + } + } + return 0; +} + +void DebugInfo::BuildAbbrev() { + uint32 abbrevid = 1; + for (uint32 i = 1; i < maxId; i++) { + DBGDie *die = idDieMap[i]; + DBGAbbrevEntry *entry = module->GetMemPool()->New(module, die); + + if (!tagAbbrevMap[die->GetTag()]) { + tagAbbrevMap[die->GetTag()] = module->GetMemPool()->New(module, die->GetTag()); + } + + uint32 id = GetAbbrevId(tagAbbrevMap[die->GetTag()], entry); + if (id) { + // using existing abbrev id + die->SetAbbrevId(id); + // free(entry); + } else { + // add entry to vector + entry->SetAbbrevId(abbrevid++); + tagAbbrevMap[die->GetTag()]->GetEntryvec().push_back(entry); + abbrevVec.push_back(entry); + // update abbrevid in die + die->SetAbbrevId(entry->GetAbbrevId()); + } + } + for (uint32 i = 1; i < maxId; i++) { + DBGDie *die = idDieMap[i]; + if (die->GetAbbrevId() == 0) { + std::cout << "0 abbrevId i = " << i << " die->id = " << die->GetId() << std::endl; + } + } +} + +void DebugInfo::BuildDieTree() { + for (auto it : idDieMap) { + if (!it.first) { + continue; + } + DBGDie *die = it.second; + uint32 size = die->GetSubDieVecSize(); + die->SetWithChildren(size > 0); + if (size) { + die->SetFirstChild(die->GetSubDieVecAt(0)); + for (uint32 i = 0; i < size - 1; i++) { + DBGDie *it = die->GetSubDieVecAt(i); + DBGDie *it1 = die->GetSubDieVecAt(i + 1); + if (it->GetSubDieVecSize()) { + it->SetSibling(it1); + it->AddAttr(DW_AT_sibling, DW_FORM_ref4, it1->GetId()); + } + } + } + } +} + +void DebugInfo::FillTypeAttrWithDieId() { + for (auto it : idDieMap) { + DBGDie *die = it.second; + for (auto at : die->GetAttrVec()) { + if (at->GetDwAt() == DW_AT_type) { + uint32 tid = at->GetId(); + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(tid)); + if (type) { + uint32 dieid = tyIdxDieIdMap[tid]; + if (dieid) { + at->SetId(dieid); + } else { + LogInfo::MapleLogger() << "dieid not found, typeKind = " << type->GetKind() << " primType = " << type->GetPrimType() + << " nameStrIdx = " << type->GetNameStrIdx().GetIdx() << std::endl; + } + } else { + LogInfo::MapleLogger() << "type not found, tid = " << tid << std::endl; + } + break; + } + } + } +} + +DBGDie *DebugInfo::GetDie(const MIRFunction *func) { + uint32 id = stridxDieIdMap[func->GetNameStrIdx().GetIdx()]; + if (id) { + return idDieMap[id]; + } + return nullptr; +} + +// Methods for calculating Offset and Size of DW_AT_xxx +uint32 DBGDieAttr::SizeOf(DBGDieAttr *attr) { + DwForm form = attr->dwForm; + switch (form) { + // case DW_FORM_implicitconst: + case DW_FORM_flag_present: + return 0; // Not handled yet. + case DW_FORM_flag: + case DW_FORM_ref1: + case DW_FORM_data1: + return sizeof(int8); + case DW_FORM_ref2: + case DW_FORM_data2: + return sizeof(int16); + case DW_FORM_ref4: + case DW_FORM_data4: + return sizeof(int32); + case DW_FORM_ref8: + case DW_FORM_ref_sig8: + case DW_FORM_data8: + return sizeof(int64); + case DW_FORM_addr: + return sizeof(int64); + case DW_FORM_sec_offset: + case DW_FORM_ref_addr: + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + // case DW_FORM_codeLinestrp: + // case DW_FORM_strp_sup: + // case DW_FORM_ref_sup: + return 4; // DWARF32, 8 if DWARF64 + + case DW_FORM_string: { + GStrIdx stridx(attr->value.id); + const std::string &str = GlobalTables::GetStrTable().GetStringFromStrIdx(stridx); + return str.length() + 1 /* terminal null byte */; + } + case DW_FORM_exprloc: { + DBGExprLoc *ptr = attr->value.ptr; + CHECK_FATAL(ptr != (DBGExprLoc *)0xdeadbeef, "wrong ptr"); + switch (ptr->GetOp()) { + case DW_OP_call_frame_cfa: + return 2; // size 1 byte + DW_OP_call_frame_cfa 1 byte + case DW_OP_fbreg: { + // DW_OP_fbreg 1 byte + uint32 size = 1 + namemangler::GetSleb128Size(ptr->GetFboffset()); + return size + namemangler::GetUleb128Size(size); + } + case DW_OP_addr: { + return namemangler::GetUleb128Size(9) + 9; + } + default: + return 4; + } + } + default: + CHECK_FATAL(maple::GetDwFormName(form) != nullptr, + "GetDwFormName return null in DebugInfo::FillTypeAttrWithDieId"); + LogInfo::MapleLogger() << "unhandled SizeOf: " << maple::GetDwFormName(form) << std::endl; + return 0; + } +} + +void DebugInfo::ComputeSizeAndOffsets() { + // CU-relative offset is reset to 0 here. + uint32 cuOffset = sizeof(int32_t) // Length of Unit Info + + sizeof(int16) // DWARF version number : 0x0004 + + sizeof(int32) // Offset into Abbrev. Section : 0x0000 + + sizeof(int8); // Pointer Size (in bytes) : 0x08 + + // After returning from this function, the length value is the size + // of the .debug_info section + ComputeSizeAndOffset(compUnit, cuOffset); + debugInfoLength = cuOffset - sizeof(int32_t); +} + +// Compute the size and offset of a DIE. The Offset is relative to start of the CU. +// It returns the offset after laying out the DIE. +void DebugInfo::ComputeSizeAndOffset(DBGDie *die, uint32 &cuOffset) { + uint32 cuOffsetOrg = cuOffset; + die->SetOffset(cuOffset); + + // Add the byte size of the abbreviation code + cuOffset += static_cast(namemangler::GetUleb128Size(uint64_t(die->GetAbbrevId()))); + + // Add the byte size of all the DIE attributes. + for (const auto &attr : die->GetAttrVec()) { + cuOffset += attr->SizeOf(attr); + } + + die->SetSize(cuOffset - cuOffsetOrg); + + // Let the children compute their offsets. + if (die->GetWithChildren()) { + uint32 size = die->GetSubDieVecSize(); + + for (uint32 i = 0; i < size; i++) { + DBGDie *childDie = die->GetSubDieVecAt(i); + ComputeSizeAndOffset(childDie, cuOffset); + } + + // Each child chain is terminated with a zero byte, adjust the offset. + cuOffset += sizeof(int8); + } +} + +/////////////////////////////// +// Dumps +/////////////////////////////// +void DebugInfo::Dump(int indent) { + LogInfo::MapleLogger() << "\n" << std::endl; + LogInfo::MapleLogger() << "maple_debug_information {" + << " Length: " << HEX(debugInfoLength) << std::endl; + compUnit->Dump(indent + 1); + LogInfo::MapleLogger() << "}\n" << std::endl; + LogInfo::MapleLogger() << "maple_debug_abbrev {" << std::endl; + for (uint32 i = 1; i < abbrevVec.size(); i++) { + abbrevVec[i]->Dump(indent + 1); + } + LogInfo::MapleLogger() << "}" << std::endl; + return; +} + +void DBGExprLoc::Dump() { + LogInfo::MapleLogger() << " " << HEX(GetOp()); + for (auto it : simpLoc->GetOpnd()) { + LogInfo::MapleLogger() << " " << HEX(it); + } +} + +void DBGDieAttr::Dump(int indent) { + PrintIndentation(indent); + CHECK_FATAL(GetDwFormName(dwForm) && GetDwAtName(dwAttr), "null ptr check"); + LogInfo::MapleLogger() << GetDwAtName(dwAttr) << " " << GetDwFormName(dwForm); + if (dwForm == DW_FORM_string || dwForm == DW_FORM_strp) { + GStrIdx idx(value.id); + LogInfo::MapleLogger() << " 0x" << std::hex << value.u << std::dec; + LogInfo::MapleLogger() << " \"" << GlobalTables::GetStrTable().GetStringFromStrIdx(idx).c_str() << "\""; + } else if (dwForm == DW_FORM_ref4) { + LogInfo::MapleLogger() << " <" << HEX(value.id) << ">"; + } else if (dwAttr == DW_AT_encoding) { + CHECK_FATAL(GetDwAteName(value.u), "null ptr check"); + LogInfo::MapleLogger() << " " << GetDwAteName(value.u); + } else if (dwAttr == DW_AT_location) { + value.ptr->Dump(); + } else { + LogInfo::MapleLogger() << " 0x" << std::hex << value.u << std::dec; + } + LogInfo::MapleLogger() << std::endl; +} + +void DBGDie::Dump(int indent) { + PrintIndentation(indent); + LogInfo::MapleLogger() << "<" << HEX(id) << "><" << HEX(offset); + LogInfo::MapleLogger() << "><" << HEX(size) << "><" + << "> abbrev id: " << HEX(abbrevId); + CHECK_FATAL(GetDwTagName(tag), "null ptr check"); + LogInfo::MapleLogger() << " (" << GetDwTagName(tag) << ") "; + if (parent) { + LogInfo::MapleLogger() << "parent <" << HEX(parent->GetId()); + } + LogInfo::MapleLogger() << "> {"; + if (tyIdx) { + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(TyIdx(tyIdx)); + if (type->GetKind() == kTypeStruct || type->GetKind() == kTypeClass || type->GetKind() == kTypeInterface) { + MIRStructType *stype = static_cast(type); + LogInfo::MapleLogger() << " # " << stype->GetName(); + } else { + LogInfo::MapleLogger() << " # " << GetPrimTypeName(type->GetPrimType()); + } + } + LogInfo::MapleLogger() << std::endl; + ; + for (auto it : attrVec) { + it->Dump(indent + 1); + } + PrintIndentation(indent); + LogInfo::MapleLogger() << "} "; + if (subDieVec.size()) { + LogInfo::MapleLogger() << " {" << std::endl; + for (auto it : subDieVec) { + it->Dump(indent + 1); + } + PrintIndentation(indent); + LogInfo::MapleLogger() << "}"; + } + LogInfo::MapleLogger() << std::endl; + return; +} + +void DBGAbbrevEntry::Dump(int indent) { + PrintIndentation(indent); + CHECK_FATAL(GetDwTagName(tag), "null ptr check "); + LogInfo::MapleLogger() << "<" << HEX(abbrevId) << "> " << GetDwTagName(tag); + if (GetWithChildren()) { + LogInfo::MapleLogger() << " [with children] {" << std::endl; + } else { + LogInfo::MapleLogger() << " [no children] {" << std::endl; + } + for (uint32 i = 0; i < attrPairs.size(); i += 2) { + PrintIndentation(indent + 1); + CHECK_FATAL(GetDwAtName(attrPairs[i]) && GetDwFormName(attrPairs[i + 1]), "NULLPTR CHECK"); + + LogInfo::MapleLogger() << " " << GetDwAtName(attrPairs[i]) << " " << GetDwFormName(attrPairs[i + 1]) << " " << std::endl; + } + PrintIndentation(indent); + LogInfo::MapleLogger() << "}" << std::endl; + return; +} + +void DBGAbbrevEntryVec::Dump(int indent) { + for (auto it : entryVec) { + PrintIndentation(indent); + it->Dump(indent); + } + return; +} + +// DBGCompileMsgInfo methods +void DBGCompileMsgInfo::ClearLine(uint32 n) { + errno_t eNum = memset_s(codeLine[n], MAXLINELEN, 0, MAXLINELEN); + if (eNum) { + FATAL(kLncFatal, "memset_s failed"); + } +} + +DBGCompileMsgInfo::DBGCompileMsgInfo() : startLine(0), errPos(0) { + lineNum[0] = 0; + lineNum[1] = 0; + lineNum[2] = 0; + ClearLine(0); + ClearLine(1); + ClearLine(2); + errLNum = 0; + errCNum = 0; +} + +void DBGCompileMsgInfo::SetErrPos(uint32 lnum, uint32 cnum) { + errLNum = lnum; + errCNum = cnum; +} + +void DBGCompileMsgInfo::UpdateMsg(uint32 lnum, const char *line) { + // LogInfo::MapleLogger() << "get #" << lnum << " "<< line << std::endl; + size_t size = strlen(line); + if (size > MAXLINELEN - 1) { + size = MAXLINELEN - 1; + } + startLine = (startLine + 2) % 3; + ClearLine(startLine); + errno_t eNum = memcpy_s(codeLine[startLine], MAXLINELEN, line, size); + if (eNum) { + FATAL(kLncFatal, "memcpy_s failed"); + } + codeLine[startLine][size] = '\0'; + lineNum[startLine] = lnum; +} + +void DBGCompileMsgInfo::EmitMsg() { + char str[MAXLINELEN + 1]; + + errPos = errCNum; + errPos = (errPos < 2) ? 2 : errPos; + errPos = (errPos > MAXLINELEN) ? MAXLINELEN : errPos; + for (uint32 i = 0; i < errPos - 1; i++) { + str[i] = ' '; + } + str[errPos - 1] = '^'; + str[errPos] = '\0'; + + fprintf(stderr, "\n===================================================================\n"); + fprintf(stderr, "=================="); + fprintf(stderr, BOLD YEL " Compilation Error Diagnosis " RESET); + fprintf(stderr, "==================\n"); + fprintf(stderr, "===================================================================\n"); + fprintf(stderr, "line %4d %s\n", lineNum[(startLine + 2) % 3], + reinterpret_cast(codeLine[(startLine + 2) % 3])); + fprintf(stderr, "line %4d %s\n", lineNum[(startLine + 1) % 3], + reinterpret_cast(codeLine[(startLine + 1) % 3])); + fprintf(stderr, "line %4d %s\n", lineNum[(startLine + 0) % 3], + reinterpret_cast(codeLine[(startLine + 0) % 3])); + fprintf(stderr, BOLD RED " %s\n" RESET, str); + fprintf(stderr, "===================================================================\n"); +} + +} // namespace maple diff --git a/src/mapleall/maple_ir/src/debug_info_util.cpp b/src/mapleall/maple_ir/src/debug_info_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ff75cfa6a7607a07d72f21982074d105fe9c07f --- /dev/null +++ b/src/mapleall/maple_ir/src/debug_info_util.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) [2021] Futurewei Technologies, Inc. All rights reverved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the MulanPSL - 2.0 for more details. + */ + +#include "mir_builder.h" +#include "printing.h" +#include "maple_string.h" +#include "namemangler.h" +#include "debug_info.h" +#include "global_tables.h" +#include "mir_type.h" +#include +#include "securec.h" +#include "mpl_logging.h" + +namespace maple { + +#define TOSTR(s) #s +// utility functions to get the string from tag value etc. +// GetDwTagName(unsigned n) +const char *GetDwTagName(unsigned n) { + switch (n) { +#define HANDLE_DW_TAG(ID, NAME, VERSION, VENDOR, KIND) case DW_TAG_##NAME: return TOSTR(DW_TAG_##NAME); +#include "Dwarf.def" + case DW_TAG_lo_user: return "DW_TAG_lo_user"; + case DW_TAG_hi_user: return "DW_TAG_hi_user"; + case DW_TAG_user_base: return "DW_TAG_user_base"; + } + return 0; +} + +// GetDwFormName(unsigned n) +const char *GetDwFormName(unsigned n) { + switch (n) { +#define HANDLE_DW_FORM(ID, NAME, VERSION, VENDOR) case DW_FORM_##NAME: return TOSTR(DW_FORM_##NAME); +#include "Dwarf.def" + case DW_FORM_lo_user: return "DW_FORM_lo_user"; + } + return 0; +} + +// GetDwAtName(unsigned n) +const char *GetDwAtName(unsigned n) { + switch (n) { +#define HANDLE_DW_AT(ID, NAME, VERSION, VENDOR) case DW_AT_##NAME: return TOSTR(DW_AT_##NAME); +#include "Dwarf.def" + case DW_AT_lo_user: return "DW_AT_lo_user"; + } + return 0; +} + +// GetDwOpName(unsigned n) +const char *GetDwOpName(unsigned n) { + switch (n) { +#define HANDLE_DW_OP(ID, NAME, VERSION, VENDOR) case DW_OP_##NAME: return TOSTR(DW_OP_##NAME); +#include "Dwarf.def" + // case DW_OP_lo_user: return "DW_OP_lo_user"; // DW_OP_GNU_push_tls_address + case DW_OP_hi_user: return "DW_OP_hi_user"; + case DW_OP_LLVM_fragment: return "DW_OP_LLVM_fragment"; + case DW_OP_LLVM_convert: return "DW_OP_LLVM_convert"; + case DW_OP_LLVM_tag_offset: return "DW_OP_LLVM_tag_offset"; + case DW_OP_LLVM_entry_value: return "DW_OP_LLVM_entry_value"; + } + return 0; +} + +#define DW_ATE_void 0x20 +// GetDwAteName(unsigned n) +const char *GetDwAteName(unsigned n) { + switch (n) { +#define HANDLE_DW_ATE(ID, NAME, VERSION, VENDOR) case DW_ATE_##NAME: return TOSTR(DW_ATE_##NAME); +#include "Dwarf.def" + case DW_ATE_lo_user: return "DW_ATE_lo_user"; + case DW_ATE_hi_user: return "DW_ATE_hi_user"; + case DW_ATE_void: return "DW_ATE_void"; + } + return 0; +} + +// GetDwCfaName(unsigned n) +const char *GetDwCfaName(unsigned n) { + switch (n) { +#define HANDLE_DW_CFA(ID, NAME) case DW_CFA_##NAME: return TOSTR(DW_CFA_##NAME); +#define HANDLE_DW_CFA_PRED(ID, NAME, ARCH) case DW_CFA_##NAME: return TOSTR(DW_CFA_##NAME); +#include "Dwarf.def" + // case DW_CFA_extended: return "DW_CFA_extended"; // DW_CFA_nop + case DW_CFA_lo_user: return "DW_CFA_lo_user"; + case DW_CFA_hi_user: return "DW_CFA_hi_user"; + } + return 0; +} + +DwAte GetAteFromPTY(PrimType pty) { + switch (pty) { + case PTY_u1: + return DW_ATE_boolean; + case PTY_u8: + return DW_ATE_unsigned_char; + case PTY_u16: + case PTY_u32: + case PTY_u64: + return DW_ATE_unsigned; + case PTY_i8: + return DW_ATE_signed_char; + case PTY_i16: + case PTY_i32: + case PTY_i64: + return DW_ATE_signed; + case PTY_f32: + case PTY_f64: + case PTY_f128: + return DW_ATE_float; + case PTY_agg: + case PTY_ref: + case PTY_ptr: + case PTY_a32: + case PTY_a64: + return DW_ATE_address; + case PTY_c64: + case PTY_c128: + return DW_ATE_complex_float; + case PTY_void: + return DW_ATE_void; + default: + return DW_ATE_void; + } +} + +} // namespace maple diff --git a/src/mapleall/maple_ir/src/lexer.cpp b/src/mapleall/maple_ir/src/lexer.cpp index 6d4c31b33a3c9268a2b655216afee1f3e231b08d..6a877c708f77c60f514b7096df4aaf87b075bba2 100644 --- a/src/mapleall/maple_ir/src/lexer.cpp +++ b/src/mapleall/maple_ir/src/lexer.cpp @@ -20,6 +20,7 @@ #include "mir_module.h" #include "securec.h" #include "utils.h" +#include "debug_info.h" namespace maple { int32 HexCharToDigit(char c) { @@ -85,6 +86,7 @@ void MIRLexer::PrepareForFile(const std::string &filename) { } else { lineNum = 1; } + module.GetDbgInfo()->UpdateMsg(lineNum, line.c_str()); kind = TK_invalid; } @@ -540,7 +542,8 @@ TokenKind MIRLexer::LexToken() { if (ReadALine() < 0) { return TK_eof; } - ++lineNum; // a new line readed. + ++lineNum; // a new line read. + module.GetDbgInfo()->UpdateMsg(lineNum, line.c_str()); // skip spaces c = GetCurrentCharWithUpperCheck(); while (c == ' ' || c == '\t') { diff --git a/src/mapleall/maple_ir/src/mir_module.cpp b/src/mapleall/maple_ir/src/mir_module.cpp index 85ff1000e541d75ddcc33c7dabcf8d78a1cea0b5..c4efb90699ad3d28502c10a350a621ff41e78518 100644 --- a/src/mapleall/maple_ir/src/mir_module.cpp +++ b/src/mapleall/maple_ir/src/mir_module.cpp @@ -23,6 +23,7 @@ #include "mir_preg.h" #include "mir_function.h" #include "mir_builder.h" +#include "debug_info.h" #include "intrinsics.h" #include "bin_mplt.h" @@ -55,6 +56,7 @@ MIRModule::MIRModule(const std::string &fn) GlobalTables::GetGsymTable().SetModule(this); typeNameTab = memPool->New(memPoolAllocator); mirBuilder = memPool->New(this); + dbgInfo = memPool->New(this); IntrinDesc::InitMIRModule(this); } @@ -637,6 +639,9 @@ void MIRModule::OutputAsciiMpl(const char *phaseName, const char *suffix, std::streambuf *backup = LogInfo::MapleLogger().rdbuf(); LogInfo::MapleLogger().rdbuf(mplFile.rdbuf()); // change LogInfo::MapleLogger()'s buffer to that of file Dump(emitStructureType, dumpFuncSet); + if (withDbgInfo) { + dbgInfo->Dump(0); + } LogInfo::MapleLogger().rdbuf(backup); // restore LogInfo::MapleLogger()'s buffer mplFile.close(); } else { diff --git a/src/mapleall/maple_ir/src/mpl_dbg.cpp b/src/mapleall/maple_ir/src/mpl_dbg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10b5a4435a45a2f8633dcfd261ff872cdbaf3d8c --- /dev/null +++ b/src/mapleall/maple_ir/src/mpl_dbg.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) [2021] Futurewei Technologies, Inc. All rights reverved. + * + * OpenArkCompiler is licensed under the Mulan Permissive Software License v2. + * You can use this software according to the terms and conditions of the MulanPSL - 2.0. + * You may obtain a copy of MulanPSL - 2.0 at: + * + * https://opensource.org/licenses/MulanPSL-2.0 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the MulanPSL - 2.0 for more details. + */ + +#include "mir_parser.h" +#include "debug_info.h" +#include "bin_mplt.h" +#include "opcode_info.h" +#include +#include "mir_function.h" +#include "mir_type.h" +#include +#include + +using namespace maple; + +std::unordered_set dumpFuncSet = {}; + +int main(int argc, char **argv) { + if (argc < 2) { + MIR_PRINTF("usage: mpldbg foo.mpl\n"); + exit(1); + } + std::vector themodule(argc, nullptr); + bool useBinary = false; + MIRSrcLang srcLang = kSrcLangUnknown; + // process the options which must come first + maple::int32 i = 1; + while (argv[i][0] == '-' ) { + if (argv[i][1] == 'b' && argv[i][2] == '\0') { + useBinary = true; + } else if (strncmp(argv[i], "-dumpfunc=", 10) == 0 && strlen(argv[i]) > 10) { + std::string funcName(&argv[i][10]); + dumpFuncSet.insert(funcName); + } else if (strcmp(argv[i], "-srclang=java") == 0 ) { + srcLang = kSrcLangJava; + } else if (strcmp(argv[i], "-srclang=c") == 0 ) { + srcLang = kSrcLangC; + } else if (strcmp(argv[i], "-srclang=c++") == 0 ) { + srcLang = kSrcLangCPlusPlus; + } else { + ERR(kLncErr, "mpldbg: unrecognized command line option"); + return 1; + } + i++; + } + // process the input files + while (i < argc) { + themodule[i] = new maple::MIRModule(argv[i]); + themodule[i]->SetSrcLang(srcLang); + std::string::size_type lastdot = themodule[i]->GetFileName().find_last_of("."); + bool ismplt = themodule[i]->GetFileName().compare(lastdot, 5, ".mplt") == 0; + bool istmpl = themodule[i]->GetFileName().compare(lastdot, 5, ".tmpl") == 0; + bool ismpl = themodule[i]->GetFileName().compare(lastdot, 5, ".mpl\0") == 0; + bool isbpl = themodule[i]->GetFileName().compare(lastdot, 5, ".bpl\0") == 0; + if (!ismplt && !istmpl && !ismpl && !isbpl) { + ERR(kLncErr, "mpldbg: input must be .mplt or .mpl or .bpl or .tmpl file"); + return 1; + } + // input the file + if (ismpl || istmpl) { + maple::MIRParser theparser(*themodule[i]); + if (!theparser.ParseMIR()) { + theparser.EmitError(themodule[i]->GetFileName().c_str()); + return 1; + } + } else { + BinaryMplImport binMplt(*themodule[i]); + binMplt.SetImported(false); + std::string modid = themodule[i]->GetFileName(); + if (!binMplt.Import(modid, true)) { + ERR(kLncErr, "mpldbg: cannot open .mplt or .bpl file: %s", modid.c_str()); + return 1; + } + } + + themodule[i]->GetDbgInfo()->BuildDebugInfo(); + themodule[i]->SetWithDbgInfo(true); + + // output the file + themodule[i]->OutputAsciiMpl(".dbg", (ismpl || isbpl) ? ".mpl" : ".tmpl"); + i++; + } + return 0; +} diff --git a/src/mapleall/maple_ir/src/parser.cpp b/src/mapleall/maple_ir/src/parser.cpp index 779d060535da83e81c4c6be7ad15d29c8c1074ea..795831e0f75d47dcff440ebe521ae32c1ce570fd 100644 --- a/src/mapleall/maple_ir/src/parser.cpp +++ b/src/mapleall/maple_ir/src/parser.cpp @@ -24,6 +24,7 @@ #include "bin_mplt.h" #include "option.h" #include "string_utils.h" +#include "debug_info.h" namespace { using namespace maple; @@ -161,6 +162,8 @@ void MIRParser::Error(const std::string &str) { message += ": "; message += lexer.GetTokenString(); message += "\n"; + + mod.GetDbgInfo()->SetErrPos(lexer.GetLineNum(), lexer.GetCurIdx()); } const std::string &MIRParser::GetError() { @@ -1468,7 +1471,6 @@ bool MIRParser::ParseTypedef() { GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); TyIdx prevTyIdx; TyIdx tyIdx(0); - // dbginfo class/interface init if (tokenKind == TK_gname) { if (isLocal) { Error("A local type must use local type name "); @@ -2890,6 +2892,7 @@ void MIRParser::EmitError(const std::string &fileName) { if (!strlen(GetError().c_str())) { return; } + mod.GetDbgInfo()->EmitMsg(); ERR(kLncErr, "%s \n%s", fileName.c_str(), GetError().c_str()); } diff --git a/tools/setup_tools.sh b/tools/setup_tools.sh index f954989caabb00abd43d9c8f6ab0a1d44b1d8620..d4923743fcc0b78fc7464b924faed740fbb895be 100755 --- a/tools/setup_tools.sh +++ b/tools/setup_tools.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (C) [2020] Futurewei Technologies, Inc. All rights reverved. +# Copyright (C) [2020-2021] Futurewei Technologies, Inc. All rights reverved. # # Licensed under the Mulan Permissive Software License v2. # You can use this software according to the terms and conditions of the MulanPSL - 2.0. @@ -158,6 +158,14 @@ if [ ! -f $TOOLS/open64_prebuilt/x86/riscv64/bin/clangfe ]; then echo Downloaded open64_prebuilt. fi +if [ ! -f $MAPLE_ROOT/third_party/dwarf/include/Dwarf.h ]; then + cd $TOOLS + rm -rf dwarf $MAPLE_ROOT/third_party/dwarf + git clone https://gitee.com/hu-_-wen/dwarf_h.git dwarf + mv dwarf $MAPLE_ROOT/third_party/ + echo Downloaded dwarf header files. +fi + mkdir -p ${TOOL_BIN_PATH} if [ "$OLD_OS" == "1" ]; then ln -s -f ${MAPLE_ROOT}/tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/clang++ ${TOOL_BIN_PATH}/clang++