diff options
-rw-r--r-- | .circleci/config.yml | 42 | ||||
-rw-r--r-- | Dockerfile | 14 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | azure-pipelines.yml | 12 | ||||
-rw-r--r-- | builder/cc1as.cpp | 42 | ||||
-rw-r--r-- | builder/cc1as.h | 4 | ||||
-rw-r--r-- | builder/clang.cpp | 6 | ||||
-rw-r--r-- | builder/commands.go | 30 | ||||
-rw-r--r-- | builder/lld.cpp | 4 | ||||
-rw-r--r-- | cgo/libclang.go | 2 | ||||
-rw-r--r-- | cgo/libclang_config.go | 13 | ||||
-rw-r--r-- | cgo/libclang_config_llvm9.go | 14 | ||||
-rw-r--r-- | cgo/libclang_stubs.c | 2 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 4 | ||||
-rw-r--r-- | loader/loader.go | 2 | ||||
-rw-r--r-- | main.go | 3 | ||||
-rw-r--r-- | transform/testdata/coroutines.out.ll | 28 | ||||
-rw-r--r-- | transform/testdata/func-lowering.out.ll | 6 | ||||
-rw-r--r-- | transform/testdata/gc-stackslots.out.ll | 4 | ||||
-rw-r--r-- | transform/testdata/interrupt-avr.out.ll | 2 | ||||
-rw-r--r-- | transform/testdata/interrupt-cortexm.out.ll | 4 | ||||
-rw-r--r-- | transform/testdata/wasm-abi.out.ll | 2 | ||||
-rw-r--r-- | transform/transform_test.go | 21 |
25 files changed, 165 insertions, 118 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml index 31d6051f5..13d85e1a6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,24 +41,24 @@ commands: steps: - restore_cache: keys: - - llvm-source-9-v0 + - llvm-source-10-v0 - run: name: "Fetch LLVM source" command: make llvm-source - save_cache: - key: llvm-source-9-v0 + key: llvm-source-10-v0 paths: - llvm-project build-wasi-libc: steps: - restore_cache: keys: - - wasi-libc-sysroot-v1 + - wasi-libc-sysroot-v2 - run: name: "Build wasi-libc" command: make wasi-libc - save_cache: - key: wasi-libc-sysroot-v1 + key: wasi-libc-sysroot-v2 paths: - lib/wasi-libc/sysroot test-linux: @@ -66,7 +66,7 @@ commands: - checkout - submodules - apt-dependencies: - llvm: "-9" + llvm: "-10" - install-node - restore_cache: keys: @@ -76,10 +76,10 @@ commands: - run: go install . - restore_cache: keys: - - wasi-libc-sysroot-systemclang-v0 + - wasi-libc-sysroot-systemclang-v1 - run: make wasi-libc - save_cache: - key: wasi-libc-sysroot-systemclang-v0 + key: wasi-libc-sysroot-systemclang-v1 paths: - lib/wasi-libc/sysroot - run: go test -v ./cgo ./compileopts ./interp ./transform . @@ -117,7 +117,7 @@ commands: - llvm-source-linux - restore_cache: keys: - - llvm-build-9-linux-v0-assert + - llvm-build-10-linux-v0-assert - run: name: "Build LLVM" command: | @@ -135,7 +135,7 @@ commands: make ASSERT=1 llvm-build fi - save_cache: - key: llvm-build-9-linux-v0-assert + key: llvm-build-10-linux-v0-assert paths: llvm-build - run: make ASSERT=1 @@ -176,7 +176,7 @@ commands: - llvm-source-linux - restore_cache: keys: - - llvm-build-9-linux-v0 + - llvm-build-10-linux-v0 - run: name: "Build LLVM" command: | @@ -194,7 +194,7 @@ commands: make llvm-build fi - save_cache: - key: llvm-build-9-linux-v0 + key: llvm-build-10-linux-v0 paths: llvm-build - build-wasi-libc @@ -239,17 +239,17 @@ commands: - go-cache-macos-v2-{{ checksum "go.mod" }} - restore_cache: keys: - - llvm-source-9-macos-v0 + - llvm-source-10-macos-v0 - run: name: "Fetch LLVM source" command: make llvm-source - save_cache: - key: llvm-source-9-macos-v0 + key: llvm-source-10-macos-v0 paths: - llvm-project - restore_cache: keys: - - llvm-build-9-macos-v0 + - llvm-build-10-macos-v0 - run: name: "Build LLVM" command: | @@ -261,7 +261,7 @@ commands: make llvm-build fi - save_cache: - key: llvm-build-9-macos-v0 + key: llvm-build-10-macos-v0 paths: llvm-build - restore_cache: @@ -306,17 +306,17 @@ commands: jobs: - test-llvm9-go111: + test-llvm10-go111: docker: - image: circleci/golang:1.11-buster steps: - test-linux - test-llvm9-go112: + test-llvm10-go112: docker: - image: circleci/golang:1.12-buster steps: - test-linux - test-llvm9-go113: + test-llvm10-go113: docker: - image: circleci/golang:1.13-buster steps: @@ -343,9 +343,9 @@ jobs: workflows: test-all: jobs: - - test-llvm9-go111 - - test-llvm9-go112 - - test-llvm9-go113 + - test-llvm10-go111 + - test-llvm10-go112 + - test-llvm10-go113 - build-linux - build-macos - assert-test-linux diff --git a/Dockerfile b/Dockerfile index 80ae1046c..4632c4fb2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ -# TinyGo base stage installs Go 1.13, LLVM 9 and the TinyGo compiler itself. +# TinyGo base stage installs Go 1.13, LLVM 10 and the TinyGo compiler itself. FROM golang:1.13 AS tinygo-base RUN wget -O- https://apt.llvm.org/llvm-snapshot.gpg.key| apt-key add - && \ - echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-9 main" >> /etc/apt/sources.list && \ + echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-10 main" >> /etc/apt/sources.list && \ apt-get update && \ - apt-get install -y llvm-9-dev libclang-9-dev git + apt-get install -y llvm-10-dev libclang-10-dev git COPY . /tinygo @@ -28,9 +28,9 @@ COPY --from=tinygo-base /tinygo/src /tinygo/src COPY --from=tinygo-base /tinygo/targets /tinygo/targets RUN wget -O- https://apt.llvm.org/llvm-snapshot.gpg.key| apt-key add - && \ - echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-9 main" >> /etc/apt/sources.list && \ + echo "deb http://apt.llvm.org/buster/ llvm-toolchain-buster-10 main" >> /etc/apt/sources.list && \ apt-get update && \ - apt-get install -y libllvm9 lld-9 + apt-get install -y libllvm10 lld-10 # tinygo-avr stage installs the needed dependencies to compile TinyGo programs for AVR microcontrollers. FROM tinygo-base AS tinygo-avr @@ -61,7 +61,7 @@ COPY --from=tinygo-base /tinygo/lib /tinygo/lib RUN cd /tinygo/ && \ apt-get update && \ - apt-get install -y apt-utils make clang-9 && \ + apt-get install -y apt-utils make clang-10 && \ make gen-device-nrf && make gen-device-stm32 # tinygo-all stage installs the needed dependencies to compile TinyGo programs for all platforms. @@ -73,7 +73,7 @@ COPY --from=tinygo-base /tinygo/lib /tinygo/lib RUN cd /tinygo/ && \ apt-get update && \ - apt-get install -y apt-utils make clang-9 binutils-avr gcc-avr avr-libc && \ + apt-get install -y apt-utils make clang-10 binutils-avr gcc-avr avr-libc && \ make gen-device CMD ["tinygo"] @@ -12,19 +12,19 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld ifneq (, $(shell command -v llvm-build/bin/clang 2> /dev/null)) CLANG ?= $(abspath llvm-build/bin/clang) else - CLANG ?= clang-9 + CLANG ?= clang-10 endif ifneq (, $(shell command -v llvm-build/bin/llvm-ar 2> /dev/null)) LLVM_AR ?= $(abspath llvm-build/bin/llvm-ar) -else ifneq (, $(shell command -v llvm-ar-9 2> /dev/null)) - LLVM_AR ?= llvm-ar-9 +else ifneq (, $(shell command -v llvm-ar-10 2> /dev/null)) + LLVM_AR ?= llvm-ar-10 else LLVM_AR ?= llvm-ar endif ifneq (, $(shell command -v llvm-build/bin/llvm-nm 2> /dev/null)) LLVM_NM ?= $(abspath llvm-build/bin/llvm-nm) -else ifneq (, $(shell command -v llvm-nm-9 2> /dev/null)) - LLVM_NM ?= llvm-nm-9 +else ifneq (, $(shell command -v llvm-nm-10 2> /dev/null)) + LLVM_NM ?= llvm-nm-10 else LLVM_NM ?= llvm-nm endif @@ -53,7 +53,7 @@ endif .PHONY: all tinygo test $(LLVM_BUILDDIR) llvm-source clean fmt gen-device gen-device-nrf gen-device-avr -LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target +LLVM_COMPONENTS = all-targets analysis asmparser asmprinter bitreader bitwriter codegen core coroutines coverage debuginfodwarf executionengine frontendopenmp instrumentation interpreter ipo irreader linker lto mc mcjit objcarcopts option profiledata scalaropts support target ifeq ($(OS),Windows_NT) EXE = .exe @@ -103,8 +103,8 @@ LLD_LIBS = $(START_GROUP) -llldCOFF -llldCommon -llldCore -llldDriver -llldELF - # For static linking. ifneq ("$(wildcard $(LLVM_BUILDDIR)/bin/llvm-config*)","") CGO_CPPFLAGS=$(shell $(LLVM_BUILDDIR)/bin/llvm-config --cppflags) -I$(abspath $(LLVM_BUILDDIR))/tools/clang/include -I$(abspath $(CLANG_SRC))/include -I$(abspath $(LLD_SRC))/include - CGO_CXXFLAGS=-std=c++11 - CGO_LDFLAGS+=$(LIBCLANG_PATH) -std=c++11 -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA) + CGO_CXXFLAGS=-std=c++14 + CGO_LDFLAGS+=$(LIBCLANG_PATH) -std=c++14 -L$(abspath $(LLVM_BUILDDIR)/lib) $(CLANG_LIBS) $(LLD_LIBS) $(shell $(LLVM_BUILDDIR)/bin/llvm-config --ldflags --libs --system-libs $(LLVM_COMPONENTS)) -lstdc++ $(CGO_LDFLAGS_EXTRA) endif @@ -148,7 +148,7 @@ gen-device-stm32: build/gen-device-svd # Get LLVM sources. $(LLVM_PROJECTDIR)/README.md: - git clone -b release/9.x https://github.com/llvm/llvm-project $(LLVM_PROJECTDIR) + git clone -b release/10.x https://github.com/llvm/llvm-project $(LLVM_PROJECTDIR) llvm-source: $(LLVM_PROJECTDIR)/README.md # Configure LLVM. @@ -135,4 +135,4 @@ The original reasoning was: if [Python](https://micropython.org/) can run on mic This project is licensed under the BSD 3-clause license, just like the [Go project](https://golang.org/LICENSE) itself. -Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/9.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files. +Some code has been copied from the LLVM project and is therefore licensed under [a variant of the Apache 2.0 license](http://releases.llvm.org/10.0.0/LICENSE.TXT). This has been clearly indicated in the header of these files. diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d8c4b8a47..135dcf414 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,12 +12,12 @@ jobs: steps: - task: GoTool@0 inputs: - version: '1.13.8' + version: '1.13.8' - checkout: self - task: CacheBeta@0 displayName: Cache LLVM source inputs: - key: llvm-source-9-windows-v0 + key: llvm-source-10-windows-v0 path: llvm-project - task: Bash@3 displayName: Download LLVM source @@ -27,7 +27,7 @@ jobs: - task: CacheBeta@0 displayName: Cache LLVM build inputs: - key: llvm-build-9-windows-v0 + key: llvm-build-10-windows-v0 path: llvm-build - task: Bash@3 displayName: Build LLVM @@ -37,10 +37,6 @@ jobs: if [ ! -f llvm-build/lib/liblldELF.a ] then choco install ninja - # LLVM 9 cannot be built with MinGW 8. - # For details: https://reviews.llvm.org/D70266 - choco uninstall mingw - choco install mingw --version=7.3.0 make llvm-build fi - task: Bash@3 @@ -51,7 +47,7 @@ jobs: - task: CacheBeta@0 displayName: Cache wasi-libc sysroot inputs: - key: wasi-libc-sysroot-v1 + key: wasi-libc-sysroot-v2 path: lib/wasi-libc/sysroot - task: Bash@3 displayName: Build wasi-libc diff --git a/builder/cc1as.cpp b/builder/cc1as.cpp index 95b0a0a44..d8e402889 100644 --- a/builder/cc1as.cpp +++ b/builder/cc1as.cpp @@ -48,6 +48,7 @@ #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -70,12 +71,12 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, bool Success = true; // Parse the arguments. - std::unique_ptr<OptTable> OptTbl(createDriverOptTable()); + const OptTable &OptTbl = getDriverOptTable(); const unsigned IncludedFlagsBitmask = options::CC1AsOption; unsigned MissingArgIndex, MissingArgCount; - InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount, - IncludedFlagsBitmask); + InputArgList Args = OptTbl.ParseArgs(Argv, MissingArgIndex, MissingArgCount, + IncludedFlagsBitmask); // Check for missing argument error. if (MissingArgCount) { @@ -88,7 +89,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { auto ArgString = A->getAsString(Args); std::string Nearest; - if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) + if (OptTbl.findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) Diags.Report(diag::err_drv_unknown_argument) << ArgString; else Diags.Report(diag::err_drv_unknown_argument_with_suggestion) @@ -181,6 +182,7 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); + Opts.NoWarn = Args.hasArg(OPT_massembler_no_warn); Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); Opts.TargetABI = Args.getLastArgValue(OPT_target_abi); Opts.IncrementalLinkerCompatible = @@ -208,8 +210,8 @@ getOutputStream(StringRef Path, DiagnosticsEngine &Diags, bool Binary) { sys::RemoveFileOnSignal(Path); std::error_code EC; - auto Out = llvm::make_unique<raw_fd_ostream>( - Path, EC, (Binary ? sys::fs::F_None : sys::fs::F_Text)); + auto Out = std::make_unique<raw_fd_ostream>( + Path, EC, (Binary ? sys::fs::OF_None : sys::fs::OF_Text)); if (EC) { Diags.Report(diag::err_fe_unable_to_open_output) << Path << EC.message(); return nullptr; @@ -245,7 +247,9 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(Opts.Triple)); assert(MRI && "Unable to create target register info!"); - std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, Opts.Triple)); + MCTargetOptions MCOptions; + std::unique_ptr<MCAsmInfo> MAI( + TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions)); assert(MAI && "Unable to create target asm info!"); // Ensure MCAsmInfo initialization occurs before any use, otherwise sections @@ -269,7 +273,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { // MCObjectFileInfo needs a MCContext reference in order to initialize itself. std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo()); - MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr); + MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &SrcMgr, &MCOptions); bool PIC = false; if (Opts.RelocationModel == "static") { @@ -326,7 +330,8 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { raw_pwrite_stream *Out = FDOS.get(); std::unique_ptr<buffer_ostream> BOS; - MCTargetOptions MCOptions; + MCOptions.MCNoWarn = Opts.NoWarn; + MCOptions.MCFatalWarnings = Opts.FatalWarnings; MCOptions.ABIName = Opts.TargetABI; // FIXME: There is a bit of code duplication with addPassesToEmitFile. @@ -340,7 +345,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); - auto FOut = llvm::make_unique<formatted_raw_ostream>(*Out); + auto FOut = std::make_unique<formatted_raw_ostream>(*Out); Str.reset(TheTarget->createAsmStreamer( Ctx, std::move(FOut), /*asmverbose*/ true, /*useDwarfDirectory*/ true, IP, std::move(CE), std::move(MAB), @@ -351,7 +356,7 @@ bool ExecuteAssembler(AssemblerInvocation &Opts, DiagnosticsEngine &Diags) { assert(Opts.OutputType == AssemblerInvocation::FT_Obj && "Invalid file type!"); if (!FDOS->supportsSeeking()) { - BOS = make_unique<buffer_ostream>(*FDOS); + BOS = std::make_unique<buffer_ostream>(*FDOS); Out = BOS.get(); } @@ -436,7 +441,7 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message, Diags.Report(diag::err_fe_error_backend) << Message; // We cannot recover from llvm errors. - exit(1); + sys::Process::Exit(1); } int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { @@ -464,11 +469,11 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { return 1; if (Asm.ShowHelp) { - std::unique_ptr<OptTable> Opts(driver::createDriverOptTable()); - Opts->PrintHelp(llvm::outs(), "clang -cc1as [options] file...", - "Clang Integrated Assembler", - /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0, - /*ShowAllAliases=*/false); + getDriverOptTable().PrintHelp( + llvm::outs(), "clang -cc1as [options] file...", + "Clang Integrated Assembler", + /*Include=*/driver::options::CC1AsOption, /*Exclude=*/0, + /*ShowAllAliases=*/false); return 0; } @@ -485,7 +490,7 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { // FIXME: Remove this, one day. if (!Asm.LLVMArgs.empty()) { unsigned NumArgs = Asm.LLVMArgs.size(); - auto Args = llvm::make_unique<const char*[]>(NumArgs + 2); + auto Args = std::make_unique<const char*[]>(NumArgs + 2); Args[0] = "clang (LLVM option parsing)"; for (unsigned i = 0; i != NumArgs; ++i) Args[i + 1] = Asm.LLVMArgs[i].c_str(); @@ -499,6 +504,7 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { // If any timers were active but haven't been destroyed yet, print their // results now. TimerGroup::printAll(errs()); + TimerGroup::clearAll(); return !!Failed; } diff --git a/builder/cc1as.h b/builder/cc1as.h index 1475adc1c..ce9a1781c 100644 --- a/builder/cc1as.h +++ b/builder/cc1as.h @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" - /// Helper class for representing a single invocation of the assembler. struct AssemblerInvocation { /// @name Target Options @@ -82,6 +80,7 @@ struct AssemblerInvocation { unsigned RelaxAll : 1; unsigned NoExecStack : 1; unsigned FatalWarnings : 1; + unsigned NoWarn : 1; unsigned IncrementalLinkerCompatible : 1; unsigned EmbedBitcode : 1; @@ -107,6 +106,7 @@ public: RelaxAll = 0; NoExecStack = 0; FatalWarnings = 0; + NoWarn = 0; IncrementalLinkerCompatible = 0; DwarfVersion = 0; EmbedBitcode = 0; diff --git a/builder/clang.cpp b/builder/clang.cpp index e0993bf6e..a511772ad 100644 --- a/builder/clang.cpp +++ b/builder/clang.cpp @@ -52,8 +52,7 @@ bool tinygo_clang_driver(int argc, char **argv) { std::unique_ptr<clang::CompilerInstance> Clang(new clang::CompilerInstance()); bool success = clang::CompilerInvocation::CreateFromArgs( Clang->getInvocation(), - const_cast<const char **>(CCArgs.data()), - const_cast<const char **>(CCArgs.data()) + CCArgs.size(), + CCArgs, Diags); if (!success) { return false; @@ -74,7 +73,8 @@ bool tinygo_clang_driver(int argc, char **argv) { } else if (strcmp(*CCArgs.data(), "-cc1as") == 0) { // This is the assembler frontend. Parse the arguments. AssemblerInvocation Asm; - if (!AssemblerInvocation::CreateFromArgs(Asm, llvm::ArrayRef<const char*>(CCArgs).slice(1), Diags)) + ArrayRef<const char *> Argv = llvm::ArrayRef<const char*>(CCArgs); + if (!AssemblerInvocation::CreateFromArgs(Asm, Argv.slice(1), Diags)) return false; // Execute the invocation, unless there were parsing errors. diff --git a/builder/commands.go b/builder/commands.go index ab196337d..e96aca67d 100644 --- a/builder/commands.go +++ b/builder/commands.go @@ -6,25 +6,28 @@ import ( "os/exec" "runtime" "strings" + + "tinygo.org/x/go-llvm" ) // Commands lists command alternatives for various operating systems. These // commands may have a slightly different name across operating systems and // distributions or may not even exist in $PATH, in which case absolute paths // may be used. -var commands = map[string][]string{ - "clang": {"clang-9"}, - "ld.lld": {"ld.lld-9", "ld.lld"}, - "wasm-ld": {"wasm-ld-9", "wasm-ld"}, -} +var commands = map[string][]string{} func init() { - // Add the path to a Homebrew-installed LLVM 9 for ease of use (no need to + llvmMajor := strings.Split(llvm.Version, ".")[0] + commands["clang"] = []string{"clang-" + llvmMajor} + commands["ld.lld"] = []string{"ld.lld-" + llvmMajor, "ld.lld"} + commands["wasm-ld"] = []string{"wasm-ld-" + llvmMajor, "wasm-ld"} + // Add the path to a Homebrew-installed LLVM for ease of use (no need to // manually set $PATH). if runtime.GOOS == "darwin" { - commands["clang"] = append(commands["clang"], "/usr/local/opt/llvm@9/bin/clang-9") - commands["ld.lld"] = append(commands["ld.lld"], "/usr/local/opt/llvm@9/bin/ld.lld") - commands["wasm-ld"] = append(commands["wasm-ld"], "/usr/local/opt/llvm@9/bin/wasm-ld") + prefix := "/usr/local/opt/llvm@" + llvmMajor + "/bin/" + commands["clang"] = append(commands["clang"], prefix+"clang-"+llvmMajor) + commands["ld.lld"] = append(commands["ld.lld"], prefix+"ld.lld") + commands["wasm-ld"] = append(commands["wasm-ld"], prefix+"wasm-ld") } // Add the path for when LLVM was installed with the installer from // llvm.org, which by default doesn't add LLVM to the $PATH environment @@ -34,11 +37,12 @@ func init() { commands["ld.lld"] = append(commands["ld.lld"], "lld", "C:\\Program Files\\LLVM\\bin\\lld.exe") commands["wasm-ld"] = append(commands["wasm-ld"], "C:\\Program Files\\LLVM\\bin\\wasm-ld.exe") } - // Add the path to the llvm90 installed from ports + // Add the path to LLVM installed from ports. if runtime.GOOS == "freebsd" { - commands["clang"] = append(commands["clang"], "/usr/local/llvm90/bin/clang-9") - commands["ld.lld"] = append(commands["ld.lld"], "/usr/local/llvm90/bin/ld.lld") - commands["wasm-ld"] = append(commands["wasm-ld"], "/usr/local/llvm90/bin/wasm-ld") + prefix := "/usr/local/llvm" + llvmMajor + "/bin/" + commands["clang"] = append(commands["clang"], prefix+"clang-"+llvmMajor) + commands["ld.lld"] = append(commands["ld.lld"], prefix+"ld.lld") + commands["wasm-ld"] = append(commands["wasm-ld"], prefix+"wasm-ld") } } diff --git a/builder/lld.cpp b/builder/lld.cpp index 2373edeec..9231df9cf 100644 --- a/builder/lld.cpp +++ b/builder/lld.cpp @@ -8,12 +8,12 @@ extern "C" { bool tinygo_link_elf(int argc, char **argv) { std::vector<const char*> args(argv, argv + argc); - return lld::elf::link(args, false); + return lld::elf::link(args, false, llvm::outs(), llvm::errs()); } bool tinygo_link_wasm(int argc, char **argv) { std::vector<const char*> args(argv, argv + argc); - return lld::wasm::link(args, false); + return lld::wasm::link(args, false, llvm::outs(), llvm::errs()); } } // external "C" diff --git a/cgo/libclang.go b/cgo/libclang.go index 3aaded21e..3d7695b5e 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -15,7 +15,7 @@ import ( ) /* -#include <clang-c/Index.h> // if this fails, install libclang-9-dev +#include <clang-c/Index.h> // if this fails, install libclang-10-dev #include <stdlib.h> #include <stdint.h> diff --git a/cgo/libclang_config.go b/cgo/libclang_config.go index 908d7d5ba..ec65d8a89 100644 --- a/cgo/libclang_config.go +++ b/cgo/libclang_config.go @@ -1,13 +1,14 @@ // +build !byollvm +// +build !llvm9 package cgo /* -#cgo linux CFLAGS: -I/usr/lib/llvm-9/include -#cgo darwin CFLAGS: -I/usr/local/opt/llvm@9/include -#cgo freebsd CFLAGS: -I/usr/local/llvm90/include -#cgo linux LDFLAGS: -L/usr/lib/llvm-9/lib -lclang -#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@9/lib -lclang -lffi -#cgo freebsd LDFLAGS: -L/usr/local/llvm90/lib -lclang +#cgo linux CFLAGS: -I/usr/lib/llvm-10/include +#cgo darwin CFLAGS: -I/usr/local/opt/llvm@10/include +#cgo freebsd CFLAGS: -I/usr/local/llvm10/include +#cgo linux LDFLAGS: -L/usr/lib/llvm-10/lib -lclang +#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@10/lib -lclang -lffi +#cgo freebsd LDFLAGS: -L/usr/local/llvm10/lib -lclang */ import "C" diff --git a/cgo/libclang_config_llvm9.go b/cgo/libclang_config_llvm9.go new file mode 100644 index 000000000..6e09b01ad --- /dev/null +++ b/cgo/libclang_config_llvm9.go @@ -0,0 +1,14 @@ +// +build !byollvm +// +build llvm9 + +package cgo + +/* +#cgo linux CFLAGS: -I/usr/lib/llvm-9/include +#cgo darwin CFLAGS: -I/usr/local/opt/llvm@9/include +#cgo freebsd CFLAGS: -I/usr/local/llvm9/include +#cgo linux LDFLAGS: -L/usr/lib/llvm-9/lib -lclang +#cgo darwin LDFLAGS: -L/usr/local/opt/llvm@9/lib -lclang -lffi +#cgo freebsd LDFLAGS: -L/usr/local/llvm9/lib -lclang +*/ +import "C" diff --git a/cgo/libclang_stubs.c b/cgo/libclang_stubs.c index 9c193076b..293ca6026 100644 --- a/cgo/libclang_stubs.c +++ b/cgo/libclang_stubs.c @@ -3,7 +3,7 @@ // are slightly different from the ones defined in libclang.go, but they // should be ABI compatible. -#include <clang-c/Index.h> // if this fails, install libclang-9-dev +#include <clang-c/Index.h> // if this fails, install libclang-10-dev CXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) { return clang_getTranslationUnitCursor(tu); @@ -9,5 +9,5 @@ require ( go.bug.st/serial v1.0.0 golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2 google.golang.org/appengine v1.4.0 // indirect - tinygo.org/x/go-llvm v0.0.0-20200226165415-53522ab6713d + tinygo.org/x/go-llvm v0.0.0-20200401165421-8d120882fc7a ) @@ -15,6 +15,7 @@ go.bug.st/serial v1.0.0 h1:ogEPzrllCsnG00EqKRjeYvPRsO7NJW6DqykzkdD6E/k= go.bug.st/serial v1.0.0/go.mod h1:rpXPISGjuNjPTRTcMlxi9lN6LoIPxd1ixVjBd8aSk/Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -31,6 +32,7 @@ golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef h1:ymc9FeDom3RIEA3coKokSll golang.org/x/tools v0.0.0-20190227180812-8dcc6e70cdef/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2 h1:0sfSpGSa544Fwnbot3Oxq/U6SXqjty6Jy/3wRhVS7ig= golang.org/x/tools v0.0.0-20200216192241-b320d3a0f5a2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -53,3 +55,5 @@ tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566 h1:a4y30bTf7U0zDA75v2PTL tinygo.org/x/go-llvm v0.0.0-20200104190746-1ff21df33566/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE= tinygo.org/x/go-llvm v0.0.0-20200226165415-53522ab6713d h1:mtgZh/e8a3wxneQFuLXoQYO//1mvlki02yZ1JCwMKp4= tinygo.org/x/go-llvm v0.0.0-20200226165415-53522ab6713d/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE= +tinygo.org/x/go-llvm v0.0.0-20200401165421-8d120882fc7a h1:Ugje2Lxuv8CFncHzs5W+hWfJvPsM+W4K0zRvzFbLvoE= +tinygo.org/x/go-llvm v0.0.0-20200401165421-8d120882fc7a/go.mod h1:fv1F0BSNpxMfCL0zF3M4OPFbgYHnhtB6ST0HvUtu/LE= diff --git a/loader/loader.go b/loader/loader.go index 8c13cb813..5682bfa4a 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -423,7 +423,7 @@ func (p *Package) parseFiles(includeTests bool) ([]*ast.File, error) { if len(p.CgoFiles) != 0 { cflags := append(p.CFlags, "-I"+p.Package.Dir) if p.ClangHeaders != "" { - cflags = append(cflags, "-I"+p.ClangHeaders) + cflags = append(cflags, "-Xclang", "-internal-isystem", "-Xclang", p.ClangHeaders) } generated, errs := cgo.Process(files, p.Program.Dir, p.fset, cflags) if errs != nil { @@ -23,6 +23,7 @@ import ( "github.com/tinygo-org/tinygo/goenv" "github.com/tinygo-org/tinygo/interp" "github.com/tinygo-org/tinygo/loader" + "tinygo.org/x/go-llvm" "go.bug.st/serial" ) @@ -902,7 +903,7 @@ func main() { if s, err := builder.GorootVersionString(goenv.Get("GOROOT")); err == nil { goversion = s } - fmt.Printf("tinygo version %s %s/%s (using go version %s)\n", version, runtime.GOOS, runtime.GOARCH, goversion) + fmt.Printf("tinygo version %s %s/%s (using go version %s and LLVM version %s)\n", version, runtime.GOOS, runtime.GOARCH, goversion, llvm.Version) case "env": if flag.NArg() == 0 { // Show all environment variables. diff --git a/transform/testdata/coroutines.out.ll b/transform/testdata/coroutines.out.ll index b46a414f0..c7850a5b1 100644 --- a/transform/testdata/coroutines.out.ll +++ b/transform/testdata/coroutines.out.ll @@ -32,7 +32,7 @@ declare void @callMain(i8*, i8*) declare void @enqueueTimer(%"internal/task.Task"*, i64, i8*, i8*) -define void @sleep(i64, i8*, i8* %parentHandle) { +define void @sleep(i64 %0, i8* %1, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %task.current1 = bitcast i8* %parentHandle to %"internal/task.Task"* @@ -40,7 +40,7 @@ entry: ret void } -define i32 @delayedValue(i32, i64, i8*, i8* %parentHandle) { +define i32 @delayedValue(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %ret.ptr = call i8* @"(*internal/task.Task).getReturnPtr"(%"internal/task.Task"* %task.current, i8* undef, i8* undef) @@ -50,20 +50,20 @@ entry: ret i32 undef } -define void @deadlock(i8*, i8* %parentHandle) { +define void @deadlock(i8* %0, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* ret void } -define i32 @tail(i32, i64, i8*, i8* %parentHandle) { +define i32 @tail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %3 = call i32 @delayedValue(i32 %0, i64 %1, i8* undef, i8* %parentHandle) ret i32 undef } -define void @ditchTail(i32, i64, i8*, i8* %parentHandle) { +define void @ditchTail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %ret.ditch = call i8* @runtime.alloc(i32 4, i8* undef, i8* undef) @@ -72,14 +72,14 @@ entry: ret void } -define void @voidTail(i32, i64, i8*, i8* %parentHandle) { +define void @voidTail(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* call void @ditchTail(i32 %0, i64 %1, i8* undef, i8* %parentHandle) ret void } -define i32 @alternateTail(i32, i32, i64, i8*, i8* %parentHandle) { +define i32 @alternateTail(i32 %0, i32 %1, i64 %2, i8* %3, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* %ret.ptr = call i8* @"(*internal/task.Task).getReturnPtr"(%"internal/task.Task"* %task.current, i8* undef, i8* undef) @@ -91,7 +91,7 @@ entry: ret i32 undef } -define i1 @coroutine(i32, i64, i8*, i8* %parentHandle) { +define i1 @coroutine(i32 %0, i64 %1, i8* %2, i8* %parentHandle) { entry: %call.return = alloca i32 %coro.id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null) @@ -133,18 +133,18 @@ cleanup: ; preds = %entry, %wakeup br label %suspend } -define void @doNothing(i8*, i8*) { +define void @doNothing(i8* %0, i8* %1) { entry: ret void } -define void @sleepGoroutine(i8*, i8* %parentHandle) { +define void @sleepGoroutine(i8* %0, i8* %parentHandle) { %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* call void @sleep(i64 1000000, i8* undef, i8* %parentHandle) ret void } -define void @progMain(i8*, i8* %parentHandle) { +define void @progMain(i8* %0, i8* %parentHandle) { entry: %task.current = bitcast i8* %parentHandle to %"internal/task.Task"* call void @doNothing(i8* undef, i8* undef) @@ -185,13 +185,13 @@ declare i8* @llvm.coro.free(token, i8* nocapture readonly) #0 ; Function Attrs: nounwind declare token @llvm.coro.save(i8*) #2 -; Function Attrs: argmemonly nounwind +; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #3 -; Function Attrs: argmemonly nounwind +; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #3 attributes #0 = { argmemonly nounwind readonly } attributes #1 = { nounwind readnone } attributes #2 = { nounwind } -attributes #3 = { argmemonly nounwind } +attributes #3 = { argmemonly nounwind willreturn } diff --git a/transform/testdata/func-lowering.out.ll b/transform/testdata/func-lowering.out.ll index 747d6e6e7..50558fc8f 100644 --- a/transform/testdata/func-lowering.out.ll +++ b/transform/testdata/func-lowering.out.ll @@ -29,7 +29,7 @@ declare void @func1Uint8(i8, i8*, i8*) declare void @func2Uint8(i8, i8*, i8*) -define void @runFunc1(i8*, i32, i8, i8* %context, i8* %parentHandle) { +define void @runFunc1(i8* %0, i32 %1, i8 %2, i8* %context, i8* %parentHandle) { entry: %3 = icmp eq i32 %1, 0 %4 = select i1 %3, void (i8, i8*, i8*)* null, void (i8, i8*, i8*)* @funcInt8 @@ -45,7 +45,7 @@ fpcall.next: ; preds = %entry ret void } -define void @runFunc2(i8*, i32, i8, i8* %context, i8* %parentHandle) { +define void @runFunc2(i8* %0, i32 %1, i8 %2, i8* %context, i8* %parentHandle) { entry: br i1 false, label %fpcall.nil, label %fpcall.next @@ -79,7 +79,7 @@ func.default: ; preds = %fpcall.next unreachable } -define void @sleepFuncValue(i8*, i32, i8* nocapture readnone %context, i8* nocapture readnone %parentHandle) { +define void @sleepFuncValue(i8* %0, i32 %1, i8* nocapture readnone %context, i8* nocapture readnone %parentHandle) { entry: switch i32 %1, label %func.default [ i32 0, label %func.nil diff --git a/transform/testdata/gc-stackslots.out.ll b/transform/testdata/gc-stackslots.out.ll index c24793ea9..88ee8c02a 100644 --- a/transform/testdata/gc-stackslots.out.ll +++ b/transform/testdata/gc-stackslots.out.ll @@ -94,7 +94,7 @@ entry: store i8 1, i8* %entry.y br label %loop -loop: +loop: ; preds = %loop, %entry %prev.y = phi i8* [ %entry.y, %entry ], [ %prev.x, %loop ] %prev.x = phi i8* [ %entry.x, %entry ], [ %next.x, %loop ] %5 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 5 @@ -108,7 +108,7 @@ loop: %loop.done = icmp ult i8 40, %next.x.val br i1 %loop.done, label %end, label %loop -end: +end: ; preds = %loop store %runtime.stackChainObject* %0, %runtime.stackChainObject** @runtime.stackChainStart ret i8* %next.x } diff --git a/transform/testdata/interrupt-avr.out.ll b/transform/testdata/interrupt-avr.out.ll index b71c43998..322d6516a 100644 --- a/transform/testdata/interrupt-avr.out.ll +++ b/transform/testdata/interrupt-avr.out.ll @@ -19,7 +19,7 @@ declare i32 @"runtime/interrupt.Register"(i32, i8*, i16, i8*, i8*) addrspace(1) declare void @"runtime/interrupt.use"(%"runtime/interrupt.Interrupt") addrspace(1) -define void @"(machine.UART).Configure"(%machine.RingBuffer*, i32, i8, i8, i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { +define void @"(machine.UART).Configure"(%machine.RingBuffer* %0, i32 %1, i8 %2, i8 %3, i8* %context, i8* %parentHandle) unnamed_addr addrspace(1) { ret void } diff --git a/transform/testdata/interrupt-cortexm.out.ll b/transform/testdata/interrupt-cortexm.out.ll index 41fa9a776..2e35f2633 100644 --- a/transform/testdata/interrupt-cortexm.out.ll +++ b/transform/testdata/interrupt-cortexm.out.ll @@ -16,14 +16,14 @@ declare void @"device/arm.EnableIRQ"(i32, i8* nocapture readnone, i8* nocapture declare void @"device/arm.SetPriority"(i32, i32, i8* nocapture readnone, i8* nocapture readnone) -define void @runtime.initAll(i8* nocapture readnone, i8* nocapture readnone) unnamed_addr { +define void @runtime.initAll(i8* nocapture readnone %0, i8* nocapture readnone %1) unnamed_addr { entry: call void @"device/arm.SetPriority"(i32 2, i32 192, i8* undef, i8* undef) call void @"device/arm.EnableIRQ"(i32 2, i8* undef, i8* undef) ret void } -define internal void @"(*machine.UART).handleInterrupt$bound"(i32, i8* nocapture %context, i8* nocapture readnone %parentHandle) { +define internal void @"(*machine.UART).handleInterrupt$bound"(i32 %0, i8* nocapture %context, i8* nocapture readnone %parentHandle) { entry: %unpack.ptr = bitcast i8* %context to %machine.UART* call void @"(*machine.UART).handleInterrupt"(%machine.UART* %unpack.ptr, i32 %0, i8* undef, i8* undef) diff --git a/transform/testdata/wasm-abi.out.ll b/transform/testdata/wasm-abi.out.ll index 6fb9a9482..68bed05e8 100644 --- a/transform/testdata/wasm-abi.out.ll +++ b/transform/testdata/wasm-abi.out.ll @@ -37,7 +37,7 @@ define internal void @callExportedFunction(i64 %foo) { declare void @externalCall(i64*, i8*, i32, i64*) -define void @exportedFunction(i64*) { +define void @exportedFunction(i64* %0) { entry: %i64 = load i64, i64* %0 call void @"exportedFunction$i64wrap"(i64 %i64) diff --git a/transform/transform_test.go b/transform/transform_test.go index 3905293c0..7a607f13b 100644 --- a/transform/transform_test.go +++ b/transform/transform_test.go @@ -6,6 +6,8 @@ import ( "flag" "io/ioutil" "os" + "regexp" + "strconv" "strings" "testing" @@ -82,6 +84,12 @@ func fuzzyEqualIR(s1, s2 string) bool { // stripped out. func filterIrrelevantIRLines(lines []string) []string { var out []string + llvmVersion, err := strconv.Atoi(strings.Split(llvm.Version, ".")[0]) + if err != nil { + // Note: this should never happen and if it does, it will always happen + // for a particular build because llvm.Version is a constant. + panic(err) + } for _, line := range lines { line = strings.Split(line, ";")[0] // strip out comments/info line = strings.TrimRight(line, "\r ") // drop '\r' on Windows and remove trailing spaces from comments @@ -91,6 +99,19 @@ func filterIrrelevantIRLines(lines []string) []string { if strings.HasPrefix(line, "source_filename = ") { continue } + if llvmVersion < 10 && strings.HasPrefix(line, "attributes ") { + // Ignore attribute groups. These may change between LLVM versions. + // Right now test outputs are for LLVM 10. + continue + } + if llvmVersion < 10 && strings.HasPrefix(line, "define ") { + // Remove parameter values such as %0 in function definitions. These + // were added in LLVM 10 so to get the tests to pass on older + // versions, ignore them there (there are other tests that verify + // correct behavior). + re := regexp.MustCompile(` %[0-9]+(\)|,)`) + line = re.ReplaceAllString(line, "$1") + } out = append(out, line) } return out |