mirror of
https://github.com/danog/gllvm.git
synced 2024-11-30 06:29:01 +01:00
[WIP] implement compiling part
This commit is contained in:
parent
3f332fd60b
commit
e14e7e328c
142
compiler.go
142
compiler.go
@ -1,19 +1,149 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func compile(args []string) {
|
||||
if len(args) < 1 {
|
||||
fmt.Println("You must precise which compiler to use.")
|
||||
os.Exit(1)
|
||||
log.Fatal("You must precise which compiler to use.")
|
||||
}
|
||||
var compilerName = args[0]
|
||||
var compilerExecName = getCompilerExecName(compilerName)
|
||||
var configureOnly bool
|
||||
if os.Getenv(CONFIGURE_ONLY) != "" {
|
||||
configureOnly = true
|
||||
}
|
||||
args = args[1:]
|
||||
|
||||
var pr = parse(args)
|
||||
var _ = pr
|
||||
var _ = compilerName
|
||||
|
||||
// If configure only is set, try to execute normal compiling command then exit silently
|
||||
if configureOnly {
|
||||
execCompile(compilerExecName, pr)
|
||||
os.Exit(0)
|
||||
}
|
||||
// Else try to build objects and bitcode
|
||||
buildAndAttachBitcode(compilerExecName, pr)
|
||||
}
|
||||
|
||||
// Compiles bitcode files and attach path to the object files
|
||||
func buildAndAttachBitcode(compilerExecName string, pr ParserResult) {
|
||||
// If nothing to do, exit silently
|
||||
if len(pr.InputFiles) == 0 || pr.IsEmitLLVM || pr.IsAssembly || pr.IsAssembleOnly ||
|
||||
(pr.IsDependencyOnly && !pr.IsCompileOnly) || pr.IsPreprocessOnly {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
var newObjectFiles []string
|
||||
var hidden = !pr.IsCompileOnly
|
||||
|
||||
if len(pr.InputFiles) == 1 && pr.IsCompileOnly {
|
||||
var srcFile = pr.InputFiles[0]
|
||||
objFile, bcFile := getArtifactNames(pr, 0, hidden)
|
||||
buildObjectFile(compilerExecName, pr, srcFile, objFile)
|
||||
buildBitcodeFile(compilerExecName, pr, srcFile, bcFile)
|
||||
attachBitcodePathToObject(bcFile, objFile)
|
||||
} else {
|
||||
for i, srcFile := range pr.InputFiles {
|
||||
objFile, bcFile := getArtifactNames(pr, i, hidden)
|
||||
buildObjectFile(compilerExecName, pr, srcFile, objFile)
|
||||
if hidden {
|
||||
newObjectFiles = append(newObjectFiles, objFile)
|
||||
} else if strings.HasSuffix(srcFile, ".bc") {
|
||||
attachBitcodePathToObject(srcFile, objFile)
|
||||
} else {
|
||||
buildBitcodeFile(compilerExecName, pr, srcFile, bcFile)
|
||||
attachBitcodePathToObject(bcFile, objFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !pr.IsCompileOnly {
|
||||
linkFiles(compilerExecName, pr, newObjectFiles)
|
||||
}
|
||||
}
|
||||
|
||||
func attachBitcodePathToObject(bcFile, objFile string) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
func linkFiles(compilerExecName string, pr ParserResult, objFiles []string) {
|
||||
var outputFile = pr.OutputFilename
|
||||
if outputFile == "" {
|
||||
outputFile = "a.out"
|
||||
}
|
||||
args := append(pr.ObjectFiles, objFiles...)
|
||||
args = append(args, pr.LinkArgs...)
|
||||
args = append(args, "-o", outputFile)
|
||||
if execCmd(compilerExecName, args) {
|
||||
log.Fatal("Failed to link.")
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to build the specified source file to object
|
||||
func buildObjectFile(compilerExecName string, pr ParserResult, srcFile string, objFile string) {
|
||||
args := pr.CompileArgs[:]
|
||||
args = append(args, srcFile, "-c", "-o", objFile)
|
||||
if execCmd(compilerExecName, args) {
|
||||
log.Fatal("Failed to build object file for", srcFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to build the specified source file to bitcode
|
||||
func buildBitcodeFile(compilerExecName string, pr ParserResult, srcFile string, bcFile string) {
|
||||
args := pr.CompileArgs[:]
|
||||
args = append(args, "-emit-llvm", "-c", srcFile, "-o", bcFile)
|
||||
if execCmd(compilerExecName, args) {
|
||||
log.Fatal("Failed to build bitcode file for", srcFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to build object file
|
||||
func execCompile(compilerExecName string, pr ParserResult) {
|
||||
if execCmd(compilerExecName, pr.InputList) {
|
||||
log.Fatal("Failed to execute compile command.")
|
||||
}
|
||||
}
|
||||
|
||||
// Executes a command then returns true if there was an error
|
||||
func execCmd(cmdExecName string, args []string) bool {
|
||||
cmd := exec.Command(cmdExecName, listToArgString(args))
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
if cmd.Run() == nil {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Joins a list of arguments to create a string
|
||||
func listToArgString(argList []string) string {
|
||||
return strings.Join(argList, " ")
|
||||
}
|
||||
|
||||
func getCompilerExecName(compilerName string) string {
|
||||
var compilerPath = os.Getenv(COMPILER_PATH)
|
||||
switch compilerName {
|
||||
case "clang":
|
||||
var clangName = os.Getenv(C_COMPILER_NAME)
|
||||
if clangName != "" {
|
||||
return compilerPath + clangName
|
||||
} else {
|
||||
return compilerPath + compilerName
|
||||
}
|
||||
case "clang++":
|
||||
var clangppName = os.Getenv(C_COMPILER_NAME)
|
||||
if clangppName != "" {
|
||||
return compilerPath + clangppName
|
||||
} else {
|
||||
return compilerPath + compilerName
|
||||
}
|
||||
default:
|
||||
log.Fatal("The compiler", compilerName, "is not supported by this tool.")
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
12
constants.go
12
constants.go
@ -1 +1,13 @@
|
||||
package main
|
||||
|
||||
// Environment variables
|
||||
var CONFIGURE_ONLY = "GOWLLVM_CONFIGURE_ONLY"
|
||||
var COMPILER_PATH = "GOWLLVM_COMPILER_PATH"
|
||||
var C_COMPILER_NAME = "GOWLLVM_CC_NAME"
|
||||
var CXX_COMPILER_NAME = "GOWLLVM_CXX_NAME"
|
||||
var BC_STORE_PATH = "GOWLLVM_BC_STORE"
|
||||
|
||||
// Gowllvm functioning
|
||||
var ELF_SECTION_NAME = ".llvm_bc"
|
||||
var DARWIN_SEGMENT_NAME = "__WLLVM"
|
||||
var DARWIN_SECTION_NAME = "__llvm_bc"
|
||||
|
11
gowllvm.go
11
gowllvm.go
@ -1,16 +1,15 @@
|
||||
package main
|
||||
|
||||
import(
|
||||
"fmt"
|
||||
"os"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse command line
|
||||
var args = os.Args
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Not enough arguments.")
|
||||
os.Exit(1)
|
||||
log.Fatal("Not enough arguments.")
|
||||
}
|
||||
var modeFlag = args[1]
|
||||
args = args[2:]
|
||||
@ -20,10 +19,8 @@ func main() {
|
||||
// Call main compile function with args
|
||||
compile(args)
|
||||
case "extract":
|
||||
fmt.Println("The extract feature is not implemented yet.")
|
||||
os.Exit(1)
|
||||
log.Fatal("The extract feature is not implemented yet.")
|
||||
default:
|
||||
fmt.Println("You should call gowllvm with a valid mode.")
|
||||
os.Exit(1)
|
||||
log.Fatal("You should call gowllvm with a valid mode.")
|
||||
}
|
||||
}
|
||||
|
21
parser.go
21
parser.go
@ -4,6 +4,8 @@ import(
|
||||
"fmt"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type ParserResult struct {
|
||||
@ -215,6 +217,25 @@ func parse(argList []string) ParserResult {
|
||||
return pr
|
||||
}
|
||||
|
||||
// Return the object and bc filenames that correspond to the i-th source file
|
||||
func getArtifactNames(pr ParserResult, srcFileIndex int, hidden bool) (objBase string, bcBase string) {
|
||||
if len(pr.InputFiles) == 1 && pr.IsCompileOnly && len(pr.OutputFilename) > 0 {
|
||||
objBase = pr.OutputFilename
|
||||
bcBase = fmt.Sprintf(".%s.bc", objBase)
|
||||
} else {
|
||||
srcFile := pr.InputFiles[srcFileIndex]
|
||||
var baseNameWithExt = filepath.Base(srcFile)
|
||||
var baseName = strings.TrimSuffix(baseNameWithExt, filepath.Ext(baseNameWithExt))
|
||||
bcBase = fmt.Sprintf(".%s.o.bc", baseName)
|
||||
if hidden {
|
||||
objBase = fmt.Sprintf(".%s.o", baseName)
|
||||
} else {
|
||||
objBase = fmt.Sprintf("%s.o", baseName)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func inputFileCallback(pr ParserResult, flag string, _ []string) {
|
||||
var regExp = regexp.MustCompile(`\\.(s|S)$`)
|
||||
pr.InputFiles = append(pr.InputFiles, flag)
|
||||
|
Loading…
Reference in New Issue
Block a user