Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -831,6 +831,39 @@ getDeclContextDescriptor(Ty->getDecl())); } +static unsigned getDwarfCC(CallingConv CC) { + switch (CC) { + case CC_C: + // Avoid emitting DW_AT_calling_convention if the C convention was used. + return 0; + + case CC_X86StdCall: + return llvm::dwarf::DW_CC_BORLAND_stdcall; + case CC_X86FastCall: + return llvm::dwarf::DW_CC_BORLAND_msfastcall; + case CC_X86ThisCall: + return llvm::dwarf::DW_CC_BORLAND_thiscall; + case CC_X86VectorCall: + return llvm::dwarf::DW_CC_LLVM_vectorcall; + case CC_X86Pascal: + return llvm::dwarf::DW_CC_BORLAND_pascal; + + // FIXME: Create new DW_CC_ codes for these calling conventions. + case CC_X86_64Win64: + case CC_X86_64SysV: + case CC_AAPCS: + case CC_AAPCS_VFP: + case CC_IntelOclBicc: + case CC_SpirFunction: + case CC_SpirKernel: + case CC_Swift: + case CC_PreserveMost: + case CC_PreserveAll: + return 0; + } + return 0; +} + llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, llvm::DIFile *Unit) { SmallVector EltTys; @@ -850,7 +883,8 @@ } llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray); + return DBuilder.createSubroutineType(EltTypeArray, 0, + getDwarfCC(Ty->getCallConv())); } /// Convert an AccessSpecifier into the corresponding DINode flag. @@ -1103,7 +1137,8 @@ if (Func->getExtProtoInfo().RefQualifier == RQ_RValue) Flags |= llvm::DINode::FlagRValueReference; - return DBuilder.createSubroutineType(EltTypeArray, Flags); + return DBuilder.createSubroutineType(EltTypeArray, Flags, + getDwarfCC(Func->getCallConv())); } /// isFunctionLocalClass - Return true if CXXRecordDecl is defined @@ -2562,9 +2597,9 @@ SmallVector ArgTypes; for (const ParmVarDecl *Parm: FD->parameters()) ArgTypes.push_back(Parm->getType()); - QualType FnType = - CGM.getContext().getFunctionType(FD->getReturnType(), ArgTypes, - FunctionProtoType::ExtProtoInfo()); + CallingConv CC = FD->getType()->castAs()->getCallConv(); + QualType FnType = CGM.getContext().getFunctionType( + FD->getReturnType(), ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); llvm::DISubprogram *SP = DBuilder.createTempFunctionFwdDecl( DContext, Name, LinkageName, Unit, Line, getOrCreateFunctionType(FD, FnType, Unit), !FD->isExternallyVisible(), @@ -2668,6 +2703,10 @@ if (const CXXMethodDecl *Method = dyn_cast(D)) return getOrCreateMethodType(Method, F); + + const auto *FTy = FnType->getAs(); + CallingConv CC = FTy ? FTy->getCallConv() : CallingConv::CC_C; + if (const ObjCMethodDecl *OMethod = dyn_cast(D)) { // Add "self" and "_cmd" SmallVector Elts; @@ -2701,7 +2740,7 @@ Elts.push_back(DBuilder.createUnspecifiedParameter()); llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(Elts); - return DBuilder.createSubroutineType(EltTypeArray); + return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC)); } // Handle variadic function types; they need an additional @@ -2715,7 +2754,7 @@ EltTys.push_back(getOrCreateType(FPT->getParamType(i), F)); EltTys.push_back(DBuilder.createUnspecifiedParameter()); llvm::DITypeRefArray EltTypeArray = DBuilder.getOrCreateTypeArray(EltTys); - return DBuilder.createSubroutineType(EltTypeArray); + return DBuilder.createSubroutineType(EltTypeArray, 0, getDwarfCC(CC)); } return cast(getOrCreateType(FnType, F)); Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -762,15 +762,18 @@ // Emit subprogram debug descriptor. if (CGDebugInfo *DI = getDebugInfo()) { + // Reconstruct the type from the argument list so that implicit parameters, + // such as 'this' and 'vtt', show up in the debug info. Preserve the calling + // convention. + CallingConv CC = CallingConv::CC_C; + if (auto *FD = dyn_cast_or_null(D)) + if (const auto *SrcFnTy = FD->getType()->getAs()) + CC = SrcFnTy->getCallConv(); SmallVector ArgTypes; - for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); - i != e; ++i) { - ArgTypes.push_back((*i)->getType()); - } - - QualType FnType = - getContext().getFunctionType(RetTy, ArgTypes, - FunctionProtoType::ExtProtoInfo()); + for (const VarDecl *VD : Args) + ArgTypes.push_back(VD->getType()); + QualType FnType = getContext().getFunctionType( + RetTy, ArgTypes, FunctionProtoType::ExtProtoInfo(CC)); DI->EmitFunctionStart(GD, Loc, StartLoc, FnType, CurFn, Builder); } Index: test/CodeGenCXX/debug-info-calling-conventions.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/debug-info-calling-conventions.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -triple=i686-pc-windows-msvc -debug-info-kind=limited -emit-llvm -o - | FileCheck %s + +struct A { + void thiscallcc(); +}; +void A::thiscallcc() {} + +// CHECK: !DISubprogram(name: "thiscallcc", {{.*}} type: ![[thiscallty:[^,]*]], {{.*}}) +// CHECK: ![[thiscallty]] = !DISubroutineType(cc: DW_CC_BORLAND_thiscall, types: ![[thisargs:[^,)]*]]) +// CHECK: ![[thisargs]] = !{null, ![[thisptrty:[^,}]*]]} +// CHECK: ![[thisptrty]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !{{.*}}, size: 32, align: 32, flags: DIFlagArtificial | DIFlagObjectPointer) + +void cdeclcc() {} +void __fastcall fastcallcc() {} +void __stdcall stdcallcc() {} +void __vectorcall vectorcallcc() {} + +// CHECK: !DISubprogram(name: "cdeclcc", {{.*}} type: ![[cdeclty:[^,]*]], {{.*}}) +// CHECK: ![[cdeclty]] = !DISubroutineType(types: ![[noargs:[^,)]*]]) +// CHECK: ![[noargs]] = !{null} +// CHECK: !DISubprogram(name: "fastcallcc", {{.*}} type: ![[fastcallty:[^,]*]], {{.*}}) +// CHECK: ![[fastcallty]] = !DISubroutineType(cc: DW_CC_BORLAND_msfastcall, types: ![[noargs]]) +// CHECK: !DISubprogram(name: "stdcallcc", {{.*}} type: ![[stdcallty:[^,]*]], {{.*}}) +// CHECK: ![[stdcallty]] = !DISubroutineType(cc: DW_CC_BORLAND_stdcall, types: ![[noargs]]) +// CHECK: !DISubprogram(name: "vectorcallcc", {{.*}} type: ![[vectorcallty:[^,]*]], {{.*}}) +// CHECK: ![[vectorcallty]] = !DISubroutineType(cc: DW_CC_LLVM_vectorcall, types: ![[noargs]])