-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
121 lines (111 loc) · 2.22 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/davecgh/go-spew/spew"
"tinygo.org/x/go-llvm"
)
var (
dumpIR = flag.Bool("d", false, "dump the llvm ir")
execProg = flag.Bool("e", false, "evaluate the code")
optimize = flag.Int("O", 0, "the level of optimization")
output = flag.String("o", "", "output filename")
verbose = flag.Bool("v", false, "verbose output")
writer *os.File
err error
)
func main() {
flag.Parse()
files := flag.Args()
if len(files) == 0 {
return
}
initExecutionEngine()
if *optimize > 0 {
Optimize()
}
needWrite, filename, extname := true, "", ""
if *output == "" {
if *dumpIR || *execProg {
needWrite = false
} else {
filename = filepath.Base(files[0])
pos := len(filename) - len(filepath.Ext(filename))
*output = filename[:pos]
}
}
filename = *output
if needWrite {
extname = strings.ToLower(filepath.Ext(*output))
if extname == "" {
filename += ".o"
}
writer, err = os.Create(filename)
handleError(true, "can not open the file:", err)
defer writer.Close()
}
lex := Lex()
go func() {
for _, fn := range files {
f, err := os.Open(fn)
handleError(true, "", err)
lex.Add(f)
}
lex.Done()
}()
tokens := lex.Tokens()
if extname == ".tok" {
for tok := range tokens {
spew.Fdump(writer, tok)
}
if needWrite {
return
}
}
nodes := Parse(tokens)
if *dumpIR {
EmitIR(nodes)
}
if *execProg {
Exec(nodes)
}
if !needWrite {
return
}
switch extname {
case ".ast":
for nod := range nodes {
spew.Fdump(writer, nod)
}
case ".bc":
VisitNodes(nodes, nil)
llvm.WriteBitcodeToFile(rootModule, writer)
default:
obj, err := Compile(nodes, rootModule)
handleError(true, "can not emit object file to memory buffer:", err)
_, err = writer.Write(obj)
handleError(true, "write to file failure:", err)
if extname == "" {
cmd := exec.Command("clang", "-o", *output, "lib.c", filename)
// fmt.Println(cmd.String())
handleError(true, "build failure:", cmd.Run())
os.Chmod(*output, 0755)
}
}
}
func handleError(isExit bool, msg string, err error) {
if err == nil {
return
}
if len(msg) > 0 {
fmt.Println(msg)
}
fmt.Println(err)
if isExit {
os.Exit(-1)
}
}