github.com/alexanius/gollvm12@v0.0.0-20230419200121-b152358b84f3/README.md (about)

     1  
     2  
     3  # Gollvm
     4  
     5  Gollvm is an LLVM-based Go compiler. It incorporates "gofrontend" (a Go language front end written in C++ and shared with GCCGO), a bridge component (which translates from gofrontend IR to LLVM IR), and a driver that sends the resulting IR through the LLVM back end.
     6  
     7  Gollvm is set up to be a subproject within the LLVM tools directory, similar to
     8  how things work for "clang" or "compiler-rt": you check out a copy of the LLVM
     9  source tree, then within the LLVM tree you check out additional git repos.
    10  
    11  
    12  # Table of contents <a name="toc"></a>
    13  
    14   * [Building gollvm](#building)
    15   * [Work area setup](#workarea)
    16   * [Invoking cmake and ninja](#cmakeninja)
    17   * [Installing gollvm](#installing)
    18   * [Using an installed copy of gollvm](#using)
    19   * [Information for gollvm developers](#developers)
    20  
    21  [FAQ](#FAQ)
    22  
    23    * [Where should I post questions about gollvm?](#wheretopostquestions)
    24    * [Where should I file gollvm bugs?](#wheretofile)
    25    * [How can I go about contributing to gollvm?](#contributing)
    26    * [Is gollvm a replacement for the main Go compiler (gc)?](#replacegc)
    27    * [Which architectures and operating systems are supported for gollvm?](#supported)
    28    * [How does the gollvm runtime differ from the main Go runtime?](#runtimediffs)
    29    * [Shared linkage is the default for gollvm. How do I build non-shared?](#buildstatic)
    30    * [What command line options are supported for gollvm?](#cmdlineopts)
    31    * [How do I see the LLVM IR generated by gollvm?](#seetheir)
    32    * [What is the relationship between gollvm and gccgo?](#gollvmandgccgo)
    33    * [Can I use FDO or Thin LTO with gollvm?](#thinltofdo)
    34    * [Can I use the race detector?](#racedetector)
    35    * [I am seeing "undefined symbol: `__get_cpuid_count`" from my gollvm install](#getcpuidcount_undefined)
    36    
    37  # Building gollvm <a name="building"></a>
    38  
    39  Gollvm is currently in development -- releases are not yet available for download.  Instructions for building gollvm follow.
    40  
    41  ## Setting up a gollvm work area <a name="workarea"></a>
    42  
    43  To set up a work area for Gollvm, check out a copy of LLVM, the overlay the gollvm repo (and other associated dependencies) within the LLVM tools subdir, as follows:
    44  
    45  ```
    46  // Here 'workarea' will contain a copy of the LLVM source tree and one or more build areas
    47  % mkdir workarea
    48  % cd workarea
    49  
    50  // Sources
    51  % git clone https://github.com/llvm/llvm-project.git
    52  ...
    53  % cd llvm-project/llvm/tools
    54  % git clone https://go.googlesource.com/gollvm
    55  ...
    56  % cd gollvm
    57  % git clone https://go.googlesource.com/gofrontend
    58  ...
    59  % cd libgo
    60  % git clone https://github.com/libffi/libffi.git
    61  ...
    62  % git clone https://github.com/ianlancetaylor/libbacktrace.git
    63  ...
    64  %
    65  ```
    66  
    67  ## Building gollvm with cmake and ninja <a name="cmakeninja"></a>
    68  
    69  You'll need to have an up-to-date copy of cmake on your system (3.6 or later vintage) to build Gollvm, as well as a C/C++ compiler (V10.0 or later for Clang, or V6.0 or later of GCC), and a working copy of 'm4'.
    70  
    71  Create a build directory (separate from the source tree) and run 'cmake' within the build area to set up for the build. Assuming that 'workarea' is the directory created as above:
    72  
    73  ```
    74  % cd workarea
    75  % mkdir build-debug
    76  % cd build-debug
    77  % cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_USE_LINKER=gold -G Ninja ../llvm-project/llvm
    78  ...
    79  % ninja gollvm
    80  ...
    81  %
    82  ```
    83  
    84  This will build the various tools and libraries needed for Gollvm. To select a specific C/C++ compiler for the build, you can use the "-DCMAKE_C_COMPILER" and "-DCMAKE_CXX_COMPILER" options to select your desired C/C++ compiler when invoking cmake (details [here](https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-do-i-use-a-different-compiler)). Use the "-DLLVM_USE_LINKER=<variant>" cmake variable to control which linker is selected to link the Gollvm compiler and tools (where variant is one of "bfd", "gold", "lld", etc).
    85  
    86  The Gollvm compiler driver defaults to using the gold linker when linking Go programs.  If some other linker is desired, this can be accomplished by passing "-DGOLLVM_DEFAULT_LINKER=<variant>" when running cmake. Note that this default can still be overridden on the command line using the "-fuse-ld" option.
    87  
    88  Gollvm's cmake rules expect a valid value for the SHELL environment variable; if not set, a default shell of /bin/bash will be used.
    89  
    90  ## Installing gollvm <a name="installing"></a>
    91  
    92  A gollvm installation will contain 'llvm-goc' (the compiler driver), the libgo standard Go libraries, and the standard Go tools ("go", "vet", "cgo", etc).
    93  
    94  The installation directory for gollvm needs to be specified when invoking cmake prior to the build:
    95  
    96  ```
    97  % mkdir build.rel
    98  % cd build.rel
    99  % cmake -DCMAKE_INSTALL_PREFIX=/my/install/dir -DCMAKE_BUILD_TYPE=Release -DLLVM_USE_LINKER=gold -G Ninja ../llvm-project/llvm
   100  
   101  // Build all of gollvm
   102  % ninja gollvm
   103  ...
   104  
   105  // Install gollvm to "/my/install/dir"
   106  % ninja install-gollvm
   107  
   108  ```
   109  
   110  ## Using an installed copy of gollvm  <a name="using"></a>
   111  
   112  Programs build with the Gollvm Go compiler default to shared linkage, meaning that they need to pick up the Go runtime library via LD_LIBRARY_PATH:
   113  
   114  ```
   115  // Root of Gollvm install is /tmp/gollvm-install
   116  % export LD_LIBRARY_PATH=/tmp/gollvm-install/lib64
   117  % export PATH=/tmp/gollvm-install/bin:$PATH
   118  % go run himom.go
   119  hi mom!
   120  %
   121  ```
   122  
   123  # Information for gollvm developers <a name="developers"></a>
   124  
   125  ## Source code structure
   126  
   127  Within \<workarea\>/llvm/tools/gollvm, the following directories are of interest:
   128  
   129  .../llvm/tools/gollvm:
   130  
   131   * contains rules to build third party libraries needed for gollvm,
   132     along with common definitions for subdirs.
   133  
   134  .../llvm/tools/gollvm/driver,
   135  .../llvm/tools/gollvm/driver-main:
   136  
   137   * contains build rules and source code for llvm-goc
   138  
   139  .../llvm/tools/gollvm/gofrontend:
   140  
   141   * source code for gofrontend and libgo (note: no cmake files here)
   142  
   143  .../llvm/tools/gollvm/bridge:
   144  
   145   * contains build rules for the libLLVMCppGoFrontEnd.a, a library that contains both the gofrontend code and the LLVM-specific middle layer (for example, the definition of the class Llvm_backend, which inherits from Backend).
   146  
   147  .../llvm/tools/gollvm/libgo:
   148  
   149   * build rules and supporting infrastructure to build Gollvm's copy of the Go runtime and standard packages.
   150  
   151  .../llvm/tools/gollvm/unittests:
   152  
   153   * source code for the unit tests
   154  
   155  ## The llvm-goc program
   156  
   157  The executable llvm-goc is the main compiler driver for gollvm; it functions as a compiler (consuming source for a Go package and producing an object file), an assembler, and/or a linker.  While it is possible to build and run llvm-goc directly from the command line, in practice there is little point in doing this (better to build using "go build", which will invoke llvm-goc on your behalf.
   158  
   159  ```
   160  // From within <workarea>/build.opt:
   161  
   162  % ninja llvm-goc
   163  ...
   164  % cat micro.go
   165  package foo
   166  func Bar() int {
   167  	return 1
   168  }
   169  % ./bin/llvm-goc -fgo-pkgpath=foo -O3 -S -o micro.s micro.go
   170  %
   171  ```
   172  
   173  
   174  ## Building and running the unit tests
   175  
   176  Here are instructions on building and running the unit tests for the middle layer:
   177  
   178  ```
   179  // From within <workarea>/build.opt:
   180  
   181  // Build unit test
   182  % ninja GoBackendCoreTests
   183  
   184  // Run a unit test
   185  % ./tools/gollvm/unittests/BackendCore/GoBackendCoreTests
   186  [==========] Running 10 tests from 2 test cases.
   187  [----------] Global test environment set-up.
   188  [----------] 9 tests from BackendCoreTests
   189  [ RUN      ] BackendCoreTests.MakeBackend
   190  [       OK ] BackendCoreTests.MakeBackend (1 ms)
   191  [ RUN      ] BackendCoreTests.ScalarTypes
   192  [       OK ] BackendCoreTests.ScalarTypes (0 ms)
   193  [ RUN      ] BackendCoreTests.StructTypes
   194  [       OK ] BackendCoreTests.StructTypes (1 ms)
   195  [ RUN      ] BackendCoreTests.ComplexTypes
   196  [       OK ] BackendCoreTests.ComplexTypes (0 ms)
   197  [ RUN      ] BackendCoreTests.FunctionTypes
   198  [       OK ] BackendCoreTests.FunctionTypes (0 ms)
   199  [ RUN      ] BackendCoreTests.PlaceholderTypes
   200  [       OK ] BackendCoreTests.PlaceholderTypes (0 ms)
   201  [ RUN      ] BackendCoreTests.ArrayTypes
   202  [       OK ] BackendCoreTests.ArrayTypes (0 ms)
   203  [ RUN      ] BackendCoreTests.NamedTypes
   204  [       OK ] BackendCoreTests.NamedTypes (0 ms)
   205  [ RUN      ] BackendCoreTests.TypeUtils
   206  
   207  ...
   208  
   209  [  PASSED  ] 10 tests.
   210  ```
   211  
   212  The unit tests currently work by instantiating an LLVM Backend instance and making backend method calls (to mimic what the frontend would do), then inspects the results to make sure they are as expected. Here is an example:
   213  
   214  ```
   215  TEST(BackendCoreTests, ComplexTypes) {
   216    LLVMContext C;
   217  
   218    Type *ft = Type::getFloatTy(C);
   219    Type *dt = Type::getDoubleTy(C);
   220  
   221    std::unique_ptr<Backend> be(go_get_backend(C, gollvm::driver::CallingConvId::X86_64_SysV));
   222    Btype *c32 = be->complex_type(64);
   223    ASSERT_TRUE(c32 != NULL);
   224    ASSERT_EQ(c32->type(), mkTwoFieldLLvmStruct(C, ft, ft));
   225    Btype *c64 = be->complex_type(128);
   226    ASSERT_TRUE(c64 != NULL);
   227    ASSERT_EQ(c64->type(), mkTwoFieldLLvmStruct(C, dt, dt));
   228  }
   229  ```
   230  
   231  The test above makes sure that the LLVM type we get as a result of calling Backend::complex_type() is kosher and matches up to expectations.
   232  
   233  ## Building libgo (Go runtime and standard libraries)
   234  
   235  To build the Go runtime and standard libraries, use the following:
   236  
   237  ```
   238  // From within <workarea>/build.opt:
   239  
   240  // Build Go runtime and standard libraries
   241  % ninja libgo_all
   242  
   243  ```
   244  
   245  This will compile static (\*.a) and dynamic (\*.so) versions of the library.
   246  
   247  # FAQ <a name="FAQ"></a>
   248  
   249  ## Where should I post questions about gollvm? <a name="wheretopostquestions"></a>
   250  
   251  Please send questions about gollvm to the [golang-nuts](https://groups.google.com/d/forum/golang-nuts) mailing list. Posting questions to the issue tracker is generally not the right way to start discussions or get information.
   252  
   253  ## Where should I file gollvm bugs? <a name="wheretofile"></a>
   254  
   255  Please file an issue on the golang [issue tracker](https://github.com/golang/go/issues); please be sure to use "gollvm" somewhere in the headline.
   256  
   257  ## How can I go about contributing to gollvm? <a name="contributing"></a>
   258  
   259  Please see the Go project guidelines at [https://golang.org/doc/contribute.html](https://golang.org/doc/contribute.html). Changes to [https://go.googlesource.com/gollvm](https://go.googlesource.com/gollvm) can be made by any Go contributor; for changes to gofrontend see [the gccgo guidelines](https://golang.org/doc/gccgo_contribute.html).
   260  
   261  ## Is gollvm a replacement for the main Go compiler? (gc) <a name="replacegc"></a>
   262  
   263  Gollvm is not intended as a replacement for the main Go compiler -- the
   264  expectation is that the bulk of users will want to continue to use the main Go
   265  compiler due to its superior compilation speed, ease of use, broader
   266  functionality, and higher-performance runtime. Gollvm is intended to provide a
   267  Go compiler with a more powerful back end, enabling such benefits as better
   268  inlining, vectorization, register allocation, etc.
   269  
   270  ## Which architectures and operating systems are supported for gollvm? <a name="supported"></a>
   271  
   272  Gollvm is currently supported only for x86_64 and aarch64 Linux.
   273  
   274  ## How does the gollvm runtime differ from the main Go runtime?  <a name="runtimediffs"></a>
   275  
   276  The main Go runtime supports generation of accurate stack maps, which allows the
   277  garbage collector to do precise stack scanning; gollvm does not yet support
   278  stack map generation (note that we're actively working on fixing this), hence
   279  for gollvm the garbage collector has to scan stacks conservatively (which can
   280  lead to longer scan times and increased memory usage). The main Go runtime
   281  compiles to a different calling convention, whereas Gollvm uses the standard
   282  C/C++ calling convention. There are many other smaller differences as well.
   283  
   284  ## Shared linkage is the default for gollvm. How do I build non-shared?  <a name="buildstatic"></a>
   285  
   286  Linking with "-static-libgo" will yield a binary that incorporates a full copy of the Go runtime. Example:
   287  
   288  ```
   289   % go build -gccgoflags -static-libgo myprogram.go
   290  ```
   291  
   292  Note that this will increase binary size.
   293  
   294  ## What command line options are supported for gollvm?  <a name="cmdlineopts"></a>
   295  
   296  You can run 'llvm-goc -help' to see a full set of supported options. These can be passed to the compiler via '-gccgoflags' option. Example:
   297  
   298  ```
   299  % go build -gccgoflags -fno-inline mumble.go
   300  ```
   301  
   302  ## How do I see the LLVM IR generated by gollvm?  <a name="seetheir"></a>
   303  
   304  The 'llvm-goc' command supports the -emit-llvm flag, however passing this option
   305  to a "go build" command is not practical, since the "go build" won't be
   306  expecting the compiler to emit LLVM bitcode or assembly.
   307  
   308  A better recipe is to run "go build" with "-x -work" to capture the commands
   309  being executed, then rerun the llvm-goc command shown adding "-S -emit-llvm".
   310  The resulting output will be an LLVM IR dump. Example:
   311  
   312  ```
   313  % go build -work -x mypackage.go 1> transcript.txt 2>&1
   314  % egrep '(WORK=|llvm-goc -c)' transcript.txt
   315  WORK=/tmp/go-build887931787
   316  /t/bin/llvm-goc -c -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build \
   317    -gno-record-gcc-switches -fgo-pkgpath=command-line-arguments \
   318    -fgo-relative-import-path=/mygopath/src/tmp -o $WORK/b001/_go_.o \
   319    -I $WORK/b001/_importcfgroot_ ./mypackage.go
   320  % /t/bin/llvm-goc -c -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build \
   321    -gno-record-gcc-switches -fgo-pkgpath=command-line-arguments \
   322    -fgo-relative-import-path=/mygopath/src/tmp \
   323    -I $WORK/b001/_importcfgroot_ -o mypackage.ll -S -emit-llvm \
   324    ./mypackage.go
   325  % ls -l mypackage.ll
   326  ...
   327  %
   328  ```
   329  
   330  
   331  ## What is the relationship between gollvm and gccgo?  <a name="gollvmandgccgo"></a>
   332  
   333  Gollvm and gccgo share a common front end (gofrontend) and associated runtime
   334  (libgo), however each uses a separate back end. When using "go build", the Go
   335  command currently treats gollvm as an instance of gccgo (hence the need to pass
   336  compile flags via "-gccgoflags"). This is expected to be temporary.
   337  
   338  ## Can I use FDO or ThinLTO with gollvm?  <a name="thinltofdo"></a>
   339  
   340  There are plans to support FDO, AutoFDO, and ThinLTO for gollvm, however these features have not yet been implemented.
   341  
   342  ## Can I use the race detector?  <a name="racedetector"></a>
   343  
   344  Gollvm does not support the Go race detector; please use the main Go compiler for this purpose.
   345  
   346  ## I am seeing "undefined symbol: `__get_cpuid_count`" from my gollvm install <a name="getcpuidcount_undefined">
   347  
   348  The Gollvm build procedure requires an up-to-date C/C++ compiler; there is code in the gollvm runtime (libgo) that refers to functions defined in `<cpuid.h>`, however some older versions of clang (prior to 5.0) don't provide definitions for all the needed functions. If you encounter this problem, rerun `cmake` to configure your build to use a more recent version of Clang (or use GCC), as described above.