diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c8193ae..de7d5dfa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -373,12 +373,12 @@ commands: - /go/pkg/mod jobs: - test-llvm10-go115: + test-llvm11-go115: docker: - image: circleci/golang:1.15-buster steps: - test-linux: - llvm: "10" + llvm: "11" test-llvm11-go116: docker: - image: circleci/golang:1.16-buster @@ -406,7 +406,7 @@ jobs: workflows: test-all: jobs: - - test-llvm10-go115 + - test-llvm11-go115 - test-llvm11-go116 - build-linux - build-macos diff --git a/Makefile b/Makefile index 3af2c52f..6c569be8 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ LLD_SRC ?= $(LLVM_PROJECTDIR)/lld # Try to autodetect LLVM build tools. detect = $(shell command -v $(1) 2> /dev/null && echo $(1)) -CLANG ?= $(word 1,$(abspath $(call detect,llvm-build/bin/clang))$(call detect,clang-11)$(call detect,clang-10)$(call detect,clang)) -LLVM_AR ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-ar))$(call detect,llvm-ar-11)$(call detect,llvm-ar-10)$(call detect,llvm-ar)) -LLVM_NM ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-nm))$(call detect,llvm-nm-11)$(call detect,llvm-nm-10)$(call detect,llvm-nm)) +CLANG ?= $(word 1,$(abspath $(call detect,llvm-build/bin/clang))$(call detect,clang-11)$(call detect,clang)) +LLVM_AR ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-ar))$(call detect,llvm-ar-11)$(call detect,llvm-ar)) +LLVM_NM ?= $(word 1,$(abspath $(call detect,llvm-build/bin/llvm-nm))$(call detect,llvm-nm-11)$(call detect,llvm-nm)) # Go binary and GOROOT to select GO ?= go diff --git a/builder/sizes.go b/builder/sizes.go index 750c4bd9..c88c9b7b 100644 --- a/builder/sizes.go +++ b/builder/sizes.go @@ -84,18 +84,7 @@ func loadProgramSize(path string) (*programSize, error) { if section.Type != elf.SHT_PROGBITS && section.Type != elf.SHT_NOBITS { continue } - if section.Name == ".stack" { - // HACK: this works around a bug in ld.lld from LLVM 10. The linker - // marks sections with no input symbols (such as is the case for the - // .stack section) as SHT_PROGBITS instead of SHT_NOBITS. While it - // doesn't affect the generated binaries (.hex and .bin), it does - // affect the reported size. - // https://bugs.llvm.org/show_bug.cgi?id=45336 - // https://reviews.llvm.org/D76981 - // It has been merged in master, but it has not (yet) been - // backported to the LLVM 10 release branch. - sumBSS += section.Size - } else if section.Type == elf.SHT_NOBITS { + if section.Type == elf.SHT_NOBITS { sumBSS += section.Size } else if section.Flags&elf.SHF_EXECINSTR != 0 { sumCode += section.Size diff --git a/cgo/libclang.go b/cgo/libclang.go index f27d7935..66f81c3d 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -16,7 +16,7 @@ import ( ) /* -#include // if this fails, install libclang-10-dev +#include // if this fails, install libclang-11-dev #include #include diff --git a/cgo/libclang_config.go b/cgo/libclang_config.go index 78783db2..4b4ce2db 100644 --- a/cgo/libclang_config.go +++ b/cgo/libclang_config.go @@ -1,5 +1,4 @@ // +build !byollvm -// +build !llvm10 package cgo diff --git a/cgo/libclang_config_llvm10.go b/cgo/libclang_config_llvm10.go deleted file mode 100644 index 9b993949..00000000 --- a/cgo/libclang_config_llvm10.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build !byollvm -// +build llvm10 - -package cgo - -/* -#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_stubs.c b/cgo/libclang_stubs.c index 293ca602..ce9e164a 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 // if this fails, install libclang-10-dev +#include // if this fails, install libclang-11-dev CXCursor tinygo_clang_getTranslationUnitCursor(CXTranslationUnit tu) { return clang_getTranslationUnitCursor(tu); diff --git a/interp/interp_test.go b/interp/interp_test.go index 9702cb83..9080de89 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -3,7 +3,6 @@ package interp import ( "io/ioutil" "os" - "regexp" "strings" "testing" @@ -88,8 +87,6 @@ func runTest(t *testing.T, pathPrefix string) { } } -var alignRegexp = regexp.MustCompile(", align [0-9]+$") - // fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly // equal. That means, only relevant lines are compared (excluding comments // etc.). @@ -101,15 +98,6 @@ func fuzzyEqualIR(s1, s2 string) bool { } for i, line1 := range lines1 { line2 := lines2[i] - match1 := alignRegexp.MatchString(line1) - match2 := alignRegexp.MatchString(line2) - if match1 != match2 { - // Only one of the lines has the align keyword. Remove it. - // This is a change to make the test work in both LLVM 10 and LLVM - // 11 (LLVM 11 appears to automatically add alignment everywhere). - line1 = alignRegexp.ReplaceAllString(line1, "") - line2 = alignRegexp.ReplaceAllString(line2, "") - } if line1 != line2 { return false } diff --git a/interp/testdata/basic.out.ll b/interp/testdata/basic.out.ll index 51a3b3f4..174f073e 100644 --- a/interp/testdata/basic.out.ll +++ b/interp/testdata/basic.out.ll @@ -18,14 +18,14 @@ entry: call void @runtime.printint64(i64 5) call void @runtime.printnl() %value1 = call i64 @someValue() - store i64 %value1, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0) - %value2 = load i64, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0) - store i64 %value2, i64* @main.nonConst2 + store i64 %value1, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0), align 8 + %value2 = load i64, i64* getelementptr inbounds ([4 x i64], [4 x i64]* @main.nonConst1, i32 0, i32 0), align 8 + store i64 %value2, i64* @main.nonConst2, align 8 call void @modifyExternal(i32* getelementptr inbounds ([8 x { i16, i32 }], [8 x { i16, i32 }]* @main.someArray, i32 0, i32 3, i32 1)) call void @modifyExternal(i32* bitcast ([1 x i16*]* @main.exportedValue to i32*)) - store i16 5, i16* @main.exposedValue1 + store i16 5, i16* @main.exposedValue1, align 2 call void @modifyExternal(i32* bitcast (void ()* @willModifyGlobal to i32*)) - store i16 7, i16* @main.exposedValue2 + store i16 7, i16* @main.exposedValue2, align 2 call void @modifyExternal(i32* bitcast (void ()* @hasInlineAsm to i32*)) call void @runtime.printint64(i64 6) call void @runtime.printint64(i64 -1) @@ -39,7 +39,7 @@ entry: %agg2.insertvalue2 = insertvalue { i64, i16 } %agg2.agg1, i64 5, 0 %agg2.insertvalue1 = insertvalue { float, { i64, i16 } } %agg2.agg0, { i64, i16 } %agg2.insertvalue2, 1 %agg2.insertvalue0 = insertvalue { i8, i32, { float, { i64, i16 } } } %agg, { float, { i64, i16 } } %agg2.insertvalue1, 2 - store { i8, i32, { float, { i64, i16 } } } %agg2.insertvalue0, { i8, i32, { float, { i64, i16 } } }* @main.insertedValue + store { i8, i32, { float, { i64, i16 } } } %agg2.insertvalue0, { i8, i32, { float, { i64, i16 } } }* @main.insertedValue, align 8 ret void } @@ -56,7 +56,7 @@ declare void @modifyExternal(i32*) local_unnamed_addr define void @willModifyGlobal() { entry: - store i16 8, i16* @main.exposedValue2 + store i16 8, i16* @main.exposedValue2, align 2 ret void } diff --git a/interp/testdata/slice-copy.out.ll b/interp/testdata/slice-copy.out.ll index f3b15950..9f88df09 100644 --- a/interp/testdata/slice-copy.out.ll +++ b/interp/testdata/slice-copy.out.ll @@ -1,7 +1,7 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64--linux" -@"main$alloc.1" = internal unnamed_addr constant [6 x i8] c"\05\00{\00\00\04" +@"main$alloc.1" = internal unnamed_addr constant [6 x i8] c"\05\00{\00\00\04", align 8 declare void @runtime.printuint8(i8) local_unnamed_addr @@ -17,7 +17,7 @@ entry: call void @runtime.printuint8(i8 3) call void @runtime.printuint8(i8 3) call void @runtime.printint16(i16 5) - %int16SliceDst.val = load i16, i16* bitcast ([6 x i8]* @"main$alloc.1" to i16*) + %int16SliceDst.val = load i16, i16* bitcast ([6 x i8]* @"main$alloc.1" to i16*), align 2 call void @runtime.printint16(i16 %int16SliceDst.val) ret void } diff --git a/src/runtime/print.go b/src/runtime/print.go index f7d3a285..04336cce 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -48,16 +48,6 @@ func printint16(n int16) { } func printuint32(n uint32) { - if TargetBits == 8 { - // AVR-specific workaround on LLVM 10. Should be removed when we switch - // to LLVM 11. - prevdigits := n / 10 - if prevdigits != 0 { - printuint32(prevdigits) - } - putchar(byte((n % 10) + '0')) - return - } printuint64(uint64(n)) } diff --git a/transform/testdata/allocs.out.ll b/transform/testdata/allocs.out.ll index eaddd464..4543ac17 100644 --- a/transform/testdata/allocs.out.ll +++ b/transform/testdata/allocs.out.ll @@ -6,21 +6,21 @@ target triple = "armv7m-none-eabi" declare nonnull i8* @runtime.alloc(i32) define void @testInt() { - %stackalloc.alloca = alloca [1 x i32] - store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca + %stackalloc.alloca = alloca [1 x i32], align 4 + store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca, align 4 %stackalloc = bitcast [1 x i32]* %stackalloc.alloca to i32* - store i32 5, i32* %stackalloc + store i32 5, i32* %stackalloc, align 4 ret void } define i16 @testArray() { - %stackalloc.alloca = alloca [2 x i32] - store [2 x i32] zeroinitializer, [2 x i32]* %stackalloc.alloca + %stackalloc.alloca = alloca [2 x i32], align 4 + store [2 x i32] zeroinitializer, [2 x i32]* %stackalloc.alloca, align 4 %stackalloc = bitcast [2 x i32]* %stackalloc.alloca to i16* %1 = getelementptr i16, i16* %stackalloc, i32 1 - store i16 5, i16* %1 + store i16 5, i16* %1, align 2 %2 = getelementptr i16, i16* %stackalloc, i32 2 - %3 = load i16, i16* %2 + %3 = load i16, i16* %2, align 2 ret i16 %3 } @@ -39,8 +39,8 @@ define void @testEscapingCall2() { } define void @testNonEscapingCall() { - %stackalloc.alloca = alloca [1 x i32] - store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca + %stackalloc.alloca = alloca [1 x i32], align 4 + store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca, align 4 %stackalloc = bitcast [1 x i32]* %stackalloc.alloca to i32* %1 = call i32* @noescapeIntPtr(i32* %stackalloc) ret void @@ -54,11 +54,11 @@ define i32* @testEscapingReturn() { define void @testNonEscapingLoop() { entry: - %stackalloc.alloca = alloca [1 x i32] + %stackalloc.alloca = alloca [1 x i32], align 4 br label %loop loop: ; preds = %loop, %entry - store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca + store [1 x i32] zeroinitializer, [1 x i32]* %stackalloc.alloca, align 4 %stackalloc = bitcast [1 x i32]* %stackalloc.alloca to i32* %0 = call i32* @noescapeIntPtr(i32* %stackalloc) %1 = icmp eq i32* null, %0 diff --git a/transform/testdata/gc-globals.out.ll b/transform/testdata/gc-globals.out.ll index 905e8eaf..78b182fb 100644 --- a/transform/testdata/gc-globals.out.ll +++ b/transform/testdata/gc-globals.out.ll @@ -14,18 +14,18 @@ target triple = "wasm32-unknown-unknown-wasm" @runtime.trackedGlobalsBitmap.1 = internal global [1 x i8] c"\09" define void @main() { - %1 = load i32, i32* @globalInt - %2 = load %runtime._string, %runtime._string* getelementptr inbounds ({ %runtime._string, %runtime._interface }, { %runtime._string, %runtime._interface }* @tinygo.trackedGlobals, i32 0, i32 0) - %3 = load %runtime._interface, %runtime._interface* getelementptr inbounds ({ %runtime._string, %runtime._interface }, { %runtime._string, %runtime._interface }* @tinygo.trackedGlobals, i32 0, i32 1) - %4 = load %runtime._string, %runtime._string* @constString - %5 = load %runtime._interface, %runtime._interface* @constInterface + %1 = load i32, i32* @globalInt, align 4 + %2 = load %runtime._string, %runtime._string* getelementptr inbounds ({ %runtime._string, %runtime._interface }, { %runtime._string, %runtime._interface }* @tinygo.trackedGlobals, i32 0, i32 0), align 4 + %3 = load %runtime._interface, %runtime._interface* getelementptr inbounds ({ %runtime._string, %runtime._interface }, { %runtime._string, %runtime._interface }* @tinygo.trackedGlobals, i32 0, i32 1), align 4 + %4 = load %runtime._string, %runtime._string* @constString, align 4 + %5 = load %runtime._interface, %runtime._interface* @constInterface, align 4 ret void } define void @runtime.markGlobals() { - %1 = load i32, i32* @runtime.trackedGlobalsStart - %2 = load i32, i32* @runtime.trackedGlobalsLength + %1 = load i32, i32* @runtime.trackedGlobalsStart, align 4 + %2 = load i32, i32* @runtime.trackedGlobalsLength, align 4 %3 = getelementptr inbounds [0 x i8], [0 x i8]* bitcast ([1 x i8]* @runtime.trackedGlobalsBitmap.1 to [0 x i8]*), i32 0, i32 0 - %4 = load i8, i8* %3 + %4 = load i8, i8* %3, align 1 ret void } diff --git a/transform/testdata/gc-stackslots.out.ll b/transform/testdata/gc-stackslots.out.ll index 0edb9168..af474534 100644 --- a/transform/testdata/gc-stackslots.out.ll +++ b/transform/testdata/gc-stackslots.out.ll @@ -15,44 +15,44 @@ define i8* @getPointer() { } define i8* @needsStackSlots() { - %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* } - store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject - %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart + %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* }, align 8 + store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, align 4 + %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %2 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 0 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4 %3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject* - store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart + store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %ptr = call i8* @runtime.alloc(i32 4) %4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2 - store i8* %ptr, i8** %4 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart + store i8* %ptr, i8** %4, align 4 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 call void @someArbitraryFunction() - %val = load i8, i8* @someGlobal + %val = load i8, i8* @someGlobal, align 1 ret i8* %ptr } define i8* @needsStackSlots2() { - %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } - store { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } { %runtime.stackChainObject* null, i32 5, i8* null, i8* null, i8* null, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject - %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart + %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, align 8 + store { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } { %runtime.stackChainObject* null, i32 5, i8* null, i8* null, i8* null, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, align 4 + %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %2 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 0 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4 %3 = bitcast { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject to %runtime.stackChainObject* - store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart + store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %ptr1 = call i8* @getPointer() %4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 4 - store i8* %ptr1, i8** %4 + store i8* %ptr1, i8** %4, align 4 %5 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 3 - store i8* %ptr1, i8** %5 + store i8* %ptr1, i8** %5, align 4 %6 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 2 - store i8* %ptr1, i8** %6 + store i8* %ptr1, i8** %6, align 4 %ptr2 = getelementptr i8, i8* @someGlobal, i32 0 %7 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 5 - store i8* %ptr2, i8** %7 + store i8* %ptr2, i8** %7, align 4 %unused = call i8* @runtime.alloc(i32 4) %8 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 6 - store i8* %unused, i8** %8 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart + store i8* %unused, i8** %8, align 4 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 ret i8* %ptr1 } @@ -62,79 +62,79 @@ define i8* @noAllocatingFunction() { } define i8* @fibNext(i8* %x, i8* %y) { - %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* } - store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject - %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart + %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8* }, align 8 + store { %runtime.stackChainObject*, i32, i8* } { %runtime.stackChainObject* null, i32 1, i8* null }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, align 4 + %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %2 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 0 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4 %3 = bitcast { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject to %runtime.stackChainObject* - store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart - %x.val = load i8, i8* %x - %y.val = load i8, i8* %y + store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4 + %x.val = load i8, i8* %x, align 1 + %y.val = load i8, i8* %y, align 1 %out.val = add i8 %x.val, %y.val %out.alloc = call i8* @runtime.alloc(i32 1) %4 = getelementptr { %runtime.stackChainObject*, i32, i8* }, { %runtime.stackChainObject*, i32, i8* }* %gc.stackobject, i32 0, i32 2 - store i8* %out.alloc, i8** %4 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart - store i8 %out.val, i8* %out.alloc + store i8* %out.alloc, i8** %4, align 4 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 + store i8 %out.val, i8* %out.alloc, align 1 ret i8* %out.alloc } define i8* @allocLoop() { entry: - %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } - store { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } { %runtime.stackChainObject* null, i32 5, i8* null, i8* null, i8* null, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject - %0 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart + %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, align 8 + store { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* } { %runtime.stackChainObject* null, i32 5, i8* null, i8* null, i8* null, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, align 4 + %0 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %1 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 0 - store %runtime.stackChainObject* %0, %runtime.stackChainObject** %1 + store %runtime.stackChainObject* %0, %runtime.stackChainObject** %1, align 4 %2 = bitcast { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject to %runtime.stackChainObject* - store %runtime.stackChainObject* %2, %runtime.stackChainObject** @runtime.stackChainStart + store %runtime.stackChainObject* %2, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %entry.x = call i8* @runtime.alloc(i32 1) %3 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 2 - store i8* %entry.x, i8** %3 + store i8* %entry.x, i8** %3, align 4 %entry.y = call i8* @runtime.alloc(i32 1) %4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 3 - store i8* %entry.y, i8** %4 - store i8 1, i8* %entry.y + store i8* %entry.y, i8** %4, align 4 + store i8 1, i8* %entry.y, align 1 br label %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 - store i8* %prev.y, i8** %5 + store i8* %prev.y, i8** %5, align 4 %6 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 4 - store i8* %prev.x, i8** %6 + store i8* %prev.x, i8** %6, align 4 %next.x = call i8* @fibNext(i8* %prev.x, i8* %prev.y) %7 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8*, i8*, i8*, i8* }* %gc.stackobject, i32 0, i32 6 - store i8* %next.x, i8** %7 - %next.x.val = load i8, i8* %next.x + store i8* %next.x, i8** %7, align 4 + %next.x.val = load i8, i8* %next.x, align 1 %loop.done = icmp ult i8 40, %next.x.val br i1 %loop.done, label %end, label %loop end: ; preds = %loop - store %runtime.stackChainObject* %0, %runtime.stackChainObject** @runtime.stackChainStart + store %runtime.stackChainObject* %0, %runtime.stackChainObject** @runtime.stackChainStart, align 4 ret i8* %next.x } declare [32 x i8]* @arrayAlloc() define void @testGEPBitcast() { - %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8* } - store { %runtime.stackChainObject*, i32, i8*, i8* } { %runtime.stackChainObject* null, i32 2, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject - %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart + %gc.stackobject = alloca { %runtime.stackChainObject*, i32, i8*, i8* }, align 8 + store { %runtime.stackChainObject*, i32, i8*, i8* } { %runtime.stackChainObject* null, i32 2, i8* null, i8* null }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, align 4 + %1 = load %runtime.stackChainObject*, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %2 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 0 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** %2, align 4 %3 = bitcast { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject to %runtime.stackChainObject* - store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart + store %runtime.stackChainObject* %3, %runtime.stackChainObject** @runtime.stackChainStart, align 4 %arr = call [32 x i8]* @arrayAlloc() %arr.bitcast = getelementptr [32 x i8], [32 x i8]* %arr, i32 0, i32 0 %4 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 2 - store i8* %arr.bitcast, i8** %4 + store i8* %arr.bitcast, i8** %4, align 4 %other = call i8* @runtime.alloc(i32 1) %5 = getelementptr { %runtime.stackChainObject*, i32, i8*, i8* }, { %runtime.stackChainObject*, i32, i8*, i8* }* %gc.stackobject, i32 0, i32 3 - store i8* %other, i8** %5 - store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart + store i8* %other, i8** %5, align 4 + store %runtime.stackChainObject* %1, %runtime.stackChainObject** @runtime.stackChainStart, align 4 ret void } diff --git a/transform/testdata/maps.out.ll b/transform/testdata/maps.out.ll index 925a61b0..81f9bada 100644 --- a/transform/testdata/maps.out.ll +++ b/transform/testdata/maps.out.ll @@ -17,14 +17,14 @@ define void @testUnused() { define i32 @testReadonly() { %map = call %runtime.hashmap* @runtime.hashmapMake(i8 4, i8 4, i32 0) - %hashmap.value = alloca i32 - store i32 42, i32* %hashmap.value + %hashmap.value = alloca i32, align 4 + store i32 42, i32* %hashmap.value, align 4 %hashmap.value.bitcast = bitcast i32* %hashmap.value to i8* call void @runtime.hashmapStringSet(%runtime.hashmap* %map, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @answer, i32 0, i32 0), i32 6, i8* %hashmap.value.bitcast) - %hashmap.value2 = alloca i32 + %hashmap.value2 = alloca i32, align 4 %hashmap.value2.bitcast = bitcast i32* %hashmap.value2 to i8* %commaOk = call i1 @runtime.hashmapStringGet(%runtime.hashmap* %map, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @answer, i32 0, i32 0), i32 6, i8* %hashmap.value2.bitcast) - %loadedValue = load i32, i32* %hashmap.value2 + %loadedValue = load i32, i32* %hashmap.value2, align 4 ret i32 %loadedValue } diff --git a/transform/testdata/stacksize.out.ll b/transform/testdata/stacksize.out.ll index 08ad3022..29f51e34 100644 --- a/transform/testdata/stacksize.out.ll +++ b/transform/testdata/stacksize.out.ll @@ -11,7 +11,7 @@ declare void @"internal/task.start"(i32, i8*, i32) define void @Reset_Handler() { entry: - %stacksize1 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @"internal/task.stackSizes", i32 0, i32 0) + %stacksize1 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @"internal/task.stackSizes", i32 0, i32 0), align 4 call void @"internal/task.start"(i32 ptrtoint (void (i8*)* @"runtime.run$1$gowrapper" to i32), i8* undef, i32 %stacksize1) ret void } diff --git a/transform/testdata/wasm-abi.out.ll b/transform/testdata/wasm-abi.out.ll index 68bed05e..cf63c3d7 100644 --- a/transform/testdata/wasm-abi.out.ll +++ b/transform/testdata/wasm-abi.out.ll @@ -4,24 +4,24 @@ target triple = "wasm32-unknown-unknown-wasm" declare i64 @"externalCall$i64wrap"(i8*, i32, i64) define internal i64 @testCall(i8* %ptr, i32 %len, i64 %foo) { - %i64asptr = alloca i64 - %i64asptr1 = alloca i64 - store i64 %foo, i64* %i64asptr1 + %i64asptr = alloca i64, align 8 + %i64asptr1 = alloca i64, align 8 + store i64 %foo, i64* %i64asptr1, align 8 call void @externalCall(i64* %i64asptr, i8* %ptr, i32 %len, i64* %i64asptr1) - %retval = load i64, i64* %i64asptr + %retval = load i64, i64* %i64asptr, align 8 ret i64 %retval } define internal i64 @testCallNonEntry(i8* %ptr, i32 %len) { entry: - %i64asptr = alloca i64 - %i64asptr1 = alloca i64 + %i64asptr = alloca i64, align 8 + %i64asptr1 = alloca i64, align 8 br label %bb1 bb1: ; preds = %entry - store i64 3, i64* %i64asptr1 + store i64 3, i64* %i64asptr1, align 8 call void @externalCall(i64* %i64asptr, i8* %ptr, i32 %len, i64* %i64asptr1) - %retval = load i64, i64* %i64asptr + %retval = load i64, i64* %i64asptr, align 8 ret i64 %retval } @@ -39,7 +39,7 @@ declare void @externalCall(i64*, i8*, i32, i64*) define void @exportedFunction(i64* %0) { entry: - %i64 = load i64, i64* %0 + %i64 = load i64, i64* %0, align 8 call void @"exportedFunction$i64wrap"(i64 %i64) ret void } diff --git a/transform/transform_test.go b/transform/transform_test.go index f16baabd..9689a063 100644 --- a/transform/transform_test.go +++ b/transform/transform_test.go @@ -9,7 +9,6 @@ import ( "io/ioutil" "os" "path/filepath" - "regexp" "strconv" "strings" "testing" @@ -67,8 +66,6 @@ func testTransform(t *testing.T, pathPrefix string, transform func(mod llvm.Modu } } -var alignRegexp = regexp.MustCompile(", align [0-9]+$") - // fuzzyEqualIR returns true if the two LLVM IR strings passed in are roughly // equal. That means, only relevant lines are compared (excluding comments // etc.). @@ -80,15 +77,6 @@ func fuzzyEqualIR(s1, s2 string) bool { } for i, line1 := range lines1 { line2 := lines2[i] - match1 := alignRegexp.MatchString(line1) - match2 := alignRegexp.MatchString(line2) - if match1 != match2 { - // Only one of the lines has the align keyword. Remove it. - // This is a change to make the test work in both LLVM 10 and LLVM - // 11 (LLVM 11 appears to automatically add alignment everywhere). - line1 = alignRegexp.ReplaceAllString(line1, "") - line2 = alignRegexp.ReplaceAllString(line2, "") - } if line1 != line2 { return false } @@ -117,19 +105,10 @@ func filterIrrelevantIRLines(lines []string) []string { if strings.HasPrefix(line, "source_filename = ") { continue } - if llvmVersion < 10 && strings.HasPrefix(line, "attributes ") { + if llvmVersion < 11 && 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