Translate bootstrapping main from C to LLVM IR
This avoids needing a C compiler for every platform.
Этот коммит содержится в:
родитель
a9bbed2f6c
коммит
588910792d
4 изменённых файлов: 53 добавлений и 46 удалений
30
Makefile
30
Makefile
|
@ -9,6 +9,7 @@ tgo: build/tgo
|
|||
LLVM := $(shell go env GOPATH)/src/llvm.org/llvm/bindings/go/llvm/workdir/llvm_build/bin/
|
||||
LINK = $(LLVM)llvm-link
|
||||
LLC = $(LLVM)llc
|
||||
LLAS = $(LLVM)llvm-as
|
||||
|
||||
CFLAGS = -Wall -Werror -Os -g -fno-exceptions -flto -ffunction-sections -fdata-sections $(LLFLAGS)
|
||||
|
||||
|
@ -16,7 +17,14 @@ RUNTIME_PARTS = build/runtime.bc
|
|||
|
||||
TARGET ?= unix
|
||||
|
||||
ifeq ($(TARGET),pca10040)
|
||||
ifeq ($(TARGET),unix)
|
||||
# Regular *nix system.
|
||||
GCC = gcc
|
||||
LD = clang
|
||||
SIZE = size
|
||||
|
||||
else ifeq ($(TARGET),pca10040)
|
||||
# PCA10040: nRF52832 development board
|
||||
GCC = arm-none-eabi-gcc
|
||||
LD = arm-none-eabi-ld -T arm.ld --gc-sections
|
||||
SIZE = arm-none-eabi-size
|
||||
|
@ -30,14 +38,12 @@ CFLAGS += -I$(CURDIR)/lib/CMSIS/CMSIS/Include
|
|||
CFLAGS += -DNRF52832_XXAA
|
||||
CFLAGS += -Wno-uninitialized
|
||||
RUNTIME_PARTS += build/runtime_nrf.bc
|
||||
RUNTIME_PARTS += build/system_nrf52.bc
|
||||
OBJ += build/startup_nrf51.o # TODO nrf52, see https://bugs.llvm.org/show_bug.cgi?id=31601
|
||||
RUNTIME_PARTS += build/nrfx_system_nrf52.bc
|
||||
OBJ += build/nrfx_startup_nrf51.o # TODO nrf52, see https://bugs.llvm.org/show_bug.cgi?id=31601
|
||||
|
||||
else
|
||||
$(error Unknown target)
|
||||
|
||||
else ifeq ($(TARGET),unix)
|
||||
# Regular *nix system.
|
||||
GCC = gcc
|
||||
LD = clang
|
||||
SIZE = size
|
||||
endif
|
||||
|
||||
|
||||
|
@ -75,13 +81,17 @@ build/%.bc: src/runtime/%.c src/runtime/*.h
|
|||
@mkdir -p build
|
||||
clang $(CFLAGS) -c -o $@ $<
|
||||
|
||||
# Compile LLVM bitcode from LLVM source.
|
||||
build/%.bc: src/runtime/%.ll
|
||||
$(LLAS) -o $@ $<
|
||||
|
||||
# Compile system_* file for the nRF.
|
||||
build/%.bc: lib/nrfx/mdk/%.c
|
||||
build/nrfx_%.bc: lib/nrfx/mdk/%.c
|
||||
@mkdir -p build
|
||||
clang $(CFLAGS) -c -o $@ $^
|
||||
|
||||
# Compile startup_* file for the nRF.
|
||||
build/%.o: lib/nrfx/mdk/gcc_%.S
|
||||
build/nrfx_%.o: lib/nrfx/mdk/gcc_%.S
|
||||
@mkdir -p build
|
||||
clang $(CFLAGS) -c -o $@ $^
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
#include "runtime.h"
|
||||
#include <string.h>
|
||||
|
||||
void go_init() __asm__("runtime.initAll");
|
||||
void go_main() __asm__("main.main");
|
||||
|
||||
int main() {
|
||||
go_init();
|
||||
go_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void * memset(void *s, int c, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
((uint8_t*)s)[i] = c;
|
||||
}
|
||||
return s;
|
||||
}
|
10
src/runtime/runtime.ll
Обычный файл
10
src/runtime/runtime.ll
Обычный файл
|
@ -0,0 +1,10 @@
|
|||
source_filename = "runtime/runtime.ll"
|
||||
|
||||
declare void @runtime.initAll()
|
||||
declare void @main.main()
|
||||
|
||||
define i32 @main() {
|
||||
call void @runtime.initAll()
|
||||
call void @main.main()
|
||||
ret i32 0
|
||||
}
|
34
tgo.go
34
tgo.go
|
@ -199,8 +199,12 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
|
|||
|
||||
// After all packages are imported, add a synthetic initializer function
|
||||
// that calls the initializer of each package.
|
||||
initFn := c.mod.NamedFunction("runtime.initAll")
|
||||
if initFn.IsNil() {
|
||||
initType := llvm.FunctionType(llvm.VoidType(), nil, false)
|
||||
initFn := llvm.AddFunction(c.mod, "runtime.initAll", initType)
|
||||
initFn = llvm.AddFunction(c.mod, "runtime.initAll", initType)
|
||||
}
|
||||
initFn.SetLinkage(llvm.PrivateLinkage)
|
||||
block := c.ctx.AddBasicBlock(initFn, "entry")
|
||||
c.builder.SetInsertPointAtEnd(block)
|
||||
for _, fn := range c.initFuncs {
|
||||
|
@ -208,6 +212,11 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
|
|||
}
|
||||
c.builder.CreateRetVoid()
|
||||
|
||||
// Set functions referenced in runtime.ll to internal linkage, to improve
|
||||
// optimization (hopefully).
|
||||
main := c.mod.NamedFunction("main.main")
|
||||
main.SetLinkage(llvm.PrivateLinkage)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -518,6 +527,7 @@ func (c *Compiler) parseFuncDecl(f *ssa.Function) (*Frame, error) {
|
|||
// Special function parser for generated package initializers (which also
|
||||
// initializes global variables).
|
||||
func (c *Compiler) parseInitFunc(frame *Frame, f *ssa.Function) error {
|
||||
frame.llvmFn.SetLinkage(llvm.PrivateLinkage)
|
||||
llvmBlock := c.ctx.AddBasicBlock(frame.llvmFn, "entry")
|
||||
c.builder.SetInsertPointAtEnd(llvmBlock)
|
||||
|
||||
|
@ -605,10 +615,7 @@ func (c *Compiler) parseInitFunc(frame *Frame, f *ssa.Function) error {
|
|||
}
|
||||
|
||||
func (c *Compiler) parseFunc(frame *Frame, f *ssa.Function) error {
|
||||
if frame.llvmFn.Name() != "main.main" {
|
||||
// This function is only used from within Go.
|
||||
frame.llvmFn.SetLinkage(llvm.PrivateLinkage)
|
||||
}
|
||||
|
||||
// Pre-create all basic blocks in the function.
|
||||
for _, block := range f.DomPreorder() {
|
||||
|
@ -1341,15 +1348,7 @@ func Compile(pkgName, runtimePath, outpath, target string, printIR bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
parseErr := c.Parse(pkgName, buildTags)
|
||||
if printIR {
|
||||
fmt.Println(c.IR())
|
||||
}
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
|
||||
// Add C runtime.
|
||||
// Add C/LLVM runtime.
|
||||
runtime, err := llvm.ParseBitcodeFile(runtimePath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -1359,6 +1358,15 @@ func Compile(pkgName, runtimePath, outpath, target string, printIR bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Compile Go code to IR.
|
||||
parseErr := c.Parse(pkgName, buildTags)
|
||||
if printIR {
|
||||
fmt.Println(c.IR())
|
||||
}
|
||||
if parseErr != nil {
|
||||
return parseErr
|
||||
}
|
||||
|
||||
c.ApplyFunctionSections() // -ffunction-sections
|
||||
|
||||
if err := c.Verify(); err != nil {
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче