Index: include/llvm-c/DebugInfo.h =================================================================== --- include/llvm-c/DebugInfo.h +++ include/llvm-c/DebugInfo.h @@ -160,7 +160,9 @@ LLVMDIObjCPropertyMetadataKind, LLVMDIImportedEntityMetadataKind, LLVMDIMacroMetadataKind, - LLVMDIMacroFileMetadataKind + LLVMDIMacroFileMetadataKind, + LLVMDICallSiteMetadataKind, + LLVMDICallSiteParamMetadataKind }; typedef unsigned LLVMMetadataKind; Index: include/llvm/BinaryFormat/Dwarf.def =================================================================== --- include/llvm/BinaryFormat/Dwarf.def +++ include/llvm/BinaryFormat/Dwarf.def @@ -354,7 +354,13 @@ HANDLE_DW_AT(0x2110, GNU_template_name, 0, GNU) HANDLE_DW_AT(0x210f, GNU_odr_signature, 0, GNU) HANDLE_DW_AT(0x2111, GNU_call_site_value, 0, GNU) +HANDLE_DW_AT (0x2112, GNU_call_site_data_value, 0, GNU) +HANDLE_DW_AT (0x2113, GNU_call_site_target, 0, GNU) +HANDLE_DW_AT (0x2114, GNU_call_site_target_clobbered, 0, GNU) +HANDLE_DW_AT (0x2115, GNU_tail_call, 0, GNU) +HANDLE_DW_AT (0x2116, GNU_all_tail_call_sites, 0, GNU) HANDLE_DW_AT(0x2117, GNU_all_call_sites, 0, GNU) +HANDLE_DW_AT (0x2118, GNU_all_source_call_sites, 0, GNU) HANDLE_DW_AT(0x2119, GNU_macros, 0, GNU) // Extensions for Fission proposal. HANDLE_DW_AT(0x2130, GNU_dwo_name, 0, GNU) Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -310,6 +310,8 @@ METADATA_INDEX_OFFSET = 38, // [offset] METADATA_INDEX = 39, // [bitpos] METADATA_LABEL = 40, // [distinct, scope, name, file, line] + METADATA_CALL_SITE = 41, // [distinct, scope, parameters, line, calledSubprogram] + METADATA_CALL_SITE_PARAM = 42, // [distinct, argno, var, expr] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each Index: include/llvm/IR/DebugInfoFlags.def =================================================================== --- include/llvm/IR/DebugInfoFlags.def +++ include/llvm/IR/DebugInfoFlags.def @@ -84,11 +84,13 @@ HANDLE_DISP_FLAG((1u << 2), LocalToUnit) HANDLE_DISP_FLAG((1u << 3), Definition) HANDLE_DISP_FLAG((1u << 4), Optimized) +HANDLE_DISP_FLAG((1u << 5), AllCallsDesc) +HANDLE_DISP_FLAG((1u << 6), DeclForCallSite) #ifdef DISP_FLAG_LARGEST_NEEDED // Intended to be used with ADT/BitmaskEnum.h. // NOTE: Always must be equal to largest flag, check this when adding new flags. -HANDLE_DISP_FLAG((1 << 4), Largest) +HANDLE_DISP_FLAG((1 << 6), Largest) #undef DISP_FLAG_LARGEST_NEEDED #endif Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -224,6 +224,8 @@ case DIFileKind: case DICompileUnitKind: case DISubprogramKind: + case DICallSiteKind: + case DICallSiteParamKind: case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: @@ -482,6 +484,7 @@ case DIFileKind: case DICompileUnitKind: case DISubprogramKind: + case DICallSiteKind: case DILexicalBlockKind: case DILexicalBlockFileKind: case DINamespaceKind: @@ -1690,7 +1693,7 @@ private: DIFlags Flags; - DISPFlags SPFlags; + mutable DISPFlags SPFlags; DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, @@ -1785,6 +1788,13 @@ bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } + /// Used for debug info about call sites. + bool getIsDesribedByCallSites() const { return getSPFlags() & SPFlagAllCallsDesc; } + void setIsDesribedByCallSites() { getSPFlags() | SPFlagAllCallsDesc; } + void setIsDesribedByCallSites() const { getSPFlags() | SPFlagAllCallsDesc; } + bool getIsDeclForCallSite() const { return getSPFlags() & SPFlagDeclForCallSite; } + void setIsDeclForCallSite() { getSPFlags() | SPFlagDeclForCallSite; } + bool isArtificial() const { return getFlags() & FlagArtificial; } bool isPrivate() const { return (getFlags() & FlagAccessibility) == FlagPrivate; @@ -1853,6 +1863,10 @@ return cast_or_null(getRawThrownTypes()); } + void replaceElements(DINodeArray Elements) { + replaceOperandWith(10, Elements.get()); + } + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } MDString *getRawLinkageName() const { return getOperandAs(3); } @@ -1880,6 +1894,137 @@ } }; +class DICallSite : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned Line; + + DICallSite(LLVMContext &C, StorageType Storage, unsigned Line, + ArrayRef Ops) + : DINode(C, DICallSiteKind, Storage, dwarf::DW_TAG_GNU_call_site, Ops), + Line(Line){}; + ~DICallSite() { dropAllReferences(); } + + static DICallSite *getImpl(LLVMContext &Context, DIScope *Scope, DIFile *File, + DINodeArray Params, unsigned Line, + DISubprogram *CalledSubprogram, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, File, cast_or_null(Params.get()), + Line, CalledSubprogram, Storage, ShouldCreate); + } + + static DICallSite *getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, Metadata *Params, unsigned Line, + Metadata *CalledSubprogram, StorageType Storage, + bool ShouldCreate = true); + + TempDICallSite cloneImpl() const { + return getTemporary(getContext(), getScope(), getFile(), getParameters(), + getLine(), getCalledSubprogram()); + } + +public: + DEFINE_MDNODE_GET(DICallSite, + (DILocalScope * Scope, DIFile *File, DINodeArray Params, + unsigned Line, DISubprogram *CalledSubprogram), + (Scope, File, Params, Line, CalledSubprogram)) + DEFINE_MDNODE_GET(DICallSite, + (Metadata * Scope, Metadata *File, Metadata *Params, + unsigned Line, Metadata *CalledSubprogram), + (Scope, File, Params, Line, CalledSubprogram)) + + TempDICallSite clone() const { return cloneImpl(); } + + DILocalScope *getScope() const { + return cast_or_null(getRawScope()); + } + + unsigned getLine() const { return Line; } + DIFile *getFile() const { return cast_or_null(getRawFile()); } + DISubprogram *getCalledSubprogram() const { + return cast_or_null(getRawCalledSubprogram()); + } + + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawFile() const { return getOperand(1); } + DINodeArray getParameters() const { + return cast_or_null(getRawParams()); + } + Metadata *getRawParams() const { return getOperand(2); } + Metadata *getRawCalledSubprogram() const { return getOperand(3); } + + bool isValidLocationForIntrinsic(const DILocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICallSiteKind; + } +}; + +class DICallSiteParam : public DINode { + friend class LLVMContextImpl; + friend class MDNode; + + unsigned ArgNo; + + DICallSiteParam(LLVMContext &C, StorageType Storage, unsigned ArgNo, + ArrayRef Ops) + : DINode(C, DICallSiteParamKind, Storage, + dwarf::DW_TAG_GNU_call_site_parameter, Ops), + ArgNo(ArgNo) {} + ~DICallSiteParam() = default; + // TODO :: CONSIDER ONE getImpl and one DEFINE_MDNODE_GE like in + // GlobalDIExpression + static DICallSiteParam *getImpl(LLVMContext &Context, unsigned ArgNo, + DILocalVariable *Var, DIExpression *Expr, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, ArgNo, cast_or_null(Var), + cast(Expr), Storage, ShouldCreate); + } + + static DICallSiteParam *getImpl(LLVMContext &Context, unsigned ArgNo, + Metadata *Var, Metadata *Expr, + StorageType Storage, + bool ShouldCreate = true); + + TempDICallSiteParam cloneImpl() const { + return getTemporary(getContext(), getArgNo(), getVar(), getExpression()); + } + +public: + DEFINE_MDNODE_GET(DICallSiteParam, + (unsigned ArgNo, DILocalVariable *Var, DIExpression *Expr), + (ArgNo, Var, Expr)) + DEFINE_MDNODE_GET(DICallSiteParam, + (unsigned ArgNo, Metadata *Var, Metadata *Expr), + (ArgNo, Var, Expr)) + DEFINE_MDNODE_GET(DICallSiteParam, (unsigned ArgNo, Metadata *Expr), + (ArgNo, nullptr, Expr)) + DEFINE_MDNODE_GET(DICallSiteParam, (unsigned ArgNo, DIExpression *Expr), + (ArgNo, nullptr, Expr)) + + TempDICallSiteParam clone() const { return cloneImpl(); } + + unsigned getArgNo() const { return ArgNo; } + + Metadata *getRawVar() const { return getOperand(0); } + Metadata *getRawExpression() const { return getOperand(1); } + + DILocalVariable *getVar() const { + return cast_or_null(getOperand(0)); + } + DIExpression *getExpression() const { + return cast(getRawExpression()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DICallSiteParamKind; + } +}; + class DILexicalBlockBase : public DILocalScope { protected: DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, Index: include/llvm/IR/Metadata.def =================================================================== --- include/llvm/IR/Metadata.def +++ include/llvm/IR/Metadata.def @@ -96,6 +96,8 @@ HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DISubprogram) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICallSite) +HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DICallSiteParam) HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlock) HANDLE_SPECIALIZED_MDNODE_LEAF_UNIQUABLE(DILexicalBlockFile) Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4616,6 +4616,40 @@ return false; } +/// ParseDICallSite: +/// ::= !DICallSite(scope: !0, file: !2, parameters: !32, line: 7, +/// calledSubprogram: !12) +bool LLParser::ParseDICallSite(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(scope, MDField, (/* AllowNull */ false)); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(parameters, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(calledSubprogram, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = + GET_OR_DISTINCT(DICallSite, (Context, scope.Val, file.Val, parameters.Val, + line.Val, calledSubprogram.Val)); + return false; +} + +/// ParseDICallSiteParam: +/// ::= !DICallSiteParam(argno: 1, variable: !0, expr: !1) +bool LLParser::ParseDICallSiteParam(MDNode *&Result, bool IsDistinct) { +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + OPTIONAL(argno, MDUnsignedField, (0, UINT16_MAX)); \ + OPTIONAL(variable, MDField, ); \ + OPTIONAL(expr, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(DICallSiteParam, + (Context, argno.Val, variable.Val, expr.Val)); + return false; +} + /// ParseDILexicalBlock: /// ::= !DILexicalBlock(scope: !0, file: !2, line: 7, column: 9) bool LLParser::ParseDILexicalBlock(MDNode *&Result, bool IsDistinct) { Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -817,6 +817,8 @@ case bitc::METADATA_TEMPLATE_VALUE: case bitc::METADATA_GLOBAL_VAR: case bitc::METADATA_LOCAL_VAR: + case bitc::METADATA_CALL_SITE: + case bitc::METADATA_CALL_SITE_PARAM: case bitc::METADATA_LABEL: case bitc::METADATA_EXPRESSION: case bitc::METADATA_OBJC_PROPERTY: @@ -1481,6 +1483,33 @@ } break; } + case bitc::METADATA_CALL_SITE: { + if (Record.size() != 6) + return error("Invalid record"); + + IsDistinct = Record[0] & 1; + MetadataList.assignValue( + GET_OR_DISTINCT(DICallSite, + (Context, getMDOrNull(Record[1]), + getMDOrNull(Record[2]), getMDOrNull(Record[3]), + Record[4], getMDOrNull(Record[5]))), + NextMetadataNo); + NextMetadataNo++; + break; + } + case bitc::METADATA_CALL_SITE_PARAM: { + if (Record.size() != 3) + return error("Invalid record"); + + IsDistinct = Record[0] & 1; + MetadataList.assignValue( + GET_OR_DISTINCT(DICallSiteParam, + (Context, Record[1], getMDOrNull(Record[2]), + getMDOrNull(Record[3]))), + NextMetadataNo); + NextMetadataNo++; + break; + } case bitc::METADATA_LEXICAL_BLOCK: { if (Record.size() != 5) return error("Invalid record"); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -312,6 +312,10 @@ SmallVectorImpl &Record, unsigned Abbrev); void writeDISubprogram(const DISubprogram *N, SmallVectorImpl &Record, unsigned Abbrev); + void writeDICallSite(const DICallSite *N, + SmallVectorImpl &Record, unsigned Abbrev); + void writeDICallSiteParam(const DICallSiteParam *N, + SmallVectorImpl &Record, unsigned Abbrev); void writeDILexicalBlock(const DILexicalBlock *N, SmallVectorImpl &Record, unsigned Abbrev); void writeDILexicalBlockFile(const DILexicalBlockFile *N, @@ -1659,6 +1663,32 @@ Record.clear(); } +void ModuleBitcodeWriter::writeDICallSite(const DICallSite *N, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back((uint64_t)N->isDistinct()); + Record.push_back(VE.getMetadataOrNullID(N->getScope())); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(VE.getMetadataOrNullID(N->getRawParams())); + Record.push_back(N->getLine()); + Record.push_back(VE.getMetadataOrNullID(N->getRawCalledSubprogram())); + + Stream.EmitRecord(bitc::METADATA_CALL_SITE, Record, Abbrev); + Record.clear(); +} + +void ModuleBitcodeWriter::writeDICallSiteParam(const DICallSiteParam *N, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back((uint64_t)N->isDistinct()); + Record.push_back(N->getArgNo()); + Record.push_back(VE.getMetadataOrNullID(N->getRawVar())); + Record.push_back(VE.getMetadataOrNullID(N->getExpression())); + + Stream.EmitRecord(bitc::METADATA_CALL_SITE_PARAM, Record, Abbrev); + Record.clear(); +} + void ModuleBitcodeWriter::writeDILexicalBlock(const DILexicalBlock *N, SmallVectorImpl &Record, unsigned Abbrev) { Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -1964,6 +1964,32 @@ Out << ")"; } +static void writeDICallSite(raw_ostream &Out, const DICallSite *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!DICallSite("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false); + Printer.printMetadata("file", N->getRawFile()); + Printer.printMetadata("parameters", N->getRawParams()); + Printer.printInt("line", N->getLine()); + Printer.printMetadata("calledSubprogram", N->getRawCalledSubprogram()); + Out << ")"; +} + +static void writeDICallSiteParam(raw_ostream &Out, const DICallSiteParam *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + Out << "!DICallSiteParam("; + MDFieldPrinter Printer(Out, TypePrinter, Machine, Context); + Printer.printInt("argno", N->getArgNo()); + if (DILocalVariable *DIVar = N->getVar()) + Printer.printMetadata("variable", DIVar); + Printer.printMetadata("expr", N->getRawExpression()); + Out << ")"; +} + static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N, TypePrinting *TypePrinter, SlotTracker *Machine, const Module *Context) { Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -660,6 +660,28 @@ return F->getName() == Name; } +DICallSite *DICallSite::getImpl(LLVMContext &Context, Metadata *Scope, + Metadata *File, Metadata *Params, + unsigned Line, Metadata* CalledSubprogram, + StorageType Storage, + bool ShouldCreate) { + assert(Scope && "Expected scope"); + + DEFINE_GETIMPL_LOOKUP(DICallSite, + (Line, Scope, File, Params, CalledSubprogram)); + Metadata *Ops[] = {Scope, File, Params, CalledSubprogram}; + DEFINE_GETIMPL_STORE(DICallSite, (Line), Ops); +} + +DICallSiteParam *DICallSiteParam::getImpl(LLVMContext &Context, + unsigned ArgNo, Metadata *Var, + Metadata *Expr, StorageType Storage, + bool ShouldCreate) { + DEFINE_GETIMPL_LOOKUP(DICallSiteParam, (ArgNo, Var, Expr)); + Metadata *Ops[] = {Var, Expr}; + DEFINE_GETIMPL_STORE(DICallSiteParam, (ArgNo), Ops); +} + DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, StorageType Storage, Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -767,6 +767,51 @@ } }; +template <> struct MDNodeKeyImpl { + unsigned Line; + Metadata *Scope; + Metadata *File; + Metadata *Params; + Metadata *CalledSubprogram; + + MDNodeKeyImpl(unsigned Line, Metadata *Scope, Metadata *File, + Metadata *Params, Metadata *CalledSubprogram) + : Line(Line), Scope(Scope), File(File), Params(Params), + CalledSubprogram(CalledSubprogram) {} + MDNodeKeyImpl(const DICallSite *N) + : Line(N->getLine()), Scope(N->getRawScope()), File(N->getRawFile()), + Params(N->getRawParams()), + CalledSubprogram(N->getRawCalledSubprogram()) {} + + bool isKeyOf(const DICallSite *RHS) const { + return Line == RHS->getLine() && Scope == RHS->getRawScope() && + File == RHS->getRawFile() && Params == RHS->getRawParams() && + CalledSubprogram == RHS->getRawCalledSubprogram(); + } + + unsigned getHashValue() const { return hash_combine(Scope, File, Line); } +}; + +template <> struct MDNodeKeyImpl { + unsigned ArgNo; + Metadata *Var; + Metadata *Expr; + + MDNodeKeyImpl(unsigned ArgNo, Metadata *Var, Metadata *Expr) + : ArgNo(ArgNo), Var(Var), Expr(Expr) {} + MDNodeKeyImpl(const DICallSiteParam *N) + : ArgNo(N->getArgNo()), Var(N->getRawVar()), Expr(N->getRawExpression()) { + } + + // FIXME : CHEK PARENT NODES OF THIS NODE?? + bool isKeyOf(const DICallSiteParam *RHS) const { + return Var == RHS->getRawVar() && Expr == RHS->getRawExpression() && + ArgNo == RHS->getArgNo(); + } + + unsigned getHashValue() const { return hash_combine(ArgNo, Var, Expr); } +}; + template <> struct MDNodeKeyImpl { Metadata *Scope; MDString *Name; Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1137,6 +1137,34 @@ "DIFlagAllCallsDescribed must be attached to a definition"); } +void Verifier::visitDICallSite(const DICallSite &N) { + if (auto *S = N.getRawScope()) + AssertDI(isa(S), "invalid scope", &N, S); + if (auto *F = N.getRawFile()) + AssertDI(isa(F), "invalid file", &N, F); + + if (auto *RawParams = N.getRawParams()) { + auto *Params = dyn_cast(RawParams); + AssertDI(Params, "invalid variable list", &N, RawParams); + for (Metadata *Op : Params->operands()) { + AssertDI(Op && isa(Op), "invalid local variable", &N, + Params, Op); + } + } + + AssertDI(N.getTag() == dwarf::DW_TAG_GNU_call_site, "invalid tag", &N); + AssertDI(N.getRawScope() && isa(N.getRawScope()), + "callsite requires a valid scope", &N, N.getRawScope()); +} + +void Verifier::visitDICallSiteParam(const DICallSiteParam &N) { + AssertDI(N.getTag() == dwarf::DW_TAG_GNU_call_site_parameter, "invalid tag", + &N); + AssertDI(N.getRawVar() || N.getRawExpression(), + "call-parameter requires a valid variable metadat or expression", + &N); +} + void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N); AssertDI(N.getRawScope() && isa(N.getRawScope()),