gollvm: tools cleanup

Delete wrapper script (no longer needed). Relocate helper program
capture-fcn-attributes.go from driver subdir to tools subdir (makes
more sense to have it there).

Change-Id: I383e4e90ff6f419d7d710abc3c9808bf9b500c65
Reviewed-on: https://go-review.googlesource.com/c/159100
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/driver/capture-fcn-attributes.go b/tools/capture-fcn-attributes.go
similarity index 100%
rename from driver/capture-fcn-attributes.go
rename to tools/capture-fcn-attributes.go
diff --git a/tools/gollvm-wrap.py b/tools/gollvm-wrap.py
deleted file mode 100755
index 2a5844f..0000000
--- a/tools/gollvm-wrap.py
+++ /dev/null
@@ -1,384 +0,0 @@
-#!/usr/bin/python
-"""Wrapper to selectively run gollvm instead of gccgo.
-
-This is a shim script that intercepts invocations of 'gccgo' and then
-in turn invokes either the real gccgo driver or a copy of gollvm
-instead, depending on the arguments and on environment variables.
-
-When performing a Go build with gccgo, the Go command will typically
-invoke gccgo once for each compilation step, which might look like
-
-  gccgo -I ... -o objfile.o -g <options> file.go file2.go ... fileN.go
-
-and then a final invocation will be made at the link step, e.g.
-
-  gccgo -L ... somearchive.a ... -o binary
-
-The goal of this shim is to convert invocations of the first form to
-llvm-goc invocations, and to ignore invocations of the second form
-and just pass them on to gccgo.
-
-We also tack on a set of additional "-L" options to the llvm-goc
-invocation so that it can find the go runtime libraries, and intercept
-the "-o" option so that we can run the asembler afterwards.
-
-To use this script, you will need a copy of GCCGO, e.g. the directory
-produced by running "make all && make install" in a GCCGO build tree.
-From within the gccgo install dir, run
-
-   gollvm-wrap.py --install
-
-This will modify the install directory to insert the wrapper into the
-compilation path.
-
-"""
-
-import getopt
-import os
-import re
-import subprocess
-import sys
-import tempfile
-
-import script_utils as u
-
-# Echo command before executing
-flag_echo = True
-
-# Dry run mode
-flag_dryrun = False
-
-# gccgo only mode
-flag_nollvm = False
-
-# never invoke the real gccgo
-flag_alwaysllvm = False
-
-# trace llvm-goc invocations
-flag_trace_llinvoc = False
-
-
-def docmd(cmd):
-  """Execute a command."""
-  if flag_echo:
-    sys.stderr.write("executing: " + cmd + "\n")
-  if flag_dryrun:
-    return
-  u.docmd(cmd)
-
-
-def form_golibargs(driver):
-  """Form correct go library args."""
-  ddir = os.path.dirname(driver)
-  bdir = os.path.dirname(ddir)
-  cmd = "find %s/lib64 -name runtime.gox -print" % bdir
-  lines = u.docmdlines(cmd)
-  if not lines:
-    u.error("no output from %s -- bad gccgo install dir?" % cmd)
-  line = lines[0]
-  rdir = os.path.dirname(line)
-  u.verbose(1, "libdir is %s" % rdir)
-  return rdir
-
-
-def perform():
-  """Main driver routine."""
-  global flag_trace_llinvoc
-
-  u.verbose(1, "argv: %s" % " ".join(sys.argv))
-
-  # llvm-goc should be available somewhere in PATH, error if not
-  lines = u.docmdlines("which llvm-goc", True)
-  if not lines:
-    u.error("no 'llvm-goc' in PATH -- can't proceed")
-
-  # Bypass the whole mess if -A
-  if flag_alwaysllvm:
-    a = sys.argv
-    a[0] = "llvm-goc"
-    driver = "llvm-goc"
-    rc = subprocess.call(a)
-    if rc != 0:
-      u.verbose(1, "return code %d from %s" % (rc, " ".join(a)))
-      return 1
-    return 0
-
-  # Perform a walk of the command line arguments looking for Go files.
-  reg = re.compile(r"^(\S+)\.go$")
-  gofile = None
-  basename = None
-  for clarg in sys.argv[1:]:
-    m = reg.match(clarg)
-    if m:
-      gofile = clarg
-      basename = m.group(1)
-      break
-
-  if not gofile or flag_nollvm:
-    # No go files. Invoke real gccgo.
-    bd = os.path.dirname(sys.argv[0])
-    driver = "%s/gccgo.real" % bd
-    u.verbose(1, "driver path is %s" % driver)
-    args = [sys.argv[0]] + sys.argv[1:]
-    u.verbose(1, "args: '%s'" % " ".join(args))
-    if not os.path.exists(driver):
-      usage("internal error: %s does not exist [most likely this "
-            "script was not installed correctly]" % driver)
-    os.execv(driver, args)
-    u.error("exec failed: %s" % driver)
-
-  # Create a set of massaged args.
-  nargs = []
-  skipc = 0
-  outfile = None
-  linkoutfile = None
-  minus_s = False
-  minus_v = False
-  minus_c = False
-  ofiles = []
-  ldflags = []
-  largsSeen = False
-  for ii in range(1, len(sys.argv)):
-    clarg = sys.argv[ii]
-    if skipc != 0:
-      skipc -= 1
-      continue
-    if clarg == "-S":
-      minus_s = True
-    if clarg == "-c":
-      minus_c = True
-    if clarg == "-o":
-      outfile = sys.argv[ii+1]
-      skipc = 1
-      continue
-    if clarg.startswith("-L"):
-      largsSeen = True
-    if clarg == "-v":
-      flag_trace_llinvoc = True
-      minus_v = True
-
-    # redirect some gcc flags to the ones gollvm uses
-    if clarg == "-w":
-      clarg = "-no-warn"
-
-    # dummy flags that are not supported by gollvm
-    if clarg == "-lm":
-      continue  # TODO: if the linker is invoked, pass this to the linker?
-    if clarg == "-fbounds-check":
-      continue
-    if clarg == "-finline-functions":
-      continue
-    if clarg == "-fno-diagnostics-show-caret":
-      continue
-    if clarg == "-fno-toplevel-reorder":
-      continue
-    if clarg == "-fno-var-tracking-assignments":
-      continue
-    if clarg == "-fomit-frame-pointer":
-      continue
-    if clarg == "-funroll-loops":
-      continue
-    if clarg == "-funsafe-math-optimizations":
-      continue
-    if clarg == "-gno-record-gcc-switches":
-      continue
-    if clarg == "-mfancy-math-387":
-      continue
-    if clarg == "-minline-all-stringops":
-      continue
-    if clarg == "-pedantic-errors":
-      continue
-    if clarg.startswith("-fdiagnostics-color"):
-      continue
-    if clarg.startswith("-fdebug-prefix-map"):
-      continue
-
-    # skip .o and .a files in compilation, but record
-    # them for linker invocation.
-    if clarg.endswith(".o"):
-      ofiles.append(clarg)
-      continue
-    if clarg.endswith(".a"):
-      ofiles.append(clarg)
-      continue
-
-    if clarg == "-static":
-      ldflags.append(clarg)
-      continue
-    if clarg == "-static-libgo":
-      ldflags.append(clarg)
-      continue
-    if clarg == "-static-libstdc++":
-      ldflags.append(clarg)
-      continue
-    if clarg == "-static-libgcc":
-      ldflags.append(clarg)
-      continue
-
-    nargs.append(clarg)
-    u.verbose(2, "append arg %s" % clarg)
-
-  tf = None
-  if not minus_c and not minus_s:
-    if not outfile:
-      outfile = "a.out"
-    linkoutfile = outfile
-    tf = tempfile.NamedTemporaryFile(mode="w", prefix="%s" % basename,
-                                     delete=True)
-    outfile = tf.name
-
-  if outfile:
-    nargs.append("-o")
-    nargs.append(outfile)
-
-  if not largsSeen:
-    nargs.append("-L")
-    nargs.append(form_golibargs(sys.argv[0]))
-    u.verbose(1, "revised args: %s" % " ".join(nargs))
-
-  # Invoke gollvm.
-  driver = "llvm-goc"
-  u.verbose(1, "driver path is %s" % driver)
-  nargs = ["llvm-goc"] + nargs
-  if flag_trace_llinvoc or minus_v:
-    u.verbose(0, "%s" % " ".join(nargs))
-  rc = subprocess.call(nargs)
-  if rc != 0:
-    u.verbose(1, "return code %d from %s" % (rc, " ".join(nargs)))
-    return 1
-
-  # Invoke the linker
-  # Right now we use the real gccgo as the linker
-  if not minus_c and not minus_s:
-    bd = os.path.dirname(sys.argv[0])
-    driver = "%s/gccgo.real" % bd
-    ldflags += ["-o", linkoutfile]
-    ldcmd = "%s %s %s " % (driver, " ".join(ldflags), outfile)
-    ldcmd += " ".join(ofiles)  # pass extra .o files to the linker
-    u.verbose(1, "link command is: %s" % ldcmd)
-    if minus_v:
-      u.verbose(0, "%s" % ldcmd)
-    rc = u.docmdnf(ldcmd)
-    if rc != 0:
-      u.verbose(1, "return code %d from %s" % (rc, ldcmd))
-      return 1
-    if tf:
-      tf.close()
-
-  return 0
-
-
-def install_shim(scriptpath):
-  """Install shim into gccgo install dir."""
-
-  # Make sure we're in the right place (gccgo install dir)
-  if not os.path.exists("bin"):
-    usage("expected to find bin subdir")
-  if not os.path.exists("lib64/libgo.so"):
-    usage("expected to find lib64/libgo.so")
-  if not os.path.exists("bin/gccgo"):
-    usage("expected to find bin/gccgo")
-
-  # Copy script, or update if already in place.
-  docmd("cp %s bin" % scriptpath)
-  sdir = os.path.dirname(scriptpath)
-  docmd("cp %s/script_utils.py bin" % sdir)
-
-  # Test to see if script installed already
-  cmd = "file bin/gccgo"
-  lines = u.docmdlines(cmd)
-  if not lines:
-    u.error("no output from %s -- bad gccgo install dir?" % cmd)
-  else:
-    reg = re.compile(r"^.+ ELF .+$")
-    m = reg.match(lines[0])
-    if not m:
-      u.warning("wrapper appears to be installed already in this dir")
-      return
-
-  # Move aside the real gccgo binary
-  docmd("mv bin/gccgo bin/gccgo.real")
-
-  # Emit a script into gccgo
-  sys.stderr.write("emitting wrapper script into bin/gccgo\n")
-  if not flag_dryrun:
-    try:
-      with open("./bin/gccgo", "w") as wf:
-        here = os.getcwd()
-        wf.write("#!/bin/sh\n")
-        wf.write("P=%s/bin/gollvm-wrap.py\n" % here)
-        wf.write("exec python ${P} \"$@\"\n")
-    except IOError:
-      u.error("open/write failed for bin/gccgo wrapper")
-  docmd("chmod 0755 bin/gccgo")
-
-  # Success
-  u.verbose(0, "wrapper installed successfully")
-
-  # Done
-  return 0
-
-
-def usage(msgarg):
-  """Print usage and exit."""
-  if msgarg:
-    sys.stderr.write("error: %s\n" % msgarg)
-  print """\
-    usage:  %s <gccgo args>
-
-    Options (via command line)
-    --install   installs wrapper into gccgo directory
-
-    Options (via GOLLVM_WRAP_OPTIONS):
-    -t          trace llvm-goc executions
-    -d          increase debug msg verbosity level
-    -e          show commands being invoked
-    -D          dry run (echo cmds but do not execute)
-    -G          pure gccgo compile (no llvm-goc invocations)
-
-    """ % os.path.basename(sys.argv[0])
-  sys.exit(1)
-
-
-def parse_env_options():
-  """Option parsing from env var."""
-  global flag_echo, flag_dryrun, flag_nollvm, flag_trace_llinvoc
-  global flag_alwaysllvm
-
-  optstr = os.getenv("GOLLVM_WRAP_OPTIONS")
-  if not optstr:
-    return
-  args = optstr.split()
-
-  try:
-    optlist, _ = getopt.getopt(args, "detDAG")
-  except getopt.GetoptError as err:
-    # unrecognized option
-    usage(str(err))
-
-  for opt, _ in optlist:
-    if opt == "-d":
-      u.increment_verbosity()
-    elif opt == "-e":
-      flag_echo = True
-    elif opt == "-t":
-      flag_trace_llinvoc = True
-    elif opt == "-D":
-      flag_dryrun = True
-    elif opt == "-G":
-      flag_nollvm = True
-    elif opt == "-A":
-      flag_alwaysllvm = True
-  u.verbose(1, "env var options parsing complete")
-
-
-# Setup
-u.setdeflanglocale()
-parse_env_options()
-
-# Either --install mode or regular mode
-if len(sys.argv) == 2 and sys.argv[1] == "--install":
-  prc = install_shim(sys.argv[0])
-else:
-  prc = perform()
-sys.exit(prc)
diff --git a/tools/script_utils.py b/tools/script_utils.py
deleted file mode 100644
index d681a7f..0000000
--- a/tools/script_utils.py
+++ /dev/null
@@ -1,304 +0,0 @@
-#!/usr/bin/python
-"""Utility functions for scripts in my bin diretory.
-
-This module contains common utilities such as wrappers for
-error/warning reporting, executing shell commands in a controlled way,
-etc. These functions are shared by a number of helper scripts.
-
-"""
-
-import locale
-import os
-import re
-import shlex
-import signal
-import subprocess
-import sys
-import tempfile
-
-# Debugging verbosity level (0 -> no output)
-flag_debug = 0
-
-# Unit testing mode. If set to 1, throw exception instead of calling exit()
-flag_unittest = 0
-
-hrszre = re.compile(r"^([\d\.]+)(\S)$")
-factors = {"K": 1024.0, "M": 1048576.0, "G": 1073741824.0}
-
-
-def verbose(level, msg):
-  """Print debug trace output of verbosity level is >= value in 'level'."""
-  if level <= flag_debug:
-    sys.stderr.write(msg + "\n")
-
-
-def verbosity_level():
-  """Return debug trace level."""
-  return flag_debug
-
-
-def increment_verbosity():
-  """Increment debug trace level by 1."""
-  global flag_debug
-  flag_debug += 1
-
-
-def decrement_verbosity():
-  """Lower debug trace level by 1."""
-  global flag_debug
-  flag_debug -= 1
-
-
-def unit_test_enable():
-  """Set unit testing mode."""
-  global flag_unittest
-  sys.stderr.write("+++ unit testing mode enabled +++\n")
-  flag_unittest = 1
-
-
-def warning(msg):
-  """Issue a warning to stderr."""
-  sys.stderr.write("warning: " + msg + "\n")
-
-
-def error(msg):
-  """Issue an error to stderr, then exit."""
-  errm = "error: " + msg + "\n"
-  sys.stderr.write(errm)
-  if flag_unittest:
-    raise Exception(errm)
-  else:
-    exit(1)
-
-
-def docmd(cmd):
-  """Run a command via subprocess, issuing fatal error if cmd fails."""
-  args = shlex.split(cmd)
-  verbose(2, "+ docmd executing: %s" % cmd)
-  rc = subprocess.call(args)
-  if rc != 0:
-    error("command failed: %s" % cmd)
-
-
-# Similar to docmd, but return status after issuing failure message
-def docmdnf(cmd):
-  """Run a command via subprocess, returning exit status."""
-  args = shlex.split(cmd)
-  verbose(2, "+ docmd executing: %s" % cmd)
-  rc = subprocess.call(args)
-  return rc
-
-
-# Similar to docmd, but suppress output
-def doscmd(cmd, nf=None):
-  """Run a command via subprocess, suppressing output unless error."""
-  verbose(2, "+ doscmd executing: %s" % cmd)
-  args = shlex.split(cmd)
-  cmdtf = tempfile.NamedTemporaryFile(mode="w", delete=True)
-  rc = subprocess.call(args, stdout=cmdtf, stderr=cmdtf)
-  if rc != 0:
-    warning("error: command failed (rc=%d) cmd: %s" % (rc, cmd))
-    warning("output from failing command:")
-    subprocess.call(["cat", cmdtf.name])
-    if nf:
-      return None
-    error("")
-  cmdtf.close()
-  return True
-
-
-# invoke command, writing output to file
-def docmdout(cmd, outfile, nf=None):
-  """Run a command via subprocess, writing output to a file."""
-  verbose(2, "+ docmdout executing: %s > %s" % (cmd, outfile))
-  args = shlex.split(cmd)
-  with open(outfile, "w") as outfile:
-    rc = subprocess.call(args, stdout=outfile)
-    if rc != 0:
-      warning("error: command failed (rc=%d) cmd: %s" % (rc, cmd))
-      if nf:
-        return None
-      error("")
-  return True
-
-# invoke command, writing output to file
-def docmderrout(cmd, outfile, nf=None):
-  """Run a command via subprocess, writing output to a file."""
-  verbose(2, "+ docmdout executing: %s > %s" % (cmd, outfile))
-  args = shlex.split(cmd)
-  try:
-    with open(outfile, "w") as outfile:
-      rc = subprocess.call(args, stdout=outfile, stderr=outfile)
-      if rc != 0:
-        if nf:
-          sys.stderr.write("error: command failed (rc=%d) cmd: %s\n" % (rc, cmd))
-          return rc
-        else:
-          error("command failed (rc=%d) cmd: %s\n" % (rc, cmd))
-      return rc
-  except IOError:
-    error("unable to open %s for writing" % outfile)
-
-
-# invoke command, reading from one file and writing to another
-def docmdinout(cmd, infile, outfile):
-  """Run a command via subprocess with input and output file."""
-  verbose(2, "+ docmdinout executing: %s < %s > %s" % (cmd, infile, outfile))
-  args = shlex.split(cmd)
-  cmdtf = tempfile.NamedTemporaryFile(mode="w", delete=True)
-  with open(infile, "r") as inf:
-    with open(outfile, "w") as outf:
-      rc = subprocess.call(args, stdout=outf, stdin=inf, stderr=cmdtf)
-      if rc != 0:
-        warning("error: command failed (rc=%d) cmd: %s" % (rc, cmd))
-        warning("output from failing command:")
-        subprocess.call(["cat", cmdtf.name])
-        return 1
-  verbose(2, "+ finished: %s < %s > %s" % (cmd, infile, outfile))
-  return 0
-
-
-# invoke command, returning array of lines read from it
-def docmdlines(cmd, nf=None):
-  """Run a command via subprocess, returning output as an array of lines."""
-  verbose(2, "+ docmdlines executing: %s" % cmd)
-  args = shlex.split(cmd)
-  mypipe = subprocess.Popen(args, stdout=subprocess.PIPE)
-  encoding = locale.getdefaultlocale()[1]
-  if encoding is None:
-    encoding = 'UTF-8'
-  pout, perr = mypipe.communicate()
-  if mypipe.returncode != 0:
-    if perr:
-      decoded_err = perr.decode(encoding)
-      warning(decoded_err)
-    if nf:
-      return None
-    error("command failed (rc=%d): cmd was %s" % (mypipe.returncode, args))
-  decoded = pout.decode(encoding)
-  lines = decoded.strip().split("\n")
-  return lines
-
-
-# invoke command, returning raw bytes from read
-def docmdbytes(cmd, nf=None):
-  """Run a command via subprocess, returning output as raw bytestring."""
-  args = shlex.split(cmd)
-  mypipe = subprocess.Popen(args, stdout=subprocess.PIPE)
-  pout, perr = mypipe.communicate()
-  if mypipe.returncode != 0:
-    encoding = locale.getdefaultlocale()[1]
-    if perr:
-      decoded_err = perr.decode(encoding)
-      warning(decoded_err)
-    if nf:
-      return None
-    error("command failed (rc=%d): cmd was %s" % (mypipe.returncode, args))
-  return pout
-
-
-# invoke a command with input coming from an echo'd string, e.g.
-# Ex: "echo 1+2 | perl"
-def docmdinstring(cmd, instring):
-  """Invoke a command with stdin coming from a specific string."""
-  verbose(2, "+ docmdinstring executing: echo %s | %s " % (cmd, instring))
-  args = shlex.split(cmd)
-  mypipe = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
-  encoding = locale.getdefaultlocale()[1]
-  pout, perr = mypipe.communicate(instring)
-  if mypipe.returncode != 0:
-    if perr:
-      decoded_err = perr.decode(encoding)
-      warning(decoded_err)
-    error("command failed (rc=%d): cmd was %s" % (mypipe.returncode, args))
-  decoded = pout.decode(encoding)
-  lines = decoded.strip().split("\n")
-  return lines
-
-
-# Execute a command with an alarm timeout.
-def docmdwithtimeout(cmd, timeout_duration):
-  """Run a command via subprocess, returning exit status or -1 if timeout."""
-
-  class TimeoutError(Exception):
-    pass
-
-  def handler(signum, frame):
-    raise TimeoutError()
-
-  # set the timeout handler
-  prevhandler = signal.signal(signal.SIGALRM, handler)
-  signal.alarm(timeout_duration)
-  try:
-    result = docmdnf(cmd)
-  except TimeoutError as exc:
-    verbose(1, "timeout triggered after %d seconds" % timeout_duration)
-    result = -1
-  finally:
-    signal.alarm(0)
-    signal.signal(signal.SIGALRM, prevhandler)
-  return result
-
-
-# perform default locale setup if needed
-def setdeflanglocale():
-  if "LANG" not in os.environ:
-    warning("no env setting for LANG -- using default values")
-    os.environ["LANG"] = "en_US.UTF-8"
-    os.environ["LANGUAGE"] = "en_US:"
-
-
-def determine_btrfs_ssdroot(here):
-  """Determine ssd root."""
-
-  path_components = here.split("/")
-  root = "/%s" % path_components[1]
-  verbose(2, "cwd=%s root=%s" % (here, root))
-
-  # Is this a BTRFS ssd to begin with?
-  outlines = docmdlines("stat -f --printf=%%T %s" % root)
-  if not outlines:
-    error("internal error-- could not determine FS type "
-          "for root dir %s" % root)
-  if outlines[0] != "btrfs":
-    error("current FS type is %s, not btrfs (can't proceed)" % outlines[0])
-  return root
-
-
-def hr_size_to_bytes(sz):
-  """Convert human readable size back to bytes."""
-  m = hrszre.match(sz)
-  if not m:
-    warning("unmatchable size expr %s" % sz)
-    return None
-  val = float(m.group(1))
-  facs = m.group(2)
-  if facs not in factors:
-    warning("unknown factor '%s' in size expr %s" % (facs, sz))
-    return None
-  fac = factors[facs]
-  nb = int(val * fac)
-  return nb
-
-
-def trim_perf_report_file(infile):
-  """Trim trailing spaces from lines in perf report."""
-  verbose(1, "trim: reading " + infile)
-  try:
-    f = open(infile, "r")
-  except IOError:
-    warning("unable to open file %s for reading" % infile)
-    return 1
-  lines = f.readlines()
-  f.close()
-  verbose(1, "trim: rewriting " + infile)
-  try:
-    ft = open(infile, "w")
-  except IOError:
-    warning("unable to open file %s for rewriting" % infile)
-    return 1
-  for line in lines:
-    sline = line.rstrip()
-    ft.write(sline + "\n")
-  ft.close()
-  return 0