diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index 2fd4a841..dd88c08e 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -555,64 +555,66 @@ _llgo_24: ; preds = %_llgo_22 br label %_llgo_12 _llgo_25: ; preds = %_llgo_27 - %43 = fptosi double %59 to i64 - %44 = add i64 %60, 2 + %43 = fptosi double %60 to i64 + %44 = add i64 %61, 2 %45 = add i64 %43, 48 %46 = trunc i64 %45 to i8 - %47 = getelementptr inbounds i8, ptr %11, i64 %44 - store i8 %46, ptr %47, align 1 - %48 = sitofp i64 %43 to double - %49 = fsub double %59, %48 - %50 = fmul double %49, 1.000000e+01 - %51 = add i64 %60, 1 + %47 = icmp slt i64 %44, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %47) + %48 = getelementptr inbounds i8, ptr %11, i64 %44 + store i8 %46, ptr %48, align 1 + %49 = sitofp i64 %43 to double + %50 = fsub double %60, %49 + %51 = fmul double %50, 1.000000e+01 + %52 = add i64 %61, 1 br label %_llgo_27 _llgo_26: ; preds = %_llgo_27 - %52 = getelementptr inbounds i8, ptr %11, i64 2 - %53 = load i8, ptr %52, align 1 - %54 = getelementptr inbounds i8, ptr %11, i64 1 - store i8 %53, ptr %54, align 1 - %55 = getelementptr inbounds i8, ptr %11, i64 2 - store i8 46, ptr %55, align 1 - %56 = getelementptr inbounds i8, ptr %11, i64 9 - store i8 101, ptr %56, align 1 - %57 = getelementptr inbounds i8, ptr %11, i64 10 - store i8 43, ptr %57, align 1 - %58 = icmp slt i64 %19, 0 - br i1 %58, label %_llgo_28, label %_llgo_29 + %53 = getelementptr inbounds i8, ptr %11, i64 2 + %54 = load i8, ptr %53, align 1 + %55 = getelementptr inbounds i8, ptr %11, i64 1 + store i8 %54, ptr %55, align 1 + %56 = getelementptr inbounds i8, ptr %11, i64 2 + store i8 46, ptr %56, align 1 + %57 = getelementptr inbounds i8, ptr %11, i64 9 + store i8 101, ptr %57, align 1 + %58 = getelementptr inbounds i8, ptr %11, i64 10 + store i8 43, ptr %58, align 1 + %59 = icmp slt i64 %19, 0 + br i1 %59, label %_llgo_28, label %_llgo_29 _llgo_27: ; preds = %_llgo_25, %_llgo_12 - %59 = phi double [ %18, %_llgo_12 ], [ %50, %_llgo_25 ] - %60 = phi i64 [ 0, %_llgo_12 ], [ %51, %_llgo_25 ] - %61 = icmp slt i64 %60, 7 - br i1 %61, label %_llgo_25, label %_llgo_26 + %60 = phi double [ %18, %_llgo_12 ], [ %51, %_llgo_25 ] + %61 = phi i64 [ 0, %_llgo_12 ], [ %52, %_llgo_25 ] + %62 = icmp slt i64 %61, 7 + br i1 %62, label %_llgo_25, label %_llgo_26 _llgo_28: ; preds = %_llgo_26 - %62 = sub i64 0, %19 - %63 = getelementptr inbounds i8, ptr %11, i64 10 - store i8 45, ptr %63, align 1 + %63 = sub i64 0, %19 + %64 = getelementptr inbounds i8, ptr %11, i64 10 + store i8 45, ptr %64, align 1 br label %_llgo_29 _llgo_29: ; preds = %_llgo_28, %_llgo_26 - %64 = phi i64 [ %19, %_llgo_26 ], [ %62, %_llgo_28 ] - %65 = sdiv i64 %64, 100 - %66 = trunc i64 %65 to i8 - %67 = add i8 %66, 48 - %68 = getelementptr inbounds i8, ptr %11, i64 11 - store i8 %67, ptr %68, align 1 - %69 = sdiv i64 %64, 10 - %70 = trunc i64 %69 to i8 - %71 = urem i8 %70, 10 - %72 = add i8 %71, 48 - %73 = getelementptr inbounds i8, ptr %11, i64 12 - store i8 %72, ptr %73, align 1 - %74 = srem i64 %64, 10 - %75 = trunc i64 %74 to i8 - %76 = add i8 %75, 48 - %77 = getelementptr inbounds i8, ptr %11, i64 13 - store i8 %76, ptr %77, align 1 - %78 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %11, i64 1, i64 14, i64 0, i64 14, i64 14) - call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %78) + %65 = phi i64 [ %19, %_llgo_26 ], [ %63, %_llgo_28 ] + %66 = sdiv i64 %65, 100 + %67 = trunc i64 %66 to i8 + %68 = add i8 %67, 48 + %69 = getelementptr inbounds i8, ptr %11, i64 11 + store i8 %68, ptr %69, align 1 + %70 = sdiv i64 %65, 10 + %71 = trunc i64 %70 to i8 + %72 = urem i8 %71, 10 + %73 = add i8 %72, 48 + %74 = getelementptr inbounds i8, ptr %11, i64 12 + store i8 %73, ptr %74, align 1 + %75 = srem i64 %65, 10 + %76 = trunc i64 %75 to i8 + %77 = add i8 %76, 48 + %78 = getelementptr inbounds i8, ptr %11, i64 13 + store i8 %77, ptr %78, align 1 + %79 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %11, i64 1, i64 14, i64 0, i64 14, i64 14) + call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %79) ret void } @@ -622,43 +624,49 @@ _llgo_0: br label %_llgo_3 _llgo_1: ; preds = %_llgo_3 - %2 = urem i64 %14, 16 + %2 = urem i64 %17, 16 %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @10, i64 16) %4 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %3, 0 %5 = getelementptr inbounds i8, ptr %4, i64 %2 %6 = load i8, ptr %5, align 1 - %7 = getelementptr inbounds i8, ptr %1, i64 %15 - store i8 %6, ptr %7, align 1 - %8 = icmp ult i64 %14, 16 - br i1 %8, label %_llgo_5, label %_llgo_4 + %7 = icmp slt i64 %18, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %7) + %8 = getelementptr inbounds i8, ptr %1, i64 %18 + store i8 %6, ptr %8, align 1 + %9 = icmp ult i64 %17, 16 + br i1 %9, label %_llgo_5, label %_llgo_4 _llgo_2: ; preds = %_llgo_5, %_llgo_3 - %9 = sub i64 %15, 1 - %10 = getelementptr inbounds i8, ptr %1, i64 %9 - store i8 120, ptr %10, align 1 - %11 = sub i64 %9, 1 - %12 = getelementptr inbounds i8, ptr %1, i64 %11 - store i8 48, ptr %12, align 1 - %13 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %11, i64 100, i64 100) - call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %13) + %10 = sub i64 %18, 1 + %11 = icmp slt i64 %10, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %11) + %12 = getelementptr inbounds i8, ptr %1, i64 %10 + store i8 120, ptr %12, align 1 + %13 = sub i64 %10, 1 + %14 = icmp slt i64 %13, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14) + %15 = getelementptr inbounds i8, ptr %1, i64 %13 + store i8 48, ptr %15, align 1 + %16 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %13, i64 100, i64 100) + call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %16) ret void _llgo_3: ; preds = %_llgo_4, %_llgo_0 - %14 = phi i64 [ %0, %_llgo_0 ], [ %17, %_llgo_4 ] - %15 = phi i64 [ 99, %_llgo_0 ], [ %18, %_llgo_4 ] - %16 = icmp sgt i64 %15, 0 - br i1 %16, label %_llgo_1, label %_llgo_2 + %17 = phi i64 [ %0, %_llgo_0 ], [ %20, %_llgo_4 ] + %18 = phi i64 [ 99, %_llgo_0 ], [ %21, %_llgo_4 ] + %19 = icmp sgt i64 %18, 0 + br i1 %19, label %_llgo_1, label %_llgo_2 _llgo_4: ; preds = %_llgo_5, %_llgo_1 - %17 = udiv i64 %14, 16 - %18 = sub i64 %15, 1 + %20 = udiv i64 %17, 16 + %21 = sub i64 %18, 1 br label %_llgo_3 _llgo_5: ; preds = %_llgo_1 - %19 = sub i64 100, %15 - %20 = load i64, ptr @main.minhexdigits, align 4 - %21 = icmp sge i64 %19, %20 - br i1 %21, label %_llgo_2, label %_llgo_4 + %22 = sub i64 100, %18 + %23 = load i64, ptr @main.minhexdigits, align 4 + %24 = icmp sge i64 %22, %23 + br i1 %24, label %_llgo_2, label %_llgo_4 } define void @main.printint(i64 %0) { @@ -690,23 +698,25 @@ _llgo_1: ; preds = %_llgo_5, %_llgo_0 br i1 %4, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 - %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3 - %7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8 - %8 = icmp ne i64 %3, 0 - br i1 %8, label %_llgo_4, label %_llgo_5 + %5 = icmp slt i64 %3, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %5) + %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i64 %3 + %8 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, align 8 + %9 = icmp ne i64 %3, 0 + br i1 %9, label %_llgo_4, label %_llgo_5 _llgo_3: ; preds = %_llgo_1 call void @main.printnl() ret void _llgo_4: ; preds = %_llgo_2 - %9 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 1) - call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %9) + %10 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 1) + call void @main.printstring(%"github.com/goplus/llgo/internal/runtime.String" %10) br label %_llgo_5 _llgo_5: ; preds = %_llgo_4, %_llgo_2 - call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %7) + call void @main.printany(%"github.com/goplus/llgo/internal/runtime.iface" %8) br label %_llgo_1 } @@ -737,28 +747,30 @@ _llgo_0: br label %_llgo_3 _llgo_1: ; preds = %_llgo_3 - %2 = urem i64 %8, 10 + %2 = urem i64 %9, 10 %3 = add i64 %2, 48 %4 = trunc i64 %3 to i8 - %5 = getelementptr inbounds i8, ptr %1, i64 %9 - store i8 %4, ptr %5, align 1 - %6 = icmp ult i64 %8, 10 - br i1 %6, label %_llgo_2, label %_llgo_4 + %5 = icmp slt i64 %10, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %5) + %6 = getelementptr inbounds i8, ptr %1, i64 %10 + store i8 %4, ptr %6, align 1 + %7 = icmp ult i64 %9, 10 + br i1 %7, label %_llgo_2, label %_llgo_4 _llgo_2: ; preds = %_llgo_3, %_llgo_1 - %7 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %9, i64 100, i64 100) - call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %7) + %8 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr %1, i64 1, i64 100, i64 %10, i64 100, i64 100) + call void @main.gwrite(%"github.com/goplus/llgo/internal/runtime.Slice" %8) ret void _llgo_3: ; preds = %_llgo_4, %_llgo_0 - %8 = phi i64 [ %0, %_llgo_0 ], [ %11, %_llgo_4 ] - %9 = phi i64 [ 99, %_llgo_0 ], [ %12, %_llgo_4 ] - %10 = icmp sgt i64 %9, 0 - br i1 %10, label %_llgo_1, label %_llgo_2 + %9 = phi i64 [ %0, %_llgo_0 ], [ %12, %_llgo_4 ] + %10 = phi i64 [ 99, %_llgo_0 ], [ %13, %_llgo_4 ] + %11 = icmp sgt i64 %10, 0 + br i1 %11, label %_llgo_1, label %_llgo_2 _llgo_4: ; preds = %_llgo_1 - %11 = udiv i64 %8, 10 - %12 = sub i64 %9, 1 + %12 = udiv i64 %9, 10 + %13 = sub i64 %10, 1 br label %_llgo_3 } @@ -800,3 +812,5 @@ declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llg declare { i64, i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) declare { %"github.com/goplus/llgo/internal/runtime.String", i1 } @"github.com/goplus/llgo/internal/runtime.CheckI2String"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) diff --git a/cl/_testdata/utf8/in.go b/cl/_testdata/utf8/in.go new file mode 100644 index 00000000..3edfa053 --- /dev/null +++ b/cl/_testdata/utf8/in.go @@ -0,0 +1,23 @@ +package main + +import ( + "unicode/utf8" +) + +func main() { + var str = "中abcd" + for i := 0; i < len(str); { + r, n := utf8.DecodeRuneInString(str[i:]) + i += n + println(r) + } + println(index(2) == 3) +} + +var array = [...]uint8{ + 1, 2, 3, 4, 5, 6, 7, 8, +} + +func index(n int8) uint8 { + return array[n] +} diff --git a/cl/_testdata/utf8/out.ll b/cl/_testdata/utf8/out.ll new file mode 100644 index 00000000..c9aebbfd --- /dev/null +++ b/cl/_testdata/utf8/out.ll @@ -0,0 +1,101 @@ +; ModuleID = 'main' +source_filename = "main" + +%"github.com/goplus/llgo/internal/runtime.String" = type { ptr, i64 } + +@main.array = global [8 x i8] undef +@"main.init$guard" = global ptr null +@__llgo_argc = global ptr null +@__llgo_argv = global ptr null +@0 = private unnamed_addr constant [8 x i8] c"\E4\B8\ADabcd\00", align 1 +@1 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 +@2 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 +@3 = private unnamed_addr constant [8 x i8] c"\E4\B8\ADabcd\00", align 1 + +define i8 @main.index(i8 %0) { +_llgo_0: + %1 = icmp slt i8 %0, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %1) + %2 = zext i8 %0 to i64 + %3 = getelementptr inbounds i8, ptr @main.array, i64 %2 + %4 = load i8, ptr %3, align 1 + ret i8 %4 +} + +define void @main.init() { +_llgo_0: + %0 = load i1, ptr @"main.init$guard", align 1 + br i1 %0, label %_llgo_2, label %_llgo_1 + +_llgo_1: ; preds = %_llgo_0 + store i1 true, ptr @"main.init$guard", align 1 + call void @"unicode/utf8.init"() + store i8 1, ptr @main.array, align 1 + store i8 2, ptr getelementptr inbounds (i8, ptr @main.array, i64 1), align 1 + store i8 3, ptr getelementptr inbounds (i8, ptr @main.array, i64 2), align 1 + store i8 4, ptr getelementptr inbounds (i8, ptr @main.array, i64 3), align 1 + store i8 5, ptr getelementptr inbounds (i8, ptr @main.array, i64 4), align 1 + store i8 6, ptr getelementptr inbounds (i8, ptr @main.array, i64 5), align 1 + store i8 7, ptr getelementptr inbounds (i8, ptr @main.array, i64 6), align 1 + store i8 8, ptr getelementptr inbounds (i8, ptr @main.array, i64 7), align 1 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_1, %_llgo_0 + ret void +} + +define i32 @main(i32 %0, ptr %1) { +_llgo_0: + store i32 %0, ptr @__llgo_argc, align 4 + store ptr %1, ptr @__llgo_argv, align 8 + call void @"github.com/goplus/llgo/internal/runtime.init"() + call void @main.init() + br label %_llgo_3 + +_llgo_1: ; preds = %_llgo_3 + %2 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @0, i64 7) + %3 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %2, 1 + %4 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String" %2, i64 %14, i64 %3) + %5 = call { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String" %4) + %6 = extractvalue { i32, i64 } %5, 0 + %7 = extractvalue { i32, i64 } %5, 1 + %8 = add i64 %14, %7 + %9 = sext i32 %6 to i64 + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %9) + %10 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @1, i64 1) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %10) + br label %_llgo_3 + +_llgo_2: ; preds = %_llgo_3 + %11 = call i8 @main.index(i8 2) + %12 = icmp eq i8 %11, 3 + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %12) + %13 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @2, i64 1) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %13) + ret i32 0 + +_llgo_3: ; preds = %_llgo_1, %_llgo_0 + %14 = phi i64 [ 0, %_llgo_0 ], [ %8, %_llgo_1 ] + %15 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @3, i64 7) + %16 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %15, 1 + %17 = icmp slt i64 %14, %16 + br i1 %17, label %_llgo_1, label %_llgo_2 +} + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + +declare void @"unicode/utf8.init"() + +declare void @"github.com/goplus/llgo/internal/runtime.init"() + +declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) + +declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewStringSlice"(%"github.com/goplus/llgo/internal/runtime.String", i64, i64) + +declare { i32, i64 } @"unicode/utf8.DecodeRuneInString"(%"github.com/goplus/llgo/internal/runtime.String") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64) + +declare void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String") + +declare void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1) diff --git a/cl/_testdata/vargs/out.ll b/cl/_testdata/vargs/out.ll index 7c75776b..def89a93 100644 --- a/cl/_testdata/vargs/out.ll +++ b/cl/_testdata/vargs/out.ll @@ -58,12 +58,14 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %4, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %5 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 - %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %5, i64 %3 - %7 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, align 8 - %8 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) - %9 = call i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %7, ptr %8) - %10 = call i32 (ptr, ...) @printf(ptr @0, i64 %9) + %5 = icmp slt i64 %3, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %5) + %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %7 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.iface", ptr %6, i64 %3 + %8 = load %"github.com/goplus/llgo/internal/runtime.iface", ptr %7, align 8 + %9 = call ptr @"github.com/goplus/llgo/internal/runtime.Basic"(i64 2) + %10 = call i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface" %8, ptr %9) + %11 = call i32 (ptr, ...) @printf(ptr @0, i64 %10) br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -80,6 +82,8 @@ declare %"github.com/goplus/llgo/internal/runtime.iface" @"github.com/goplus/llg declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + declare i64 @"github.com/goplus/llgo/internal/runtime.I2Int"(%"github.com/goplus/llgo/internal/runtime.iface", ptr) declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/concat/out.ll b/cl/_testrt/concat/out.ll index 00c7d18a..19f0abd8 100644 --- a/cl/_testrt/concat/out.ll +++ b/cl/_testrt/concat/out.ll @@ -25,8 +25,8 @@ _llgo_0: br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 - %5 = phi ptr [ %3, %_llgo_0 ], [ %18, %_llgo_2 ] - %6 = phi i64 [ %4, %_llgo_0 ], [ %19, %_llgo_2 ] + %5 = phi ptr [ %3, %_llgo_0 ], [ %19, %_llgo_2 ] + %6 = phi i64 [ %4, %_llgo_0 ], [ %20, %_llgo_2 ] %7 = phi i64 [ -1, %_llgo_0 ], [ %12, %_llgo_2 ] %8 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %9 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %8, i32 0, i32 0 @@ -39,12 +39,14 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %13, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %14 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 - %15 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %14, i64 %12 - %16 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %15, align 8 - %17 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %16) - %18 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 0 - %19 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %17, 1 + %14 = icmp slt i64 %12, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %14) + %15 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %16 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %15, i64 %12 + %17 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %16, align 8 + %18 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String" %11, %"github.com/goplus/llgo/internal/runtime.String" %17) + %19 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %18, 0 + %20 = extractvalue %"github.com/goplus/llgo/internal/runtime.String" %18, 1 br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -100,6 +102,8 @@ _llgo_0: ret i32 0 } +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringCat"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String") declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr, i64) diff --git a/cl/_testrt/intgen/out.ll b/cl/_testrt/intgen/out.ll index a344eb5f..1fe32d61 100644 --- a/cl/_testrt/intgen/out.ll +++ b/cl/_testrt/intgen/out.ll @@ -29,9 +29,11 @@ _llgo_2: ; preds = %_llgo_1 %9 = extractvalue { ptr, ptr } %1, 1 %10 = extractvalue { ptr, ptr } %1, 0 %11 = call i32 %10(ptr %9) - %12 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 0 - %13 = getelementptr inbounds i32, ptr %12, i64 %7 - store i32 %11, ptr %13, align 4 + %12 = icmp slt i64 %7, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %12) + %13 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %4, 0 + %14 = getelementptr inbounds i32, ptr %13, i64 %7 + store i32 %11, ptr %14, align 4 br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -86,69 +88,75 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %10, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %11 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 0 - %12 = getelementptr inbounds i32, ptr %11, i64 %9 - %13 = load i32, ptr %12, align 4 - %14 = call i32 (ptr, ...) @printf(ptr @0, i32 %13) + %11 = icmp slt i64 %9, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %11) + %12 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %6, 0 + %13 = getelementptr inbounds i32, ptr %12, i64 %9 + %14 = load i32, ptr %13, align 4 + %15 = call i32 (ptr, ...) @printf(ptr @0, i32 %14) br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 - %15 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4) - store i32 1, ptr %15, align 4 - %16 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) - %17 = getelementptr inbounds { ptr }, ptr %16, i32 0, i32 0 - store ptr %15, ptr %17, align 8 - %18 = alloca { ptr, ptr }, align 8 - %19 = getelementptr inbounds { ptr, ptr }, ptr %18, i32 0, i32 0 - store ptr @"main.main$1", ptr %19, align 8 - %20 = getelementptr inbounds { ptr, ptr }, ptr %18, i32 0, i32 1 - store ptr %16, ptr %20, align 8 - %21 = load { ptr, ptr }, ptr %18, align 8 - %22 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %21) - %23 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 1 + %16 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4) + store i32 1, ptr %16, align 4 + %17 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %18 = getelementptr inbounds { ptr }, ptr %17, i32 0, i32 0 + store ptr %16, ptr %18, align 8 + %19 = alloca { ptr, ptr }, align 8 + %20 = getelementptr inbounds { ptr, ptr }, ptr %19, i32 0, i32 0 + store ptr @"main.main$1", ptr %20, align 8 + %21 = getelementptr inbounds { ptr, ptr }, ptr %19, i32 0, i32 1 + store ptr %17, ptr %21, align 8 + %22 = load { ptr, ptr }, ptr %19, align 8 + %23 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %22) + %24 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %23, 1 br label %_llgo_4 _llgo_4: ; preds = %_llgo_5, %_llgo_3 - %24 = phi i64 [ -1, %_llgo_3 ], [ %25, %_llgo_5 ] - %25 = add i64 %24, 1 - %26 = icmp slt i64 %25, %23 - br i1 %26, label %_llgo_5, label %_llgo_6 + %25 = phi i64 [ -1, %_llgo_3 ], [ %26, %_llgo_5 ] + %26 = add i64 %25, 1 + %27 = icmp slt i64 %26, %24 + br i1 %27, label %_llgo_5, label %_llgo_6 _llgo_5: ; preds = %_llgo_4 - %27 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %22, 0 - %28 = getelementptr inbounds i32, ptr %27, i64 %25 - %29 = load i32, ptr %28, align 4 - %30 = call i32 (ptr, ...) @printf(ptr @1, i32 %29) + %28 = icmp slt i64 %26, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %28) + %29 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %23, 0 + %30 = getelementptr inbounds i32, ptr %29, i64 %26 + %31 = load i32, ptr %30, align 4 + %32 = call i32 (ptr, ...) @printf(ptr @1, i32 %31) br label %_llgo_4 _llgo_6: ; preds = %_llgo_4 - %31 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4) - %32 = getelementptr inbounds %main.generator, ptr %31, i32 0, i32 0 - store i32 1, ptr %32, align 4 - %33 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) - %34 = getelementptr inbounds { ptr }, ptr %33, i32 0, i32 0 - store ptr %31, ptr %34, align 8 - %35 = alloca { ptr, ptr }, align 8 - %36 = getelementptr inbounds { ptr, ptr }, ptr %35, i32 0, i32 0 - store ptr @"main.next$bound", ptr %36, align 8 - %37 = getelementptr inbounds { ptr, ptr }, ptr %35, i32 0, i32 1 - store ptr %33, ptr %37, align 8 - %38 = load { ptr, ptr }, ptr %35, align 8 - %39 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %38) - %40 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 1 + %33 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 4) + %34 = getelementptr inbounds %main.generator, ptr %33, i32 0, i32 0 + store i32 1, ptr %34, align 4 + %35 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocU"(i64 8) + %36 = getelementptr inbounds { ptr }, ptr %35, i32 0, i32 0 + store ptr %33, ptr %36, align 8 + %37 = alloca { ptr, ptr }, align 8 + %38 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 0 + store ptr @"main.next$bound", ptr %38, align 8 + %39 = getelementptr inbounds { ptr, ptr }, ptr %37, i32 0, i32 1 + store ptr %35, ptr %39, align 8 + %40 = load { ptr, ptr }, ptr %37, align 8 + %41 = call %"github.com/goplus/llgo/internal/runtime.Slice" @main.genInts(i64 5, { ptr, ptr } %40) + %42 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %41, 1 br label %_llgo_7 _llgo_7: ; preds = %_llgo_8, %_llgo_6 - %41 = phi i64 [ -1, %_llgo_6 ], [ %42, %_llgo_8 ] - %42 = add i64 %41, 1 - %43 = icmp slt i64 %42, %40 - br i1 %43, label %_llgo_8, label %_llgo_9 + %43 = phi i64 [ -1, %_llgo_6 ], [ %44, %_llgo_8 ] + %44 = add i64 %43, 1 + %45 = icmp slt i64 %44, %42 + br i1 %45, label %_llgo_8, label %_llgo_9 _llgo_8: ; preds = %_llgo_7 - %44 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %39, 0 - %45 = getelementptr inbounds i32, ptr %44, i64 %42 - %46 = load i32, ptr %45, align 4 - %47 = call i32 (ptr, ...) @printf(ptr @2, i32 %46) + %46 = icmp slt i64 %44, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %46) + %47 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %41, 0 + %48 = getelementptr inbounds i32, ptr %47, i64 %44 + %49 = load i32, ptr %48, align 4 + %50 = call i32 (ptr, ...) @printf(ptr @2, i32 %49) br label %_llgo_7 _llgo_9: ; preds = %_llgo_7 @@ -159,6 +167,8 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice"(ptr, i64, i64) +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + declare void @"github.com/goplus/llgo/internal/runtime.init"() declare i32 @rand() diff --git a/cl/_testrt/mask/out.ll b/cl/_testrt/mask/out.ll index 6ebc1e08..68d454fe 100644 --- a/cl/_testrt/mask/out.ll +++ b/cl/_testrt/mask/out.ll @@ -16,12 +16,6 @@ source_filename = "main" @7 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 @8 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 @9 = private unnamed_addr constant [2 x i8] c"\0A\00", align 1 -@10 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 -@11 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 -@12 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 -@13 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 -@14 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 -@15 = private unnamed_addr constant [22 x i8] c"negative shift amount\00", align 1 define void @main.init() { _llgo_0: @@ -105,71 +99,65 @@ _llgo_0: define i64 @main.mask_shl(i64 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @10, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = icmp uge i64 %1, 64 - %5 = shl i64 %0, %1 - %6 = select i1 %4, i64 0, i64 %5 - ret i64 %6 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = icmp uge i64 %1, 64 + %4 = shl i64 %0, %1 + %5 = select i1 %3, i64 0, i64 %4 + ret i64 %5 } define i8 @main.mask_shl8(i8 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @11, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = trunc i64 %1 to i8 - %5 = icmp uge i8 %4, 8 - %6 = shl i8 %0, %4 - %7 = select i1 %5, i8 0, i8 %6 - ret i8 %7 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = trunc i64 %1 to i8 + %4 = icmp uge i8 %3, 8 + %5 = shl i8 %0, %3 + %6 = select i1 %4, i8 0, i8 %5 + ret i8 %6 } define i8 @main.mask_shl8u(i8 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @12, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = trunc i64 %1 to i8 - %5 = icmp uge i8 %4, 8 - %6 = shl i8 %0, %4 - %7 = select i1 %5, i8 0, i8 %6 - ret i8 %7 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = trunc i64 %1 to i8 + %4 = icmp uge i8 %3, 8 + %5 = shl i8 %0, %3 + %6 = select i1 %4, i8 0, i8 %5 + ret i8 %6 } define i64 @main.mask_shr(i64 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @13, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = icmp uge i64 %1, 64 - %5 = select i1 %4, i64 63, i64 %1 - %6 = ashr i64 %0, %5 - ret i64 %6 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = icmp uge i64 %1, 64 + %4 = select i1 %3, i64 63, i64 %1 + %5 = ashr i64 %0, %4 + ret i64 %5 } define i8 @main.mask_shr8(i8 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @14, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = trunc i64 %1 to i8 - %5 = icmp uge i8 %4, 8 - %6 = select i1 %5, i8 7, i8 %4 - %7 = ashr i8 %0, %6 - ret i8 %7 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = trunc i64 %1 to i8 + %4 = icmp uge i8 %3, 8 + %5 = select i1 %4, i8 7, i8 %3 + %6 = ashr i8 %0, %5 + ret i8 %6 } define i8 @main.mask_shr8u(i8 %0, i64 %1) { _llgo_0: %2 = icmp slt i64 %1, 0 - %3 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.NewString"(ptr @15, i64 21) - call void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1 %2, %"github.com/goplus/llgo/internal/runtime.String" %3) - %4 = trunc i64 %1 to i8 - %5 = icmp uge i8 %4, 8 - %6 = lshr i8 %0, %4 - %7 = select i1 %5, i8 0, i8 %6 - ret i8 %7 + call void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1 %2) + %3 = trunc i64 %1 to i8 + %4 = icmp uge i8 %3, 8 + %5 = lshr i8 %0, %3 + %6 = select i1 %4, i8 0, i8 %5 + ret i8 %6 } declare void @"github.com/goplus/llgo/internal/runtime.init"() @@ -182,4 +170,4 @@ declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/ll declare void @"github.com/goplus/llgo/internal/runtime.PrintUint"(i64) -declare void @"github.com/goplus/llgo/internal/runtime.CheckRuntimeError"(i1, %"github.com/goplus/llgo/internal/runtime.String") +declare void @"github.com/goplus/llgo/internal/runtime.AssertNegativeShift"(i1) diff --git a/cl/_testrt/qsort/out.ll b/cl/_testrt/qsort/out.ll index 2d203ee1..916dd34a 100644 --- a/cl/_testrt/qsort/out.ll +++ b/cl/_testrt/qsort/out.ll @@ -48,9 +48,11 @@ _llgo_1: ; preds = %_llgo_2, %_llgo_0 br i1 %12, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %13 = getelementptr inbounds i64, ptr %2, i64 %11 - %14 = load i64, ptr %13, align 4 - %15 = call i32 (ptr, ...) @printf(ptr @0, i64 %14) + %13 = icmp slt i64 %11, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %13) + %14 = getelementptr inbounds i64, ptr %2, i64 %11 + %15 = load i64, ptr %14, align 4 + %16 = call i32 (ptr, ...) @printf(ptr @0, i64 %15) br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -72,4 +74,6 @@ _llgo_0: ret i32 %5 } +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) + declare i32 @printf(ptr, ...) diff --git a/cl/_testrt/sum/out.ll b/cl/_testrt/sum/out.ll index 70c4be76..e13b24a2 100644 --- a/cl/_testrt/sum/out.ll +++ b/cl/_testrt/sum/out.ll @@ -48,17 +48,19 @@ _llgo_0: br label %_llgo_1 _llgo_1: ; preds = %_llgo_2, %_llgo_0 - %2 = phi i64 [ 0, %_llgo_0 ], [ %9, %_llgo_2 ] + %2 = phi i64 [ 0, %_llgo_0 ], [ %10, %_llgo_2 ] %3 = phi i64 [ -1, %_llgo_0 ], [ %4, %_llgo_2 ] %4 = add i64 %3, 1 %5 = icmp slt i64 %4, %1 br i1 %5, label %_llgo_2, label %_llgo_3 _llgo_2: ; preds = %_llgo_1 - %6 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 - %7 = getelementptr inbounds i64, ptr %6, i64 %4 - %8 = load i64, ptr %7, align 4 - %9 = add i64 %2, %8 + %6 = icmp slt i64 %4, 0 + call void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1 %6) + %7 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %0, 0 + %8 = getelementptr inbounds i64, ptr %7, i64 %4 + %9 = load i64, ptr %8, align 4 + %10 = add i64 %2, %9 br label %_llgo_1 _llgo_3: ; preds = %_llgo_1 @@ -72,3 +74,5 @@ declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.NewSlice3"(ptr, i64, i64, i64, i64, i64) declare i32 @printf(ptr, ...) + +declare void @"github.com/goplus/llgo/internal/runtime.AssertIndexRange"(i1) diff --git a/internal/abi/llgo_autogen.lla b/internal/abi/llgo_autogen.lla index be9b522a..cccf2f81 100644 Binary files a/internal/abi/llgo_autogen.lla and b/internal/abi/llgo_autogen.lla differ diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index 4f9b4461..fe0aad96 100644 Binary files a/internal/runtime/llgo_autogen.lla and b/internal/runtime/llgo_autogen.lla differ diff --git a/ssa/expr.go b/ssa/expr.go index 49e353d2..8132b989 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -324,9 +324,9 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr { case token.AND_NOT: return Expr{b.impl.CreateAnd(x.impl, b.impl.CreateNot(y.impl, ""), ""), x.Type} case token.SHL, token.SHR: - if y.kind == vkSigned { + if needsNegativeCheck(y) { check := Expr{b.impl.CreateICmp(llvm.IntSLT, y.impl, llvm.ConstInt(y.ll, 0, false), ""), b.Prog.Bool()} - b.InlineCall(b.Func.Pkg.rtFunc("CheckRuntimeError"), check, b.Str("negative shift amount")) + b.InlineCall(b.Func.Pkg.rtFunc("AssertNegativeShift"), check) } xsize, ysize := b.Prog.SizeOf(x.Type), b.Prog.SizeOf(y.Type) if xsize != ysize { @@ -723,6 +723,7 @@ func (b Builder) IndexAddr(x, idx Expr) Expr { if debugInstr { log.Printf("IndexAddr %v, %v\n", x.impl, idx.impl) } + idx = b.checkIndex(idx) prog := b.Prog telem := prog.Index(x.Type) pt := prog.Pointer(telem) @@ -737,6 +738,30 @@ func (b Builder) IndexAddr(x, idx Expr) Expr { return Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, x.impl, indices), pt} } +func needsNegativeCheck(x Expr) bool { + if x.kind == vkSigned { + if rv := x.impl.IsAConstantInt(); !rv.IsNil() && rv.SExtValue() >= 0 { + return false + } + return true + } + return false +} + +// check index >= 0 and size to uint +func (b Builder) checkIndex(idx Expr) Expr { + if needsNegativeCheck(idx) { + check := Expr{b.impl.CreateICmp(llvm.IntSLT, idx.impl, llvm.ConstInt(idx.ll, 0, false), ""), b.Prog.Bool()} + b.InlineCall(b.Func.Pkg.rtFunc("AssertIndexRange"), check) + } + typ := b.Prog.Uint() + if b.Prog.SizeOf(idx.Type) < b.Prog.SizeOf(typ) { + idx.Type = typ + idx.impl = castUintptr(b, idx.impl, typ) + } + return idx +} + // The Index instruction yields element Index of collection X, an array, // string or type parameter containing an array, a string, a pointer to an, // array or a slice. @@ -768,6 +793,7 @@ func (b Builder) Index(x, idx Expr, addr func(Expr) Expr) Expr { b.Store(ptr, x) } } + idx = b.checkIndex(idx) pt := prog.Pointer(telem) indices := []llvm.Value{idx.impl} buf := Expr{llvm.CreateInBoundsGEP(b.impl, telem.ll, ptr.impl, indices), pt}