Merge pull request #49 from alexbernat/gflang

Support for Fortran
This commit is contained in:
Ian A Mason 2021-06-09 12:14:07 -07:00 committed by GitHub
commit df36a3bf73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 9 deletions

View File

@ -17,10 +17,12 @@ bitcode in parallel, and is faster. A comparison between the two tools can be gl
|-----------------------------|-----------------------------| |-----------------------------|-----------------------------|
| wllvm | gclang | | wllvm | gclang |
| wllvm++ | gclang++ | | wllvm++ | gclang++ |
| | gflang |
| extract-bc | get-bc | | extract-bc | get-bc |
| wllvm-sanity-checker | gsanity-check | | wllvm-sanity-checker | gsanity-check |
| LLVM_COMPILER_PATH | LLVM_COMPILER_PATH | | LLVM_COMPILER_PATH | LLVM_COMPILER_PATH |
| LLVM_CC_NAME ... | LLVM_CC_NAME ... | | LLVM_CC_NAME ... | LLVM_CC_NAME ... |
| | LLVM_F_NAME |
| WLLVM_CONFIGURE_ONLY | WLLVM_CONFIGURE_ONLY | | WLLVM_CONFIGURE_ONLY | WLLVM_CONFIGURE_ONLY |
| WLLVM_OUTPUT_LEVEL | WLLVM_OUTPUT_LEVEL | | WLLVM_OUTPUT_LEVEL | WLLVM_OUTPUT_LEVEL |
| WLLVM_OUTPUT_FILE | WLLVM_OUTPUT_FILE | | WLLVM_OUTPUT_FILE | WLLVM_OUTPUT_FILE |
@ -52,7 +54,7 @@ For more details see [wllvm](https://github.com/SRI-CSL/whole-program-llvm).
To install `gllvm` you need the go language [tool](https://golang.org/doc/install). To install `gllvm` you need the go language [tool](https://golang.org/doc/install).
To use `gllvm` you need clang/clang++ and the llvm tools llvm-link and llvm-ar. To use `gllvm` you need clang/clang++/flang and the llvm tools llvm-link and llvm-ar.
`gllvm` is agnostic to the actual llvm version. `gllvm` also relies on standard build `gllvm` is agnostic to the actual llvm version. `gllvm` also relies on standard build
tools such as `objcopy` and `ld`. tools such as `objcopy` and `ld`.
@ -63,7 +65,7 @@ To install, simply do (making sure to include those `...`)
``` ```
go get github.com/SRI-CSL/gllvm/cmd/... go get github.com/SRI-CSL/gllvm/cmd/...
``` ```
This should install four binaries: `gclang`, `gclang++`, `get-bc`, and `gsanity-check` This should install five binaries: `gclang`, `gclang++`, `gflang`, `get-bc`, and `gsanity-check`
in the `$GOPATH/bin` directory. in the `$GOPATH/bin` directory.
If you are using `go 1.16` you may be forced to install it like this: If you are using `go 1.16` you may be forced to install it like this:
@ -74,7 +76,9 @@ Hopefully we will have a better fix for this [soon](https://github.com/golang/go
## Usage ## Usage
`gclang` and `gclang` and
`gclang++` are the wrappers used to compile C and C++. `get-bc` is used for `gclang++` are the wrappers used to compile C and C++.
`gflang` is the wrapper used to compile Fortran.
`get-bc` is used for
extracting the bitcode from a build product (either an object file, executable, library extracting the bitcode from a build product (either an object file, executable, library
or archive). `gsanity-check` can be used for detecting configuration errors. or archive). `gsanity-check` can be used for detecting configuration errors.
@ -106,8 +110,8 @@ environment variables.
contains the compiler and the other LLVM tools to be used. contains the compiler and the other LLVM tools to be used.
* `LLVM_CC_NAME` can be set if your clang compiler is not called `clang` but * `LLVM_CC_NAME` can be set if your clang compiler is not called `clang` but
something like `clang-3.7`. Similarly `LLVM_CXX_NAME` can be used to something like `clang-3.7`. Similarly `LLVM_CXX_NAME` and `LLVM_F_NAME` can be used to
describe what the C++ compiler is called. We also pay attention to the describe what the C++ and Fortran compilers are called, respectively. We also pay attention to the
environment variables `LLVM_LINK_NAME` and `LLVM_AR_NAME` in an environment variables `LLVM_LINK_NAME` and `LLVM_AR_NAME` in an
analogous way. analogous way.
@ -263,7 +267,7 @@ This will at least preserve the bitcode files, even if `get-bc` will not be able
Debugging usually boils down to looking in the logs, maybe adding a print statement or two. Debugging usually boils down to looking in the logs, maybe adding a print statement or two.
There is an additional executable, not mentioned above, called `gparse` that gets installed There is an additional executable, not mentioned above, called `gparse` that gets installed
along with `gclang`, `gclang++`, `get-bc` and `gsanity-check`. `gparse` takes the command line along with `gclang`, `gclang++`, `gflang`, `get-bc` and `gsanity-check`. `gparse` takes the command line
arguments to the compiler, and outputs how it parsed them. This can sometimes be helpful. arguments to the compiler, and outputs how it parsed them. This can sometimes be helpful.
## License ## License

54
cmd/gflang/main.go Normal file
View File

@ -0,0 +1,54 @@
//
// OCCAM
//
// Copyright (c) 2017, SRI International
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of SRI International nor the names of its contributors may
// be used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
package main
import (
"github.com/SRI-CSL/gllvm/shared"
"os"
)
func main() {
shared.LogInfo("Entering fortran %v\n", os.Args[1:])
// Parse command line
args := os.Args
args = args[1:]
exitCode := shared.Compile(args, "flang")
shared.LogDebug("Calling %v returned %v\n", os.Args, exitCode)
//important to pretend to look like the actual wrapped command
os.Exit(exitCode)
}

View File

@ -385,6 +385,11 @@ func GetCompilerExecName(compiler string) string {
return filepath.Join(LLVMToolChainBinDir, LLVMCXXName) return filepath.Join(LLVMToolChainBinDir, LLVMCXXName)
} }
return filepath.Join(LLVMToolChainBinDir, compiler) return filepath.Join(LLVMToolChainBinDir, compiler)
case "flang":
if LLVMFName != "" {
return filepath.Join(LLVMToolChainBinDir, LLVMCCName)
}
return filepath.Join(LLVMToolChainBinDir, compiler)
default: default:
LogError("The compiler %s is not supported by this tool.", compiler) LogError("The compiler %s is not supported by this tool.", compiler)
return "" return ""

View File

@ -59,6 +59,9 @@ var LLVMCCName string
//LLVMCXXName is the user configured name of the clang++ compiler. //LLVMCXXName is the user configured name of the clang++ compiler.
var LLVMCXXName string var LLVMCXXName string
//LLVMFName is the user configered name of the flang compiler.
var LLVMFName string
//LLVMARName is the user configured name of the llvm-ar. //LLVMARName is the user configured name of the llvm-ar.
var LLVMARName string var LLVMARName string
@ -93,6 +96,7 @@ const (
envpath = "LLVM_COMPILER_PATH" envpath = "LLVM_COMPILER_PATH"
envcc = "LLVM_CC_NAME" envcc = "LLVM_CC_NAME"
envcxx = "LLVM_CXX_NAME" envcxx = "LLVM_CXX_NAME"
envf = "LLVM_F_NAME"
envar = "LLVM_AR_NAME" envar = "LLVM_AR_NAME"
envlnk = "LLVM_LINK_NAME" envlnk = "LLVM_LINK_NAME"
envcfg = "WLLVM_CONFIGURE_ONLY" envcfg = "WLLVM_CONFIGURE_ONLY"
@ -116,7 +120,7 @@ func init() {
// PrintEnvironment is used for printing the aspects of the environment that concern us // PrintEnvironment is used for printing the aspects of the environment that concern us
func PrintEnvironment() { func PrintEnvironment() {
vars := []string{envpath, envcc, envcxx, envar, envlnk, envcfg, envbc, envlvl, envfile, envobjcopy, envld, envbcgen, envltolink} vars := []string{envpath, envcc, envcxx, envf, envar, envlnk, envcfg, envbc, envlvl, envfile, envobjcopy, envld, envbcgen, envltolink}
informUser("\nLiving in this environment:\n\n") informUser("\nLiving in this environment:\n\n")
for _, v := range vars { for _, v := range vars {
@ -135,6 +139,7 @@ func ResetEnvironment() {
LLVMToolChainBinDir = "" LLVMToolChainBinDir = ""
LLVMCCName = "" LLVMCCName = ""
LLVMCXXName = "" LLVMCXXName = ""
LLVMFName = ""
LLVMARName = "" LLVMARName = ""
LLVMLINKName = "" LLVMLINKName = ""
LLVMConfigureOnly = "" LLVMConfigureOnly = ""
@ -152,6 +157,7 @@ func FetchEnvironment() {
LLVMToolChainBinDir = os.Getenv(envpath) LLVMToolChainBinDir = os.Getenv(envpath)
LLVMCCName = os.Getenv(envcc) LLVMCCName = os.Getenv(envcc)
LLVMCXXName = os.Getenv(envcxx) LLVMCXXName = os.Getenv(envcxx)
LLVMFName = os.Getenv(envf)
LLVMARName = os.Getenv(envar) LLVMARName = os.Getenv(envar)
LLVMLINKName = os.Getenv(envlnk) LLVMLINKName = os.Getenv(envlnk)

View File

@ -59,6 +59,14 @@ then you will need to set the environment variable LLVM_CXX_NAME to
the appropriate string. For example if your clang++ is called ++clang the appropriate string. For example if your clang++ is called ++clang
then LLVM_CC_NAME should be set to ++clang. then LLVM_CC_NAME should be set to ++clang.
`
const explainLLVMFNAME = `
If your flang compiler is not called flang, but something else,
then you will need to set the environment variable LLVM_F_NAME to
the appropriate string. For example if your flang is called flang-7
then LLVM_F_NAME should be set to flang-7.
` `
const explainLLVMCOMPILERPATH = ` const explainLLVMCOMPILERPATH = `
@ -170,16 +178,26 @@ func checkCompilers() bool {
cxx := GetCompilerExecName("clang++") cxx := GetCompilerExecName("clang++")
cxxOK, cxxVersion, _ := checkExecutable(cxx, "-v") cxxOK, cxxVersion, _ := checkExecutable(cxx, "-v")
if !ccOK { if !cxxOK {
informUser("The CXX compiler %s was not found or not executable.\nBetter not try using gclang++!\n", cxx) informUser("The CXX compiler %s was not found or not executable.\nBetter not try using gclang++!\n", cxx)
informUser(explainLLVMCOMPILERPATH) informUser(explainLLVMCOMPILERPATH)
informUser(explainLLVMCXXNAME) informUser(explainLLVMCXXNAME)
} else { } else {
informUser("The CXX compiler %s is:\n\n\t%s\n\n", cxx, extractLine(cxxVersion, 0)) informUser("The CXX compiler %s is:\n\n\t%s\n\n", cxx, extractLine(cxxVersion, 0))
} }
f := GetCompilerExecName("flang")
fOK, fVersion, _ := checkExecutable(f, "-v")
if !fOK {
informUser("The Fortran compiler %s was not found or not executable.\nBetter not try using gflang!\n", f)
informUser(explainLLVMCOMPILERPATH)
informUser(explainLLVMFNAME)
} else {
informUser("The Fortran compiler %s is:\n\n\t%s\n\n", f, extractLine(fVersion, 0))
}
//FIXME: why "or" rather than "and"? BECAUSE: if you only need CC, not having CXX is not an error. //FIXME: why "or" rather than "and"? BECAUSE: if you only need CC, not having CXX is not an error.
return ccOK || cxxOK return ccOK || cxxOK || fOK
} }
func extractLine(version string, n int) string { func extractLine(version string, n int) string {