Index: include/llvm/DebugInfo/CodeView/CodeView.h =================================================================== --- include/llvm/DebugInfo/CodeView/CodeView.h +++ include/llvm/DebugInfo/CodeView/CodeView.h @@ -298,7 +298,8 @@ None = 0x0000, Const = 0x0001, Volatile = 0x0002, - Unaligned = 0x0004 + Unaligned = 0x0004, + Restrict = 0x0008 }; CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ModifierOptions) Index: include/llvm/DebugInfo/CodeView/TypeRecord.h =================================================================== --- include/llvm/DebugInfo/CodeView/TypeRecord.h +++ include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -330,6 +330,10 @@ return !!(Attrs & uint32_t(PointerOptions::Unaligned)); } + bool isRestrict() const { + return !!(Attrs & uint32_t(PointerOptions::Restrict)); + } + TypeIndex ReferentType; uint32_t Attrs; Optional MemberInfo; Index: lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1265,6 +1265,8 @@ case dwarf::DW_TAG_volatile_type: // TODO: add support for DW_TAG_atomic_type here return lowerTypeModifier(cast(Ty)); + case dwarf::DW_TAG_restrict_type: + return lowerTypeModifier(cast(Ty)); case dwarf::DW_TAG_subroutine_type: if (ClassTy) { // The member function type of a member function pointer has no @@ -1560,6 +1562,9 @@ case dwarf::DW_TAG_volatile_type: Mods |= ModifierOptions::Volatile; break; + case dwarf::DW_TAG_restrict_type: + Mods |= ModifierOptions::Restrict; + break; default: IsModifier = false; break; Index: lib/DebugInfo/CodeView/RecordName.cpp =================================================================== --- lib/DebugInfo/CodeView/RecordName.cpp +++ lib/DebugInfo/CodeView/RecordName.cpp @@ -182,6 +182,9 @@ Name.append("&&"); else if (Ptr.getMode() == PointerMode::Pointer) Name.append("*"); + + if (Ptr.isRestrict()) + Name.append(" __restrict"); } return Error::success(); } @@ -197,6 +200,8 @@ if (Mods & uint16_t(ModifierOptions::Unaligned)) Name.append("__unaligned "); Name.append(Types.getTypeName(Mod.getModifiedType())); + if (Mods & uint16_t(ModifierOptions::Restrict)) + Name.append(" __restrict"); return Error::success(); } Index: lib/DebugInfo/CodeView/TypeDumpVisitor.cpp =================================================================== --- lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -106,6 +106,7 @@ static const EnumEntry TypeModifierNames[] = { ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile), ENUM_ENTRY(ModifierOptions, Unaligned), + ENUM_ENTRY(ModifierOptions, Restrict), }; static const EnumEntry CallingConventions[] = { @@ -370,6 +371,7 @@ W->printNumber("IsConst", Ptr.isConst()); W->printNumber("IsVolatile", Ptr.isVolatile()); W->printNumber("IsUnaligned", Ptr.isUnaligned()); + W->printNumber("IsRestrict", Ptr.isRestrict()); W->printNumber("SizeOf", Ptr.getSize()); if (Ptr.isPointerToMember()) { Index: lib/ObjectYAML/CodeViewYAMLTypes.cpp =================================================================== --- lib/ObjectYAML/CodeViewYAMLTypes.cpp +++ lib/ObjectYAML/CodeViewYAMLTypes.cpp @@ -343,6 +343,7 @@ IO.bitSetCase(Options, "Const", ModifierOptions::Const); IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile); IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned); + IO.bitSetCase(Options, "Restrict", ModifierOptions::Restrict); } void ScalarBitSetTraits::bitset(IO &IO, Index: test/DebugInfo/COFF/modifiers.ll =================================================================== --- /dev/null +++ test/DebugInfo/COFF/modifiers.ll @@ -0,0 +1,248 @@ +; RUN: llc < %s -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +; C++ source to regenerate: +; $ cat m.cpp +; union Union { +; int * __restrict x; +; float * __restrict y; +; }; +; int f() { +; Union u; +; const int *p; +; const volatile int v = 0; +; int* volatile __restrict m; +; return 1; +; } +; void g() { +; const int x = 10; +; const char s[] = "abc"; +; } +; $ clang m.cpp -S -emit-llvm -g -gcodeview -o m.ll + +; CHECK: CodeViewTypes [ +; CHECK: Section: .debug$T (7) +; CHECK: Magic: 0x4 +; CHECK: ArgList (0x1000) { +; CHECK: TypeLeafKind: LF_ARGLIST (0x1201) +; CHECK: NumArgs: 0 +; CHECK: Arguments [ +; CHECK: ] +; CHECK: } +; CHECK: Procedure (0x1001) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: int (0x74) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 0 +; CHECK: ArgListType: () (0x1000) +; CHECK: } +; CHECK: FuncId (0x1002) { +; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK: ParentScope: 0x0 +; CHECK: FunctionType: int () (0x1001) +; CHECK: Name: f +; CHECK: } +; CHECK: Union (0x1003) { +; CHECK: TypeLeafKind: LF_UNION (0x1506) +; CHECK: MemberCount: 0 +; CHECK: Properties [ (0x280) +; CHECK: ForwardReference (0x80) +; CHECK: HasUniqueName (0x200) +; CHECK: ] +; CHECK: FieldList: 0x0 +; CHECK: SizeOf: 0 +; CHECK: Name: Union +; CHECK: LinkageName: .?ATUnion@@ +; CHECK: } +; CHECK: Modifier (0x1004) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: int* (0x674) +; CHECK: Modifiers [ (0x8) +; CHECK: Restrict (0x8) +; CHECK: ] +; CHECK: } +; CHECK: Modifier (0x1005) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: float* (0x640) +; CHECK: Modifiers [ (0x8) +; CHECK: Restrict (0x8) +; CHECK: ] +; CHECK: } +; CHECK: FieldList (0x1006) { +; CHECK: TypeLeafKind: LF_FIELDLIST (0x1203) +; CHECK: DataMember { +; CHECK: TypeLeafKind: LF_MEMBER (0x150D) +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: int* __restrict (0x1004) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: x +; CHECK: } +; CHECK: DataMember { +; CHECK: TypeLeafKind: LF_MEMBER (0x150D) +; CHECK: AccessSpecifier: Public (0x3) +; CHECK: Type: float* __restrict (0x1005) +; CHECK: FieldOffset: 0x0 +; CHECK: Name: y +; CHECK: } +; CHECK: } + +; CHECK: Modifier (0x100A) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: int (0x74) +; CHECK: Modifiers [ (0x1) +; CHECK: Const (0x1) +; CHECK: ] +; CHECK: } +; CHECK: Pointer (0x100B) { +; CHECK: TypeLeafKind: LF_POINTER (0x1002) +; CHECK: PointeeType: const int (0x100A) +; CHECK: PointerAttributes: 0x1000C +; CHECK: PtrType: Near64 (0xC) +; CHECK: PtrMode: Pointer (0x0) +; CHECK: IsFlat: 0 +; CHECK: IsConst: 0 +; CHECK: IsVolatile: 0 +; CHECK: IsUnaligned: 0 +; CHECK: IsRestrict: 0 +; CHECK: SizeOf: 8 +; CHECK: } +; CHECK: Modifier (0x100C) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: int (0x74) +; CHECK: Modifiers [ (0x3) +; CHECK: Const (0x1) +; CHECK: Volatile (0x2) +; CHECK: ] +; CHECK: } +; CHECK: Modifier (0x100D) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: int* (0x674) +; CHECK: Modifiers [ (0xA) +; CHECK: Restrict (0x8) +; CHECK: Volatile (0x2) +; CHECK: ] +; CHECK: } +; CHECK: Procedure (0x100E) { +; CHECK: TypeLeafKind: LF_PROCEDURE (0x1008) +; CHECK: ReturnType: void (0x3) +; CHECK: CallingConvention: NearC (0x0) +; CHECK: FunctionOptions [ (0x0) +; CHECK: ] +; CHECK: NumParameters: 0 +; CHECK: ArgListType: () (0x1000) +; CHECK: } +; CHECK: FuncId (0x100F) { +; CHECK: TypeLeafKind: LF_FUNC_ID (0x1601) +; CHECK: ParentScope: 0x0 +; CHECK: FunctionType: void () (0x100E) +; CHECK: Name: g +; CHECK: } +; CHECK: Modifier (0x1010) { +; CHECK: TypeLeafKind: LF_MODIFIER (0x1001) +; CHECK: ModifiedType: char (0x70) +; CHECK: Modifiers [ (0x1) +; CHECK: Const (0x1) +; CHECK: ] +; CHECK: } +; CHECK: Array (0x1011) { +; CHECK: TypeLeafKind: LF_ARRAY (0x1503) +; CHECK: ElementType: const char (0x1010) +; CHECK: IndexType: unsigned __int64 (0x23) +; CHECK: SizeOf: 4 +; CHECK: Name: +; CHECK: } +; CHECK: ] + +; ModuleID = 'm.cpp' +source_filename = "m.cpp" +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc19.11.25507" + +%union.Union = type { i32* } + +@"\01?s@?1??g@@YAXXZ@3QBDB" = internal constant [4 x i8] c"abc\00", align 1, !dbg !0 + +; Function Attrs: noinline nounwind optnone uwtable +define i32 @"\01?f@@YAHXZ"() #0 !dbg !19 { +entry: + %u = alloca %union.Union, align 8 + %p = alloca i32*, align 8 + %v = alloca i32, align 4 + %m = alloca i32*, align 8 + call void @llvm.dbg.declare(metadata %union.Union* %u, metadata !23, metadata !DIExpression()), !dbg !33 + call void @llvm.dbg.declare(metadata i32** %p, metadata !34, metadata !DIExpression()), !dbg !37 + call void @llvm.dbg.declare(metadata i32* %v, metadata !38, metadata !DIExpression()), !dbg !41 + store volatile i32 0, i32* %v, align 4, !dbg !41 + call void @llvm.dbg.declare(metadata i32** %m, metadata !42, metadata !DIExpression()), !dbg !44 + ret i32 1, !dbg !45 +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind optnone uwtable +define void @"\01?g@@YAXXZ"() #0 !dbg !2 { +entry: + %x = alloca i32, align 4 + call void @llvm.dbg.declare(metadata i32* %x, metadata !46, metadata !DIExpression()), !dbg !47 + store i32 10, i32* %x, align 4, !dbg !47 + ret void, !dbg !48 +} + +attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable } + +!llvm.dbg.cu = !{!6} +!llvm.module.flags = !{!14, !15, !16, !17} +!llvm.ident = !{!18} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "s", scope: !2, file: !3, line: 17, type: !9, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "g", linkageName: "\01?g@@YAXXZ", scope: !3, file: !3, line: 15, type: !4, isLocal: false, isDefinition: true, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: false, unit: !6, variables: !7) +!3 = !DIFile(filename: "m.cpp", directory: "D:\5Cupstream\5Cllvm\5Ctest\5CDebugInfo\5CCOFF", checksumkind: CSK_MD5, checksum: "4b83b3746efa1ba3d647fa4b6129139f") +!4 = !DISubroutineType(types: !5) +!5 = !{null} +!6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8) +!7 = !{} +!8 = !{!0} +!9 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, elements: !12) +!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11) +!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!12 = !{!13} +!13 = !DISubrange(count: 4) +!14 = !{i32 2, !"CodeView", i32 1} +!15 = !{i32 2, !"Debug Info Version", i32 3} +!16 = !{i32 1, !"wchar_size", i32 2} +!17 = !{i32 7, !"PIC Level", i32 2} +!18 = !{!"clang version 7.0.0 "} +!19 = distinct !DISubprogram(name: "f", linkageName: "\01?f@@YAHXZ", scope: !3, file: !3, line: 8, type: !20, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !6, variables: !7) +!20 = !DISubroutineType(types: !21) +!21 = !{!22} +!22 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!23 = !DILocalVariable(name: "u", scope: !19, file: !3, line: 9, type: !24) +!24 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "Union", file: !3, line: 4, size: 64, flags: DIFlagTypePassByValue, elements: !25, identifier: ".?ATUnion@@") +!25 = !{!26, !29} +!26 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !24, file: !3, line: 5, baseType: !27, size: 64) +!27 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !28) +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64) +!29 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !24, file: !3, line: 6, baseType: !30, size: 64) +!30 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !31) +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) +!32 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) +!33 = !DILocation(line: 9, column: 10, scope: !19) +!34 = !DILocalVariable(name: "p", scope: !19, file: !3, line: 10, type: !35) +!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !36, size: 64) +!36 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !22) +!37 = !DILocation(line: 10, column: 15, scope: !19) +!38 = !DILocalVariable(name: "v", scope: !19, file: !3, line: 11, type: !39) +!39 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !40) +!40 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !22) +!41 = !DILocation(line: 11, column: 23, scope: !19) +!42 = !DILocalVariable(name: "m", scope: !19, file: !3, line: 12, type: !43) +!43 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !27) +!44 = !DILocation(line: 12, column: 29, scope: !19) +!45 = !DILocation(line: 13, column: 4, scope: !19) +!46 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 16, type: !36) +!47 = !DILocation(line: 16, column: 14, scope: !2) +!48 = !DILocation(line: 18, column: 2, scope: !2) Index: tools/llvm-pdbutil/PrettyFunctionDumper.cpp =================================================================== --- tools/llvm-pdbutil/PrettyFunctionDumper.cpp +++ tools/llvm-pdbutil/PrettyFunctionDumper.cpp @@ -252,6 +252,9 @@ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; PointeeType->dump(*this); Printer << (Symbol.isReference() ? "&" : "*"); + + if (Symbol.getRawSymbol().isRestrictedType()) + WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict"; } }