Hi, The attached patch implemented GPROF (ie. -pg) support in clang.
It introduces GPROFInstrument CodeGenOption and sets it when -pg is specified. The FreeBSD ::Link() method was adjusted to link the correct libraries when -pg is specified. Finally, CodeGen was modified to emit calls to "mcount" (the actual name differs between arch/OS tuples) at the start of the function body. This patch is quite FreeBSD specific (the driver modification and the mcount name selection) but adding other OSes should be trivial once this is commited. Please review! roman
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h (revision 123975)
+++ include/clang/Frontend/CodeGenOptions.h (working copy)
@@ -56,6 +56,7 @@
unsigned HiddenWeakVTables : 1; /// Emit weak vtables, RTTI, and thunks with
/// hidden visibility
unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled
+ unsigned GPROFInstrument : 1; /// Set when -pg is enabled
unsigned LessPreciseFPMAD : 1; /// Enable less precise MAD instructions to be
/// generated.
unsigned MergeAllConstants : 1; /// Merge identical constants.
@@ -125,6 +126,7 @@
HiddenWeakTemplateVTables = 0;
HiddenWeakVTables = 0;
InstrumentFunctions = 0;
+ GPROFInstrument = 0;
LessPreciseFPMAD = 0;
MergeAllConstants = 1;
NoCommon = 0;
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td (revision 123975)
+++ include/clang/Driver/CC1Options.td (working copy)
@@ -183,6 +183,7 @@
HelpText<"Emit complete constructors and destructors as aliases when possible">;
def O : Joined<"-O">, HelpText<"Optimization level">;
def Os : Flag<"-Os">, HelpText<"Optimize for size">;
+def pg : Flag<"-pg">, HelpText<"GPROF">;
//===----------------------------------------------------------------------===//
// Dependency Output Options
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp (revision 123975)
+++ lib/Frontend/CompilerInvocation.cpp (working copy)
@@ -925,6 +925,7 @@
Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
+ Opts.GPROFInstrument = Args.hasArg(OPT_pg);
if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
llvm::StringRef Name = A->getValue(Args);
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp (revision 123975)
+++ lib/Driver/Tools.cpp (working copy)
@@ -1280,6 +1280,7 @@
Args.AddLastArg(CmdArgs, options::OPT_femit_all_decls);
Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions);
Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info);
+ Args.AddLastArg(CmdArgs, options::OPT_pg);
// -flax-vector-conversions is default.
if (!Args.hasFlag(options::OPT_flax_vector_conversions,
@@ -1710,13 +1711,10 @@
C.addCommand(new Command(JA, *this, Exec, CmdArgs));
- // Explicitly warn that these options are unsupported, even though
- // we are allowing compilation to continue.
- for (arg_iterator it = Args.filtered_begin(options::OPT_pg),
- ie = Args.filtered_end(); it != ie; ++it) {
- (*it)->claim();
- D.Diag(clang::diag::warn_drv_clang_unsupported) << (*it)->getAsString(Args);
- }
+ if (Arg *A = Args.getLastArg(options::OPT_pg))
+ if (Args.hasArg(options::OPT_fomit_frame_pointer))
+ D.Diag(clang::diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args) << "-fomit-frame-pointer";
// Claim some arguments which clang supports automatically.
@@ -3148,9 +3146,13 @@
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nostartfiles)) {
if (!Args.hasArg(options::OPT_shared)) {
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("gcrt1.o")));
+ else
+ CmdArgs.push_back(Args.MakeArgString(
+ getToolChain().GetFilePath("crt1.o")));
CmdArgs.push_back(Args.MakeArgString(
- getToolChain().GetFilePath("crt1.o")));
- CmdArgs.push_back(Args.MakeArgString(
getToolChain().GetFilePath("crti.o")));
CmdArgs.push_back(Args.MakeArgString(
getToolChain().GetFilePath("crtbegin.o")));
@@ -3176,13 +3178,21 @@
!Args.hasArg(options::OPT_nodefaultlibs)) {
if (D.CCCIsCXX) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
- CmdArgs.push_back("-lm");
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lm_p");
+ else
+ CmdArgs.push_back("-lm");
}
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
- CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lgcc_p");
+ else
+ CmdArgs.push_back("-lgcc");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
@@ -3190,12 +3200,26 @@
}
if (Args.hasArg(options::OPT_pthread))
- CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lc");
+ if (Args.hasArg(options::OPT_pg))
+ CmdArgs.push_back("-lpthread_p");
+ else
+ CmdArgs.push_back("-lpthread");
- CmdArgs.push_back("-lgcc");
+ if (Args.hasArg(options::OPT_pg)) {
+ if (Args.hasArg(options::OPT_shared))
+ CmdArgs.push_back("-lc");
+ else
+ CmdArgs.push_back("-lc_p");
+ CmdArgs.push_back("-lgcc_p");
+ } else {
+ CmdArgs.push_back("-lc");
+ CmdArgs.push_back("-lgcc");
+ }
+
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
+ } else if (Args.hasArg(options::OPT_pg)) {
+ CmdArgs.push_back("-lgcc_eh_p");
} else {
CmdArgs.push_back("--as-needed");
CmdArgs.push_back("-lgcc_s");
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp (revision 123975)
+++ lib/CodeGen/CodeGenFunction.cpp (working copy)
@@ -214,6 +214,45 @@
CallSite);
}
+void CodeGenFunction::EmitGPROFInstrumentation() {
+ if (!CGM.getCodeGenOpts().GPROFInstrument)
+ return;
+
+ const char *mcountName = NULL;
+
+ // TODO: fill in more stuff
+ switch (Target.getTriple().getOS()) {
+ default:
+ mcountName = ".mcount";
+ break;
+ case llvm::Triple::FreeBSD:
+ switch (Target.getTriple().getArch()) {
+ default:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ mcountName = ".mcount";
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ mcountName = "_mcount";
+ break;
+ case llvm::Triple::arm:
+ mcountName = "__mcount";
+ break;
+
+ }
+ break;
+ }
+
+ llvm::FunctionType *FTy =
+ llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false);
+
+ llvm::Constant *MCountFn = CGM.CreateRuntimeFunction(FTy, mcountName);
+ Builder.CreateCall(MCountFn);
+}
+
void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
llvm::Function *Fn,
const FunctionArgList &Args,
@@ -264,6 +303,8 @@
EmitFunctionInstrumentation("__cyg_profile_func_enter");
+ EmitGPROFInstrumentation();
+
// FIXME: Leaked.
// CC info is ignored, hopefully?
CurFnInfo = &CGM.getTypes().getFunctionInfo(FnRetTy, Args,
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h (revision 123975)
+++ lib/CodeGen/CodeGenFunction.h (working copy)
@@ -907,6 +907,9 @@
/// function instrumentation is enabled.
void EmitFunctionInstrumentation(const char *Fn);
+ /// EmitGPROFInstrumentation - Emit all to .mcount.
+ void EmitGPROFInstrumentation();
+
/// EmitFunctionProlog - Emit the target specific LLVM code to load the
/// arguments for the given function. This is also responsible for naming the
/// LLVM function arguments.
pgpiIvmDWmLUk.pgp
Description: PGP signature
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
