--- /dev/null
+//===- Transforms/GCOVProfiler.h - GCOVProfiler pass ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file provides the interface for the GCOV style profiler pass.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_GCOVPROFILER_H
+#define LLVM_TRANSFORMS_GCOVPROFILER_H
+
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+namespace llvm {
+/// The gcov-style instrumentation pass
+class GCOVProfilerPass : public PassInfoMixin<GCOVProfilerPass> {
+public:
+ GCOVProfilerPass(const GCOVOptions &Options = GCOVOptions::getDefault()) : GCOVOpts(Options) { }
+ PreservedAnalyses run(Module &M, AnalysisManager<Module> &AM);
+
+private:
+ GCOVOptions GCOVOpts;
+};
+
+} // End llvm namespace
+#endif
#include "llvm/Support/Debug.h"
#include "llvm/Support/Regex.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/GCOVProfiler.h"
#include "llvm/Transforms/IPO/ConstantMerge.h"
#include "llvm/Transforms/IPO/ElimAvailExtern.h"
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
MODULE_PASS("globaldce", GlobalDCEPass())
MODULE_PASS("globalopt", GlobalOptPass())
MODULE_PASS("inferattrs", InferFunctionAttrsPass())
+MODULE_PASS("insert-gcov-profiling", GCOVProfilerPass())
MODULE_PASS("internalize", InternalizePass())
MODULE_PASS("instrprof", InstrProfiling())
MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Instrumentation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/GCOVProfiler.h"
+#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <algorithm>
#include <memory>
return false;
}
+PreservedAnalyses GCOVProfilerPass::run(Module &M,
+ AnalysisManager<Module> &AM) {
+
+ GCOVProfiler Profiler(GCOVOpts);
+
+ if (!Profiler.runOnModule(M))
+ return PreservedAnalyses::all();
+
+ return PreservedAnalyses::none();
+}
+
static bool functionHasLines(Function &F) {
// Check whether this function actually has any source lines. Not only
// do these waste space, they also can crash gcov.
; RUN: opt -insert-gcov-profiling -S < %t2 | 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 < %t2 | 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"
; RUN: not grep '_GLOBAL__sub_I_global-ctor' %T/global-ctor.gcno
; RUN: rm %T/global-ctor.gcno
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t2
+; RUN: not grep '_GLOBAL__sub_I_global-ctor' %T/global-ctor.gcno
+; RUN: rm %T/global-ctor.gcno
+
@x = global i32 0, align 4
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_global-ctor.ll, i8* null }]
; RUN: sed -e 's|PATTERN|%/T|g' %s | opt -insert-gcov-profiling -disable-output
; RUN: rm %T/linezero.gcno
+; RUN: sed -e 's|PATTERN|%/T|g' %s | opt -passes=insert-gcov-profiling -disable-output
+; RUN: rm %T/linezero.gcno
+
; This is a crash test.
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; RUN: grep _Z3foov %T/linkagename.gcno
; RUN: rm %T/linkagename.gcno
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t2
+; RUN: grep _Z3foov %T/linkagename.gcno
+; RUN: rm %T/linkagename.gcno
+
define void @_Z3foov() !dbg !5 {
entry:
ret void, !dbg !8
; RUN: opt -insert-gcov-profiling -o - < %s | llvm-dis | FileCheck -check-prefix=EMIT-ARCS %s
+; RUN: opt -passes=insert-gcov-profiling -o - < %s | llvm-dis | FileCheck -check-prefix=EMIT-ARCS %s
; EMIT-ARCS-NOT: call void @llvm_gcda_start_file
; But we can optionally emit it second, to match newer gcc versions.
; RUN: opt -insert-gcov-profiling -gcov-exit-block-before-body -disable-output %t2
; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-SECOND %s
+; RUN: rm %T/return-block.gcno
+
+; By default, the return block is last.
+; RUN: opt -passes=insert-gcov-profiling -disable-output %t2
+; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-LAST %s
+
+; But we can optionally emit it second, to match newer gcc versions.
+; RUN: opt -passes=insert-gcov-profiling -gcov-exit-block-before-body -disable-output %t2
+; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-SECOND %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; RUN: head -c8 %T/version.gcno | grep '^oncg.704'
; RUN: rm %T/version.gcno
+; RUN: opt -passes=insert-gcov-profiling -disable-output < %t2
+; RUN: head -c8 %T/version.gcno | grep '^oncg.204'
+; RUN: rm %T/version.gcno
+; RUN: not opt -passes=insert-gcov-profiling -default-gcov-version=asdfasdf -disable-output < %t2
+; RUN: opt -passes=insert-gcov-profiling -default-gcov-version=407* -disable-output < %t2
+; RUN: head -c8 %T/version.gcno | grep '^oncg.704'
+; RUN: rm %T/version.gcno
+
define void @test() !dbg !5 {
ret void, !dbg !8
}