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.

Attachment: pgpiIvmDWmLUk.pgp
Description: PGP signature

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to