Defaulting to -Xclang -coverage-version='407*' makes .gcno/.gcda compatible with gcov [4.7,8) In addition, delete clang::CodeGenOptionsBase::CoverageExtraChecksum and GCOVOptions::UseCfgChecksum. We can infer the information from the version. With this change, .gcda files produced by `clang --coverage a.o` linked executable can be read by gcov 4.7~7. We don't need other -Xclang -coverage* options. There may be a mismatching version warning, though. (Note, GCC r173147 "split checksum into cfg checksum and line checksum" made gcov 4.7 incompatible with previous versions.)
115 lines
6.8 KiB
LLVM
115 lines
6.8 KiB
LLVM
; Test that GCOV instrumentation numbers functions correctly when some
|
|
; functions aren't emitted.
|
|
|
|
; Inject metadata to set the .gcno file location
|
|
; RUN: rm -rf %t && mkdir -p %t
|
|
; RUN: echo '!14 = !{!"%/t/function-numbering.ll", !0}' > %t/1
|
|
; RUN: cat %s %t/1 > %t/2
|
|
|
|
; RUN: opt -insert-gcov-profiling -S < %t/2 | FileCheck --check-prefix GCDA %s
|
|
; RUN: llvm-cov gcov -n -dump %t/function-numbering.gcno 2>&1 | FileCheck --check-prefix GCNO %s
|
|
; RUNN: rm %t/function-numbering.gcno
|
|
|
|
; RUN: opt -passes=insert-gcov-profiling -S < %t/2 | FileCheck --check-prefix GCDA %s
|
|
; RUN: llvm-cov gcov -n -dump %t/function-numbering.gcno 2>&1 | FileCheck --check-prefix GCNO %s
|
|
|
|
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-apple-macosx10.10.0"
|
|
|
|
; GCDA: @__llvm_internal_gcov_emit_function_args.0 = internal unnamed_addr constant
|
|
; GCDA-SAME: { i32 0,
|
|
; GCDA-SAME: { i32 1,
|
|
;
|
|
; GCDA-LABEL: define internal void @__llvm_gcov_writeout() {{.*}} {
|
|
; GCDA-NEXT: entry:
|
|
; GCDA-NEXT: br label %[[FILE_LOOP_HEADER:.*]]
|
|
;
|
|
; GCDA: [[FILE_LOOP_HEADER]]:
|
|
; GCDA-NEXT: %[[IV:.*]] = phi i32 [ 0, %entry ], [ %[[NEXT_IV:.*]], %[[FILE_LOOP_LATCH:.*]] ]
|
|
; GCDA-NEXT: %[[FILE_INFO:.*]] = getelementptr inbounds {{.*}}, {{.*}}* @__llvm_internal_gcov_emit_file_info, i32 0, i32 %[[IV]]
|
|
; GCDA-NEXT: %[[START_FILE_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 0
|
|
; GCDA-NEXT: %[[START_FILE_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 0
|
|
; GCDA-NEXT: %[[START_FILE_ARG_0:.*]] = load i8*, i8** %[[START_FILE_ARG_0_PTR]]
|
|
; GCDA-NEXT: %[[START_FILE_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 1
|
|
; GCDA-NEXT: %[[START_FILE_ARG_1:.*]] = load i8*, i8** %[[START_FILE_ARG_1_PTR]]
|
|
; GCDA-NEXT: %[[START_FILE_ARG_2_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[START_FILE_ARGS]], i32 0, i32 2
|
|
; GCDA-NEXT: %[[START_FILE_ARG_2:.*]] = load i32, i32* %[[START_FILE_ARG_2_PTR]]
|
|
; GCDA-NEXT: call void @llvm_gcda_start_file(i8* %[[START_FILE_ARG_0]], i8* %[[START_FILE_ARG_1]], i32 %[[START_FILE_ARG_2]])
|
|
; GCDA-NEXT: %[[NUM_COUNTERS_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 1
|
|
; GCDA-NEXT: %[[NUM_COUNTERS:.*]] = load i32, i32* %[[NUM_COUNTERS_PTR]]
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARGS_ARRAY_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 2
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARGS_ARRAY:.*]] = load {{.*}}*, {{.*}}** %[[EMIT_FUN_ARGS_ARRAY_PTR]]
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARGS_ARRAY_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[FILE_INFO]], i32 0, i32 3
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARGS_ARRAY:.*]] = load {{.*}}*, {{.*}}** %[[EMIT_ARCS_ARGS_ARRAY_PTR]]
|
|
; GCDA-NEXT: %[[ENTER_COUNTER_LOOP_COND:.*]] = icmp slt i32 0, %[[NUM_COUNTERS]]
|
|
; GCDA-NEXT: br i1 %[[ENTER_COUNTER_LOOP_COND]], label %[[COUNTER_LOOP:.*]], label %[[FILE_LOOP_LATCH]]
|
|
;
|
|
; GCDA: [[COUNTER_LOOP]]:
|
|
; GCDA-NEXT: %[[JV:.*]] = phi i32 [ 0, %[[FILE_LOOP_HEADER]] ], [ %[[NEXT_JV:.*]], %[[COUNTER_LOOP]] ]
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS_ARRAY]], i32 %[[JV]]
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 0
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_0:.*]] = load i32, i32* %[[EMIT_FUN_ARG_0_PTR]]
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 1
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_1:.*]] = load i32, i32* %[[EMIT_FUN_ARG_1_PTR]]
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_2_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_FUN_ARGS]], i32 0, i32 2
|
|
; GCDA-NEXT: %[[EMIT_FUN_ARG_2:.*]] = load i32, i32* %[[EMIT_FUN_ARG_2_PTR]]
|
|
; GCDA-NEXT: call void @llvm_gcda_emit_function(i32 %[[EMIT_FUN_ARG_0]],
|
|
; GCDA-SAME: i32 %[[EMIT_FUN_ARG_1]],
|
|
; GCDA-SAME: i32 %[[EMIT_FUN_ARG_2]])
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARGS:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS_ARRAY]], i32 %[[JV]]
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARG_0_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS]], i32 0, i32 0
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARG_0:.*]] = load i32, i32* %[[EMIT_ARCS_ARG_0_PTR]]
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARG_1_PTR:.*]] = getelementptr inbounds {{.*}}, {{.*}}* %[[EMIT_ARCS_ARGS]], i32 0, i32 1
|
|
; GCDA-NEXT: %[[EMIT_ARCS_ARG_1:.*]] = load i64*, i64** %[[EMIT_ARCS_ARG_1_PTR]]
|
|
; GCDA-NEXT: call void @llvm_gcda_emit_arcs(i32 %[[EMIT_ARCS_ARG_0]],
|
|
; GCDA-SAME: i64* %[[EMIT_ARCS_ARG_1]])
|
|
; GCDA-NEXT: %[[NEXT_JV]] = add i32 %[[JV]], 1
|
|
; GCDA-NEXT: %[[COUNTER_LOOP_COND:.*]] = icmp slt i32 %[[NEXT_JV]], %[[NUM_COUNTERS]]
|
|
; GCDA-NEXT: br i1 %[[COUNTER_LOOP_COND]], label %[[COUNTER_LOOP]], label %[[FILE_LOOP_LATCH]]
|
|
;
|
|
; GCDA: [[FILE_LOOP_LATCH]]:
|
|
; GCDA-NEXT: call void @llvm_gcda_summary_info()
|
|
; GCDA-NEXT: call void @llvm_gcda_end_file()
|
|
; GCDA-NEXT: %[[NEXT_IV]] = add i32 %[[IV]], 1
|
|
; GCDA-NEXT: %[[FILE_LOOP_COND:.*]] = icmp slt i32 %[[NEXT_IV]], 1
|
|
; GCDA-NEXT: br i1 %[[FILE_LOOP_COND]], label %[[FILE_LOOP_HEADER]], label %[[EXIT:.*]]
|
|
;
|
|
; GCDA: [[EXIT]]:
|
|
; GCDA-NEXT: ret void
|
|
|
|
; GCNO: == foo (0) @
|
|
; GCNO-NOT: == bar ({{[0-9]+}}) @
|
|
; GCNO: == baz (1) @
|
|
|
|
define void @foo() !dbg !4 {
|
|
ret void, !dbg !12
|
|
}
|
|
|
|
define void @bar() !dbg !7 {
|
|
; This function is referenced by the debug info, but no lines have locations.
|
|
ret void
|
|
}
|
|
|
|
define void @baz() !dbg !8 {
|
|
ret void, !dbg !13
|
|
}
|
|
|
|
!llvm.gcov = !{!14}
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!9, !10}
|
|
!llvm.ident = !{!11}
|
|
|
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 3.6.0 ", isOptimized: false, emissionKind: LineTablesOnly, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
|
|
!1 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/function-numbering.ll", directory: "")
|
|
!2 = !{}
|
|
!4 = distinct !DISubprogram(name: "foo", line: 1, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 1, file: !1, scope: !5, type: !6, retainedNodes: !2)
|
|
!5 = !DIFile(filename: ".../llvm/test/Transforms/GCOVProfiling/function-numbering.ll", directory: "")
|
|
!6 = !DISubroutineType(types: !2)
|
|
!7 = distinct !DISubprogram(name: "bar", line: 2, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 2, file: !1, scope: !5, type: !6, retainedNodes: !2)
|
|
!8 = distinct !DISubprogram(name: "baz", line: 3, isLocal: false, isDefinition: true, isOptimized: false, unit: !0, scopeLine: 3, file: !1, scope: !5, type: !6, retainedNodes: !2)
|
|
!9 = !{i32 2, !"Dwarf Version", i32 2}
|
|
!10 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!11 = !{!"clang version 3.6.0 "}
|
|
!12 = !DILocation(line: 1, column: 13, scope: !4)
|
|
!13 = !DILocation(line: 3, column: 13, scope: !8)
|