Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -2380,6 +2380,10 @@ bool doesDeclarationForceExternallyVisibleDefinition() const; + bool isStatic() const { return getStorageClass() == SC_Static; } + + bool isExtern() const { return getStorageClass() == SC_Extern; } + /// Whether this function declaration represents an C++ overloaded /// operator, e.g., "operator+". bool isOverloadedOperator() const { Index: lib/CodeGen/CGBlocks.cpp =================================================================== --- lib/CodeGen/CGBlocks.cpp +++ lib/CodeGen/CGBlocks.cpp @@ -1486,7 +1486,7 @@ codegenoptions::LimitedDebugInfo) { DI->setLocation(D->getLocation()); DI->EmitDeclareOfBlockLiteralArgVariable( - *BlockInfo, D->getName(), argNum, + *BlockInfo, D, argNum, cast(alloc.getPointer()), Builder); } } Index: lib/CodeGen/CGDebugInfo.h =================================================================== --- lib/CodeGen/CGDebugInfo.h +++ lib/CodeGen/CGDebugInfo.h @@ -19,6 +19,7 @@ #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" +#include "clang/AST/GlobalDecl.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" @@ -417,6 +418,12 @@ /// the current block. void EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc); + /// Emit DICallSite for a call. + llvm::DICallSite* EmitCallSite(const Decl *D, const CallExpr *E, + llvm::DISubprogram* CalledSubprogram, + CGBuilderTy &Builder, + unsigned NumIRInstrArgs); + /// Emit call to \c llvm.dbg.declare for an automatic variable /// declaration. /// Returns a pointer to the DILocalVariable associated with the @@ -442,7 +449,8 @@ /// Emit call to \c llvm.dbg.declare for the block-literal argument /// to a block invocation function. void EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - StringRef Name, unsigned ArgNo, + const ImplicitParamDecl *VD, + unsigned ArgNo, llvm::AllocaInst *LocalAddr, CGBuilderTy &Builder); @@ -476,6 +484,14 @@ /// Emit standalone debug info for a type. llvm::DIType *getOrCreateStandaloneType(QualType Ty, SourceLocation Loc); + /// Get DISubprogram for an extern function. + llvm::DISubprogram *getFunctionExternDecl(GlobalDecl GD, SourceLocation Loc, + QualType FnType); + + llvm::DISubprogram *getFunctionFwdDeclaration(GlobalDecl FD) { + return getFunctionForwardDeclaration(FD); + } + void completeType(const EnumDecl *ED); void completeType(const RecordDecl *RD); void completeRequiredType(const RecordDecl *RD); Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -23,6 +23,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/StmtVisitor.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/FileManager.h" @@ -3587,6 +3588,57 @@ setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt()); } +llvm::DISubprogram *CGDebugInfo::getFunctionExternDecl(GlobalDecl GD, + SourceLocation Loc, + QualType FnType) { + StringRef Name; + StringRef LinkageName; + + const Decl *D = GD.getDecl(); + if (!D) + return nullptr; + + llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero; + llvm::DIFile *Unit = getOrCreateFile(Loc); + llvm::DIScope *FDContext = Unit; + llvm::DINodeArray TParamsArray; + if (isa(D)) { + // If there is a DISubprogram for this function available then use it. + collectFunctionDeclProps(GD, Unit, Name, LinkageName, FDContext, + TParamsArray, Flags); + } else if (const auto *OMD = dyn_cast(D)) { + Name = getObjCMethodName(OMD); + Flags |= llvm::DINode::FlagPrototyped; + } else { + llvm_unreachable("not a function or ObjC method"); + } + + if (!Name.empty() && Name[0] == '\01') + Name = Name.substr(1); + + if (D->isImplicit()) { + Flags |= llvm::DINode::FlagArtificial; + // Artificial functions without a location should not silently reuse CurLoc. + if (Loc.isInvalid()) + CurLoc = SourceLocation(); + } + + unsigned LineNo = getLineNumber(Loc); + unsigned ScopeLine = 0; + + llvm::DISubprogram::DISPFlags SPFlags = llvm::DISubprogram::SPFlagZero; + if (CGM.getLangOpts().Optimize) + SPFlags |= llvm::DISubprogram::SPFlagOptimized; + // We want just func declaration. + SPFlags &= ~llvm::DISubprogram::SPFlagDefinition; + + llvm::DISubprogram *SP = DBuilder.createFunction( + FDContext, Name, LinkageName, Unit, LineNo, nullptr, ScopeLine, Flags, + SPFlags, TParamsArray.get(), getFunctionDeclaration(D), nullptr, true); + + return SP; +} + void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) { // Update our current location setLocation(Loc); @@ -3782,7 +3834,6 @@ if (CGOpts.EnableParamEntryValues && !VD->getIsValChanged()) Flags |= llvm::DINode::FlagVariableNotChanged; - auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType()); @@ -3839,10 +3890,14 @@ // Use VarDecl's Tag, Scope and Line number. auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext()); + auto *D = DBuilder.createAutoVariable( - Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize, + Scope, FieldName, Unit, Line, FieldTy, Flags | llvm::DINode::FlagArtificial, FieldAlign); + if (CGM.getLangOpts().Optimize) + DBuilder.preserveVariable(Scope, D, VD); + // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare( Storage, D, DBuilder.createExpression(Expr), @@ -3854,12 +3909,13 @@ // Create the descriptor for the variable. auto *D = ArgNo ? DBuilder.createParameterVariable( - Scope, Name, *ArgNo, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags) + Scope, Name, *ArgNo, Unit, Line, Ty, Flags) : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty, - CGM.getLangOpts().Optimize, Flags, Align); + if (CGM.getLangOpts().Optimize) + DBuilder.preserveVariable(Scope, D, VD); + // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr), llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt), @@ -3901,6 +3957,201 @@ Builder.GetInsertBlock()); } +// Algorithm for producing functions argument representation. Result of +// algorithm is supposed to be used for creating DICallSiteParam. Current +// version supports only simple cases with one variable and expression over +// that variable. If argument is constant value only expession is provided. +// Expression is given in form of DW_OP codes. Algorithm is not interested in +// representing argument that is another function call. Current version +// supports only expression over one variable. +// TODO: Next version should be able to represent expressions over more +// variables but that requires changing DICallSiteParameter +// and derived class from DIExpression that could potentially represent +// such expressions. + +namespace { +/// Represent expression in terms of dwarf expression over variable. If there +/// is no variable expression must be constant. +struct DwarfExprRepresentation + : ConstStmtVisitor { + const ASTContext *Ctx; + const VarDecl *VD; + SmallVector Ops; + + DwarfExprRepresentation() = default; + + void clean() { + VD = nullptr; + Ops.clear(); + } + + void get(const VarDecl **Var, SmallVectorImpl &Operands) { + *Var = VD; + VD = nullptr; + Operands = std::move(Ops); + } + + void setContext(const ASTContext &Context) { Ctx = &Context; }; + + bool VisitExpr(const Expr *Exp) { return false; } + + bool VisitImplicitCastExpr(const ImplicitCastExpr *Exp) { + return Visit(Exp->getSubExpr()); + } + + bool VisitBinaryOperator(const BinaryOperator *E) { + const Expr *LHS = E->getLHS(); + const Expr *RHS = E->getRHS(); + + if (Visit(LHS) && Visit(RHS)) { + if (VD) { + switch (E->getOpcode()) { + case BO_Add: + Ops.push_back(llvm::dwarf::DW_OP_plus); + return true; + case BO_Mul: + Ops.push_back(llvm::dwarf::DW_OP_mul); + return true; + case BO_Div: + Ops.push_back(llvm::dwarf::DW_OP_div); + return true; + case BO_Sub: + Ops.push_back(llvm::dwarf::DW_OP_minus); + return true; + default: + return false; + } + } else { + // If VD is null then this is constant expression. Evaluate it and + // represent the result value. + llvm::APSInt Result; + Ops.clear(); + if (E->isIntegerConstantExpr(Result, *Ctx)) { + int64_t Value = Result.getExtValue(); + if (Value >= 0 && Value <= 31) + Ops.push_back(llvm::dwarf::DW_OP_lit0 + Value); + else { + Ops.push_back(Value < 0 ? llvm::dwarf::DW_OP_consts + : llvm::dwarf::DW_OP_constu); + Ops.push_back(Value); + } + return true; + } + } + } + + // Clear all DWARF ops of unsupported expressions. + Ops.clear(); + + return false; + } + + bool VisitUnaryDeref(const UnaryOperator *E) { + if (!Visit(E->getSubExpr())) + return false; + Ops.push_back(llvm::dwarf::DW_OP_deref); + return true; + } + + bool VisitUnaryAddrOf(const UnaryOperator *E) { + if (!Visit(E->getSubExpr())) + return false; + Ops.push_back(llvm::dwarf::DW_OP_push_object_address); + return true; + } + + bool VisitUnaryMinus(const UnaryOperator *E) { + // If the expression is '-- const'. + if (Ops.size() && Ops.back() == llvm::dwarf::DW_OP_neg) + return false; + if (!Visit(E->getSubExpr())) + return false; + Ops.push_back(llvm::dwarf::DW_OP_neg); + return true; + } + + bool VisitDeclRefExpr(const DeclRefExpr *E) { + if (const VarDecl *VarD = dyn_cast(E->getDecl())) { + if (!VD && !VarD->hasGlobalStorage()) { + VD = VarD; + return true; + } + } + VD = nullptr; + return false; + } + + bool VisitIntegerLiteral(const IntegerLiteral *E) { + uint64_t Value = *E->getValue().getRawData(); + if (Value <= 31) + Ops.push_back(llvm::dwarf::DW_OP_lit0 + Value); + else { + Ops.push_back(llvm::dwarf::DW_OP_constu); + Ops.push_back(Value); + } + return true; + } +}; +} // end anonymous namespace + +llvm::DICallSite * +CGDebugInfo::EmitCallSite(const Decl *D, const CallExpr *E, + llvm::DISubprogram *CalledSubprogram, + CGBuilderTy &Builder, unsigned NumIRInstrArgs) { + if (D->hasAttr()) + return nullptr; + + SmallVector CallSiteParams; + static DwarfExprRepresentation EvalDwarfOps; + EvalDwarfOps.setContext(CGM.getContext()); + auto *Scope = cast(LexicalBlockStack.back()); + unsigned ArgNo = 1; + if (NumIRInstrArgs > E->getNumArgs()) { + llvm::DIExpression *Expr = DBuilder.createExpression(); + for (; ArgNo <= NumIRInstrArgs; ++ArgNo) { + llvm::DICallSiteParam *DCSP = DBuilder.createCallSiteParam(ArgNo, Expr); + CallSiteParams.push_back(DCSP); + } + } else { + if (isa(D)) { + llvm::DIExpression *Expr = DBuilder.createExpression(); + llvm::DICallSiteParam *DCSP = DBuilder.createCallSiteParam(ArgNo, Expr); + CallSiteParams.push_back(DCSP); + ArgNo++; + } + for (auto Arg : E->arguments()) { + SmallVector Ops; + const VarDecl *VD = nullptr; + if (EvalDwarfOps.Visit(Arg)) + EvalDwarfOps.get(&VD, Ops); + EvalDwarfOps.clean(); + + llvm::DIExpression *Expr = DBuilder.createExpression(Ops); + + llvm::DICallSiteParam *DCSP = nullptr; + if (VD) + DCSP = DBuilder.createCallSiteParam(ArgNo, Expr, Scope, VD); + else + DCSP = DBuilder.createCallSiteParam(ArgNo, Expr); + + CallSiteParams.push_back(DCSP); + ArgNo++; + } + } + + llvm::DINodeArray ParamArray = DBuilder.getOrCreateArray(CallSiteParams); + llvm::DIFile *Unit = getOrCreateFile(E->getExprLoc()); + + // Get location information. + unsigned Line = getLineNumber(E->getExprLoc()); + + // Create the descriptor for the call site. + auto *CS = DBuilder.createCallSite(Scope, Unit, Line, CalledSubprogram, + ParamArray, CGM.getLangOpts().Optimize); + + return CS; +} + llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType *Ty) { llvm::DIType *CachedTy = getTypeOrNull(QualTy); @@ -3968,7 +4219,7 @@ auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); auto *D = DBuilder.createAutoVariable( cast(LexicalBlockStack.back()), VD->getName(), Unit, - Line, Ty, false, llvm::DINode::FlagZero, Align); + Line, Ty, llvm::DINode::FlagZero, Align); // Insert an llvm.dbg.declare into the current block. auto DL = @@ -4036,10 +4287,11 @@ } void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block, - StringRef Name, + const ImplicitParamDecl *VD, unsigned ArgNo, llvm::AllocaInst *Alloca, CGBuilderTy &Builder) { + StringRef Name = VD->getName(); assert(DebugKind >= codegenoptions::LimitedDebugInfo); ASTContext &C = CGM.getContext(); const BlockDecl *blockDecl = block.getBlockDecl(); @@ -4153,7 +4405,9 @@ // Create the descriptor for the parameter. auto *debugVar = DBuilder.createParameterVariable( - scope, Name, ArgNo, tunit, line, type, CGM.getLangOpts().Optimize, flags); + scope, Name, ArgNo, tunit, line, type, flags); + if (CGM.getLangOpts().Optimize) + DBuilder.preserveVariable(scope, debugVar, VD); // Insert an llvm.dbg.declare into the current block. DBuilder.insertDeclare(Alloca, debugVar, DBuilder.createExpression(), Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -29,6 +29,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" @@ -4782,7 +4783,46 @@ Callee.setFunctionPointer(CalleePtr); } - return EmitCall(FnInfo, Callee, ReturnValue, Args, nullptr, E->getExprLoc()); + llvm::CallBase *callOrInvoke = nullptr; + RValue Call = EmitCall(FnInfo, Callee, ReturnValue, Args, &callOrInvoke, + E->getExprLoc()); + + // Generate all necessary debug information about call sites and its + // parameters. + auto &CGOpts = CGM.getCodeGenOpts(); + if (CGOpts.EnableParamEntryValues && CGM.getLangOpts().Optimize && + callOrInvoke) { + + if (CGDebugInfo *DI = getDebugInfo()) { + if (CGOpts.getDebugInfo() >= codegenoptions::LimitedDebugInfo && + CGOpts.getDebuggerTuning() == llvm::DebuggerKind::GDB && + CGOpts.DwarfVersion == 4) { + DI->setLocation(CurCodeDecl->getLocation()); + unsigned IRCallNumArgs = callOrInvoke->getNumArgOperands(); + llvm::DISubprogram *CalledSubprogram = nullptr; + + if (auto *Func = callOrInvoke->getCalledFunction()) + CalledSubprogram = Func->getSubprogram(); + + if (const FunctionDecl *CalledFD = + dyn_cast_or_null(TargetDecl)) { + if (!CalledFD->isInlined() && !CalledSubprogram) { + if (CalledFD->isStatic()) + CalledSubprogram = DI->getFunctionFwdDeclaration(CalledFD); + else + CalledSubprogram = DI->getFunctionExternDecl( + CalledFD, CalledFD->getLocation(), CalleeType); + } + } + + llvm::DICallSite *CS = DI->EmitCallSite( + CurCodeDecl, E, CalledSubprogram, Builder, IRCallNumArgs); + callOrInvoke->setMetadata(llvm::LLVMContext::MD_call_site, CS); + } + } + } + + return Call; } LValue CodeGenFunction:: Index: test/CodeGen/dbginfo-callsite-constant-params.c =================================================================== --- /dev/null +++ test/CodeGen/dbginfo-callsite-constant-params.c @@ -0,0 +1,12 @@ +// RUN: %clang -g -O2 -femit-param-entry-values -S -emit-llvm %s -o -| FileCheck %s +// CHECK: !DICallSiteParam(argno: 1, expr: !DIExpression(DW_OP_consts, 18446744073709551594)) +// CHECK: !DICallSiteParam(argno: 1, expr: !DIExpression(DW_OP_constu, 44)) +// CHECK: !DICallSiteParam(argno: 1, expr: !DIExpression(DW_OP_lit14)) +extern int foo1(unsigned); +#define NUMBER 11 +int global; +void baa() { + global = foo1(NUMBER - 33); + global += foo1(NUMBER + 33); + global += foo1(NUMBER + 3); +} Index: test/CodeGen/dbginfo-callsite-unsupported-params.c =================================================================== --- /dev/null +++ test/CodeGen/dbginfo-callsite-unsupported-params.c @@ -0,0 +1,13 @@ +// RUN: %clang -g -O2 -femit-param-entry-values -S -emit-llvm %s -o -| FileCheck %s +// CHECK: !DICallSiteParam(argno: 1, expr: !DIExpression()) +// CHECK-NEXT: !DICallSiteParam(argno: 2, expr: !DIExpression()) +// CHECK-NEXT: !DICallSiteParam(argno: 3, variable: !16, expr: !DIExpression(DW_OP_push_object_address)) +extern int foo(unsigned, unsigned, int *); +#define NUMBER 17 +int global; +void baa() { + int tmp; + global += foo(sizeof(tmp), sizeof(tmp), &tmp); + global += foo(NUMBER + 3 + sizeof(tmp), NUMBER + 0 * sizeof(tmp), &tmp); + global += foo(NUMBER + 3, NUMBER + 0 * sizeof(tmp), &tmp); +}