Skip to content

Commit c4fd19b

Browse files
aykevldeadprogram
authored andcommitted
compiler: refactor public interface
This commit merges NewCompiler and Compile into one simplifying the external interface. More importantly, it does away with the entire Compiler object so the public API becomes a lot smaller. The refactor is not complete: eventually, the compiler should just compile a single package without trying to load it first (that should be done by the builder package).
1 parent 8ef921e commit c4fd19b

File tree

3 files changed

+96
-130
lines changed

3 files changed

+96
-130
lines changed

builder/build.go

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/tinygo-org/tinygo/goenv"
1818
"github.com/tinygo-org/tinygo/interp"
1919
"github.com/tinygo-org/tinygo/transform"
20+
"tinygo.org/x/go-llvm"
2021
)
2122

2223
// Build performs a single package to executable Go build. It takes in a package
@@ -26,34 +27,34 @@ import (
2627
// The error value may be of type *MultiError. Callers will likely want to check
2728
// for this case and print such errors individually.
2829
func Build(pkgName, outpath string, config *compileopts.Config, action func(string) error) error {
29-
c, err := compiler.NewCompiler(pkgName, config)
30+
// Compile Go code to IR.
31+
machine, err := compiler.NewTargetMachine(config)
3032
if err != nil {
3133
return err
3234
}
33-
34-
// Compile Go code to IR.
35-
errs := c.Compile(pkgName)
36-
if len(errs) != 0 {
35+
mod, extraFiles, errs := compiler.Compile(pkgName, machine, config)
36+
if errs != nil {
3737
return newMultiError(errs)
3838
}
39+
3940
if config.Options.PrintIR {
4041
fmt.Println("; Generated LLVM IR:")
41-
fmt.Println(c.IR())
42+
fmt.Println(mod.String())
4243
}
43-
if err := c.Verify(); err != nil {
44+
if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {
4445
return errors.New("verification error after IR construction")
4546
}
4647

47-
err = interp.Run(c.Module(), config.DumpSSA())
48+
err = interp.Run(mod, config.DumpSSA())
4849
if err != nil {
4950
return err
5051
}
51-
if err := c.Verify(); err != nil {
52+
if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {
5253
return errors.New("verification error after interpreting runtime.initAll")
5354
}
5455

5556
if config.GOOS() != "darwin" {
56-
transform.ApplyFunctionSections(c.Module()) // -ffunction-sections
57+
transform.ApplyFunctionSections(mod) // -ffunction-sections
5758
}
5859

5960
// Browsers cannot handle external functions that have type i64 because it
@@ -62,7 +63,7 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
6263
// stack-allocated values.
6364
// Use -wasm-abi=generic to disable this behaviour.
6465
if config.Options.WasmAbi == "js" && strings.HasPrefix(config.Triple(), "wasm") {
65-
err := transform.ExternalInt64AsPtr(c.Module())
66+
err := transform.ExternalInt64AsPtr(mod)
6667
if err != nil {
6768
return err
6869
}
@@ -73,22 +74,22 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
7374
errs = nil
7475
switch config.Options.Opt {
7576
case "none", "0":
76-
errs = transform.Optimize(c.Module(), config, 0, 0, 0) // -O0
77+
errs = transform.Optimize(mod, config, 0, 0, 0) // -O0
7778
case "1":
78-
errs = transform.Optimize(c.Module(), config, 1, 0, 0) // -O1
79+
errs = transform.Optimize(mod, config, 1, 0, 0) // -O1
7980
case "2":
80-
errs = transform.Optimize(c.Module(), config, 2, 0, 225) // -O2
81+
errs = transform.Optimize(mod, config, 2, 0, 225) // -O2
8182
case "s":
82-
errs = transform.Optimize(c.Module(), config, 2, 1, 225) // -Os
83+
errs = transform.Optimize(mod, config, 2, 1, 225) // -Os
8384
case "z":
84-
errs = transform.Optimize(c.Module(), config, 2, 2, 5) // -Oz, default
85+
errs = transform.Optimize(mod, config, 2, 2, 5) // -Oz, default
8586
default:
8687
errs = []error{errors.New("unknown optimization level: -opt=" + config.Options.Opt)}
8788
}
8889
if len(errs) > 0 {
8990
return newMultiError(errs)
9091
}
91-
if err := c.Verify(); err != nil {
92+
if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {
9293
return errors.New("verification failure after LLVM optimization passes")
9394
}
9495

@@ -98,8 +99,8 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
9899
// pointers are flash and which are in RAM so that pointers can have a
99100
// correct address space parameter (address space 1 is for flash).
100101
if strings.HasPrefix(config.Triple(), "avr") {
101-
transform.NonConstGlobals(c.Module())
102-
if err := c.Verify(); err != nil {
102+
transform.NonConstGlobals(mod)
103+
if err := llvm.VerifyModule(mod, llvm.PrintMessageAction); err != nil {
103104
return errors.New("verification error after making all globals non-constant on AVR")
104105
}
105106
}
@@ -108,11 +109,17 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
108109
outext := filepath.Ext(outpath)
109110
switch outext {
110111
case ".o":
111-
return c.EmitObject(outpath)
112+
llvmBuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
113+
if err != nil {
114+
return err
115+
}
116+
return ioutil.WriteFile(outpath, llvmBuf.Bytes(), 0666)
112117
case ".bc":
113-
return c.EmitBitcode(outpath)
118+
data := llvm.WriteBitcodeToMemoryBuffer(mod).Bytes()
119+
return ioutil.WriteFile(outpath, data, 0666)
114120
case ".ll":
115-
return c.EmitText(outpath)
121+
data := []byte(mod.String())
122+
return ioutil.WriteFile(outpath, data, 0666)
116123
default:
117124
// Act as a compiler driver.
118125

@@ -125,7 +132,11 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
125132

126133
// Write the object file.
127134
objfile := filepath.Join(dir, "main.o")
128-
err = c.EmitObject(objfile)
135+
llvmBuf, err := machine.EmitToMemoryBuffer(mod, llvm.ObjectFile)
136+
if err != nil {
137+
return err
138+
}
139+
err = ioutil.WriteFile(objfile, llvmBuf.Bytes(), 0666)
129140
if err != nil {
130141
return err
131142
}
@@ -167,16 +178,13 @@ func Build(pkgName, outpath string, config *compileopts.Config, action func(stri
167178
}
168179

169180
// Compile C files in packages.
170-
for i, pkg := range c.Packages() {
171-
for _, file := range pkg.CFiles {
172-
path := filepath.Join(pkg.Package.Dir, file)
173-
outpath := filepath.Join(dir, "pkg"+strconv.Itoa(i)+"-"+file+".o")
174-
err := runCCompiler(config.Target.Compiler, append(config.CFlags(), "-c", "-o", outpath, path)...)
175-
if err != nil {
176-
return &commandError{"failed to build", path, err}
177-
}
178-
ldflags = append(ldflags, outpath)
181+
for i, file := range extraFiles {
182+
outpath := filepath.Join(dir, "pkg"+strconv.Itoa(i)+"-"+filepath.Base(file)+".o")
183+
err := runCCompiler(config.Target.Compiler, append(config.CFlags(), "-c", "-o", outpath, file)...)
184+
if err != nil {
185+
return &commandError{"failed to build", file, err}
179186
}
187+
ldflags = append(ldflags, outpath)
180188
}
181189

182190
// Link the object files together.

0 commit comments

Comments
 (0)