From 62915d5af58bff026fb85867d1292ff565dc7fcc Mon Sep 17 00:00:00 2001 From: visualfc Date: Tue, 21 May 2024 22:22:39 +0800 Subject: [PATCH] ssa: string range; string convert bytes/rune; op eql/less --- cl/_testdata/print/out.ll | 2 +- cl/_testrt/builtin/in.go | 46 ++++++ cl/_testrt/builtin/out.ll | 266 +++++++++++++++++++++++++++++- cl/_testrt/cast/out.ll | 8 +- cl/compile.go | 6 + internal/runtime/llgo_autogen.lla | Bin 5677 -> 10013 bytes internal/runtime/utf8.go | 132 +++++++++++++++ internal/runtime/z_string.go | 115 +++++++++++++ ssa/expr.go | 102 +++++++++++- 9 files changed, 666 insertions(+), 11 deletions(-) create mode 100644 internal/runtime/utf8.go diff --git a/cl/_testdata/print/out.ll b/cl/_testdata/print/out.ll index 27462d72..800dd205 100644 --- a/cl/_testdata/print/out.ll +++ b/cl/_testdata/print/out.ll @@ -847,7 +847,7 @@ _llgo_3: ; preds = %_llgo_0 define void @main.printfloat(double %0) { _llgo_0: - %1 = fcmp one double %0, %0 + %1 = fcmp une double %0, %0 br i1 %1, label %_llgo_1, label %_llgo_3 _llgo_1: ; preds = %_llgo_0 diff --git a/cl/_testrt/builtin/in.go b/cl/_testrt/builtin/in.go index e16f2465..86780665 100644 --- a/cl/_testrt/builtin/in.go +++ b/cl/_testrt/builtin/in.go @@ -40,7 +40,53 @@ func main() { println(n) } println(demo, fn1, fn2, fn3) + + for i, v := range "中abcd" { + println(i, v) + } + + println(Inf(1), Inf(-1), NaN(), IsNaN(NaN()), IsNaN(1.0)) + + data1 := []byte("中abcd") + data2 := []rune("中abcd") + println(data1, data2) + println(string(data1), string(data2), string(data1[3]), string(data2[0])) + s1 := "abc" + s2 := "abd" + println(s1 == "abc", s1 == s2, s1 != s2, s1 < s2, s1 <= s2, s1 > s2, s1 >= s2) } func demo() { } + +const ( + uvnan = 0x7FF8000000000001 + uvinf = 0x7FF0000000000000 + uvneginf = 0xFFF0000000000000 + uvone = 0x3FF0000000000000 + mask = 0x7FF + shift = 64 - 11 - 1 + bias = 1023 + signMask = 1 << 63 + fracMask = 1<= 0, negative infinity if sign < 0. +func Inf(sign int) float64 { + var v uint64 + if sign >= 0 { + v = uvinf + } else { + v = uvneginf + } + return Float64frombits(v) +} + +// NaN returns an IEEE 754 “not-a-number” value. +func NaN() float64 { return Float64frombits(uvnan) } + +func IsNaN(f float64) (is bool) { + return f != f +} + +func Float64frombits(b uint64) float64 { return *(*float64)(unsafe.Pointer(&b)) } diff --git a/cl/_testrt/builtin/out.ll b/cl/_testrt/builtin/out.ll index d6c806f3..dfc39090 100644 --- a/cl/_testrt/builtin/out.ll +++ b/cl/_testrt/builtin/out.ll @@ -17,7 +17,61 @@ source_filename = "main" @3 = private unnamed_addr constant [6 x i8] c"hello\00", align 1 @4 = private unnamed_addr constant [4 x i8] c"def\00", align 1 @5 = private unnamed_addr constant [5 x i8] c"ABCD\00", align 1 -@6 = private unnamed_addr constant [3 x i8] c"fn\00", align 1 +@6 = private unnamed_addr constant [8 x i8] c"\E4\B8\ADabcd\00", align 1 +@7 = private unnamed_addr constant [8 x i8] c"\E4\B8\ADabcd\00", align 1 +@8 = private unnamed_addr constant [8 x i8] c"\E4\B8\ADabcd\00", align 1 +@9 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@10 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@11 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@12 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@13 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@14 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@15 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@16 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@17 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@18 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@19 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@20 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@21 = private unnamed_addr constant [4 x i8] c"abc\00", align 1 +@22 = private unnamed_addr constant [4 x i8] c"abd\00", align 1 +@23 = private unnamed_addr constant [3 x i8] c"fn\00", align 1 + +define double @main.Float64frombits(i64 %0) { +_llgo_0: + %1 = call ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64 8) + store i64 %0, ptr %1, align 4 + %2 = load double, ptr %1, align 8 + ret double %2 +} + +define double @main.Inf(i64 %0) { +_llgo_0: + %1 = icmp sge i64 %0, 0 + br i1 %1, label %_llgo_1, label %_llgo_3 + +_llgo_1: ; preds = %_llgo_0 + br label %_llgo_2 + +_llgo_2: ; preds = %_llgo_3, %_llgo_1 + %2 = phi i64 [ 9218868437227405312, %_llgo_1 ], [ -4503599627370496, %_llgo_3 ] + %3 = call double @main.Float64frombits(i64 %2) + ret double %3 + +_llgo_3: ; preds = %_llgo_0 + br label %_llgo_2 +} + +define i1 @main.IsNaN(double %0) { +_llgo_0: + %1 = fcmp une double %0, %0 + ret i1 %1 +} + +define double @main.NaN() { +_llgo_0: + %0 = call double @main.Float64frombits(i64 9221120237041090561) + ret double %0 +} define void @main.demo() { _llgo_0: @@ -380,13 +434,199 @@ _llgo_0: %175 = extractvalue { ptr, ptr } %174, 0 call void @"github.com/goplus/llgo/internal/runtime.PrintPointer"(ptr %175) call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %176 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %177 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %176, i32 0, i32 0 + store ptr @6, ptr %177, align 8 + %178 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %176, i32 0, i32 1 + store i64 7, ptr %178, align 4 + %179 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %176, align 8 + %180 = call ptr @"github.com/goplus/llgo/internal/runtime.NewStringIter"(%"github.com/goplus/llgo/internal/runtime.String" %179) + br label %_llgo_1 + +_llgo_1: ; preds = %_llgo_2, %_llgo_0 + %181 = call { i1, i64, i32 } @"github.com/goplus/llgo/internal/runtime.StringIterNext"(ptr %180) + %182 = extractvalue { i1, i64, i32 } %181, 0 + br i1 %182, label %_llgo_2, label %_llgo_3 + +_llgo_2: ; preds = %_llgo_1 + %183 = extractvalue { i1, i64, i32 } %181, 1 + %184 = extractvalue { i1, i64, i32 } %181, 2 + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %183) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + %185 = sext i32 %184 to i64 + call void @"github.com/goplus/llgo/internal/runtime.PrintInt"(i64 %185) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + br label %_llgo_1 + +_llgo_3: ; preds = %_llgo_1 + %186 = call double @main.Inf(i64 1) + %187 = call double @main.Inf(i64 -1) + %188 = call double @main.NaN() + %189 = call double @main.NaN() + %190 = call i1 @main.IsNaN(double %189) + %191 = call i1 @main.IsNaN(double 1.000000e+00) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %186) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %187) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintFloat"(double %188) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %190) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %191) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %192 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %193 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %192, i32 0, i32 0 + store ptr @7, ptr %193, align 8 + %194 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %192, i32 0, i32 1 + store i64 7, ptr %194, align 4 + %195 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %192, align 8 + %196 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.StringToBytes"(%"github.com/goplus/llgo/internal/runtime.String" %195) + %197 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %198 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %197, i32 0, i32 0 + store ptr @8, ptr %198, align 8 + %199 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %197, i32 0, i32 1 + store i64 7, ptr %199, align 4 + %200 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %197, align 8 + %201 = call %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.StringToRunes"(%"github.com/goplus/llgo/internal/runtime.String" %200) + call void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice" %196) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice" %201) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %202 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromBytes"(%"github.com/goplus/llgo/internal/runtime.Slice" %196) + %203 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromRunes"(%"github.com/goplus/llgo/internal/runtime.Slice" %201) + %204 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %196, 0 + %205 = getelementptr inbounds i8, ptr %204, i64 3 + %206 = load i8, ptr %205, align 1 + %207 = sext i8 %206 to i32 + %208 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromRune"(i32 %207) + %209 = extractvalue %"github.com/goplus/llgo/internal/runtime.Slice" %201, 0 + %210 = getelementptr inbounds i32, ptr %209, i64 0 + %211 = load i32, ptr %210, align 4 + %212 = call %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromRune"(i32 %211) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %202) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %203) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %208) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintString"(%"github.com/goplus/llgo/internal/runtime.String" %212) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) + %213 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %214 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %213, i32 0, i32 0 + store ptr @9, ptr %214, align 8 + %215 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %213, i32 0, i32 1 + store i64 3, ptr %215, align 4 + %216 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %213, align 8 + %217 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %218 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %217, i32 0, i32 0 + store ptr @10, ptr %218, align 8 + %219 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %217, i32 0, i32 1 + store i64 3, ptr %219, align 4 + %220 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %217, align 8 + %221 = call i1 @"github.com/goplus/llgo/internal/runtime.StringEqual"(%"github.com/goplus/llgo/internal/runtime.String" %216, %"github.com/goplus/llgo/internal/runtime.String" %220) + %222 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %223 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %222, i32 0, i32 0 + store ptr @11, ptr %223, align 8 + %224 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %222, i32 0, i32 1 + store i64 3, ptr %224, align 4 + %225 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %222, align 8 + %226 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %227 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %226, i32 0, i32 0 + store ptr @12, ptr %227, align 8 + %228 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %226, i32 0, i32 1 + store i64 3, ptr %228, align 4 + %229 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %226, align 8 + %230 = call i1 @"github.com/goplus/llgo/internal/runtime.StringEqual"(%"github.com/goplus/llgo/internal/runtime.String" %225, %"github.com/goplus/llgo/internal/runtime.String" %229) + %231 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %232 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %231, i32 0, i32 0 + store ptr @13, ptr %232, align 8 + %233 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %231, i32 0, i32 1 + store i64 3, ptr %233, align 4 + %234 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %231, align 8 + %235 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %236 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %235, i32 0, i32 0 + store ptr @14, ptr %236, align 8 + %237 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %235, i32 0, i32 1 + store i64 3, ptr %237, align 4 + %238 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %235, align 8 + %239 = call i1 @"github.com/goplus/llgo/internal/runtime.StringEqual"(%"github.com/goplus/llgo/internal/runtime.String" %234, %"github.com/goplus/llgo/internal/runtime.String" %238) + %240 = xor i1 %239, true + %241 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %242 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %241, i32 0, i32 0 + store ptr @15, ptr %242, align 8 + %243 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %241, i32 0, i32 1 + store i64 3, ptr %243, align 4 + %244 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %241, align 8 + %245 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %246 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %245, i32 0, i32 0 + store ptr @16, ptr %246, align 8 + %247 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %245, i32 0, i32 1 + store i64 3, ptr %247, align 4 + %248 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %245, align 8 + %249 = call i1 @"github.com/goplus/llgo/internal/runtime.StringLess"(%"github.com/goplus/llgo/internal/runtime.String" %244, %"github.com/goplus/llgo/internal/runtime.String" %248) + %250 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %251 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %250, i32 0, i32 0 + store ptr @17, ptr %251, align 8 + %252 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %250, i32 0, i32 1 + store i64 3, ptr %252, align 4 + %253 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %250, align 8 + %254 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %255 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %254, i32 0, i32 0 + store ptr @18, ptr %255, align 8 + %256 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %254, i32 0, i32 1 + store i64 3, ptr %256, align 4 + %257 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %254, align 8 + %258 = call i1 @"github.com/goplus/llgo/internal/runtime.StringLess"(%"github.com/goplus/llgo/internal/runtime.String" %257, %"github.com/goplus/llgo/internal/runtime.String" %253) + %259 = xor i1 %258, true + %260 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %261 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %260, i32 0, i32 0 + store ptr @19, ptr %261, align 8 + %262 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %260, i32 0, i32 1 + store i64 3, ptr %262, align 4 + %263 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %260, align 8 + %264 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %265 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %264, i32 0, i32 0 + store ptr @20, ptr %265, align 8 + %266 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %264, i32 0, i32 1 + store i64 3, ptr %266, align 4 + %267 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %264, align 8 + %268 = call i1 @"github.com/goplus/llgo/internal/runtime.StringLess"(%"github.com/goplus/llgo/internal/runtime.String" %267, %"github.com/goplus/llgo/internal/runtime.String" %263) + %269 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %270 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %269, i32 0, i32 0 + store ptr @21, ptr %270, align 8 + %271 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %269, i32 0, i32 1 + store i64 3, ptr %271, align 4 + %272 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %269, align 8 + %273 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 + %274 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %273, i32 0, i32 0 + store ptr @22, ptr %274, align 8 + %275 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %273, i32 0, i32 1 + store i64 3, ptr %275, align 4 + %276 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %273, align 8 + %277 = call i1 @"github.com/goplus/llgo/internal/runtime.StringLess"(%"github.com/goplus/llgo/internal/runtime.String" %272, %"github.com/goplus/llgo/internal/runtime.String" %276) + %278 = xor i1 %277, true + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %221) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %230) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %240) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %249) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %259) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %268) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 32) + call void @"github.com/goplus/llgo/internal/runtime.PrintBool"(i1 %278) + call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) ret i32 0 } -declare void @"github.com/goplus/llgo/internal/runtime.init"() - declare ptr @"github.com/goplus/llgo/internal/runtime.AllocZ"(i64) +declare void @"github.com/goplus/llgo/internal/runtime.init"() + 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.PrintSlice"(%"github.com/goplus/llgo/internal/runtime.Slice") @@ -431,7 +671,7 @@ define void @"main.main$1"() { _llgo_0: %0 = alloca %"github.com/goplus/llgo/internal/runtime.String", align 8 %1 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 0 - store ptr @6, ptr %1, align 8 + store ptr @23, ptr %1, align 8 %2 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.String", ptr %0, i32 0, i32 1 store i64 2, ptr %2, align 4 %3 = load %"github.com/goplus/llgo/internal/runtime.String", ptr %0, align 8 @@ -439,3 +679,21 @@ _llgo_0: call void @"github.com/goplus/llgo/internal/runtime.PrintByte"(i8 10) ret void } + +declare ptr @"github.com/goplus/llgo/internal/runtime.NewStringIter"(%"github.com/goplus/llgo/internal/runtime.String") + +declare { i1, i64, i32 } @"github.com/goplus/llgo/internal/runtime.StringIterNext"(ptr) + +declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.StringToBytes"(%"github.com/goplus/llgo/internal/runtime.String") + +declare %"github.com/goplus/llgo/internal/runtime.Slice" @"github.com/goplus/llgo/internal/runtime.StringToRunes"(%"github.com/goplus/llgo/internal/runtime.String") + +declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromBytes"(%"github.com/goplus/llgo/internal/runtime.Slice") + +declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromRunes"(%"github.com/goplus/llgo/internal/runtime.Slice") + +declare %"github.com/goplus/llgo/internal/runtime.String" @"github.com/goplus/llgo/internal/runtime.StringFromRune"(i32) + +declare i1 @"github.com/goplus/llgo/internal/runtime.StringEqual"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String") + +declare i1 @"github.com/goplus/llgo/internal/runtime.StringLess"(%"github.com/goplus/llgo/internal/runtime.String", %"github.com/goplus/llgo/internal/runtime.String") diff --git a/cl/_testrt/cast/out.ll b/cl/_testrt/cast/out.ll index 794eea9e..1f82dabd 100644 --- a/cl/_testrt/cast/out.ll +++ b/cl/_testrt/cast/out.ll @@ -82,7 +82,7 @@ _llgo_2: ; preds = %_llgo_0 define void @main.cvt32Fto64F(float %0, double %1) { _llgo_0: %2 = fpext float %0 to double - %3 = fcmp one double %2, %1 + %3 = fcmp une double %2, %1 br i1 %3, label %_llgo_1, label %_llgo_2 _llgo_1: ; preds = %_llgo_0 @@ -198,7 +198,7 @@ _llgo_2: ; preds = %_llgo_0 define void @main.cvt64Fto32F(double %0, float %1) { _llgo_0: %2 = fptrunc double %0 to float - %3 = fcmp one float %2, %1 + %3 = fcmp une float %2, %1 br i1 %3, label %_llgo_1, label %_llgo_2 _llgo_1: ; preds = %_llgo_0 @@ -227,7 +227,7 @@ _llgo_2: ; preds = %_llgo_0 define void @main.cvt64Uto64F(i64 %0, double %1) { _llgo_0: %2 = uitofp i64 %0 to double - %3 = fcmp one double %2, %1 + %3 = fcmp une double %2, %1 br i1 %3, label %_llgo_1, label %_llgo_2 _llgo_1: ; preds = %_llgo_0 @@ -256,7 +256,7 @@ _llgo_2: ; preds = %_llgo_0 define void @main.cvt64to64F(i64 %0, double %1) { _llgo_0: %2 = sitofp i64 %0 to double - %3 = fcmp one double %2, %1 + %3 = fcmp une double %2, %1 br i1 %3, label %_llgo_1, label %_llgo_2 _llgo_1: ; preds = %_llgo_0 diff --git a/cl/compile.go b/cl/compile.go index 1b23d3b8..991c136e 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -714,6 +714,12 @@ func (p *context) compileInstrOrValue(b llssa.Builder, iv instrOrValue, asValue case *ssa.Extract: x := p.compileValue(b, v.Tuple) ret = b.Extract(x, v.Index) + case *ssa.Range: + x := p.compileValue(b, v.X) + ret = b.Range(x) + case *ssa.Next: + iter := p.compileValue(b, v.Iter) + ret = b.Next(iter, v.IsString) default: panic(fmt.Sprintf("compileInstrAndValue: unknown instr - %T\n", iv)) } diff --git a/internal/runtime/llgo_autogen.lla b/internal/runtime/llgo_autogen.lla index a5c5b75bc81fc925cd674fcc15e25965e95a45cc..92d400d629a0cacaa8cde57ce89b1329599314e9 100644 GIT binary patch literal 10013 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 len(s) { + return runeError, k + 1 + } + + s = s[k:] + + switch { + case t2 <= s[0] && s[0] < t3: + // 0080-07FF two byte sequence + if len(s) > 1 && (locb <= s[1] && s[1] <= hicb) { + r = rune(s[0]&mask2)<<6 | rune(s[1]&maskx) + pos += 2 + if rune1Max < r { + return + } + } + case t3 <= s[0] && s[0] < t4: + // 0800-FFFF three byte sequence + if len(s) > 2 && (locb <= s[1] && s[1] <= hicb) && (locb <= s[2] && s[2] <= hicb) { + r = rune(s[0]&mask3)<<12 | rune(s[1]&maskx)<<6 | rune(s[2]&maskx) + pos += 3 + if rune2Max < r && !(surrogateMin <= r && r <= surrogateMax) { + return + } + } + case t4 <= s[0] && s[0] < t5: + // 10000-1FFFFF four byte sequence + if len(s) > 3 && (locb <= s[1] && s[1] <= hicb) && (locb <= s[2] && s[2] <= hicb) && (locb <= s[3] && s[3] <= hicb) { + r = rune(s[0]&mask4)<<18 | rune(s[1]&maskx)<<12 | rune(s[2]&maskx)<<6 | rune(s[3]&maskx) + pos += 4 + if rune3Max < r && r <= maxRune { + return + } + } + } + + return runeError, k + 1 +} + +// encoderune writes into p (which must be large enough) the UTF-8 encoding of the rune. +// It returns the number of bytes written. +func encoderune(p []byte, r rune) int { + // Negative values are erroneous. Making it unsigned addresses the problem. + switch i := uint32(r); { + case i <= rune1Max: + p[0] = byte(r) + return 1 + case i <= rune2Max: + _ = p[1] // eliminate bounds checks + p[0] = t2 | byte(r>>6) + p[1] = tx | byte(r)&maskx + return 2 + case i > maxRune, surrogateMin <= i && i <= surrogateMax: + r = runeError + fallthrough + case i <= rune3Max: + _ = p[2] // eliminate bounds checks + p[0] = t3 | byte(r>>12) + p[1] = tx | byte(r>>6)&maskx + p[2] = tx | byte(r)&maskx + return 3 + default: + _ = p[3] // eliminate bounds checks + p[0] = t4 | byte(r>>18) + p[1] = tx | byte(r>>12)&maskx + p[2] = tx | byte(r>>6)&maskx + p[3] = tx | byte(r)&maskx + return 4 + } +} diff --git a/internal/runtime/z_string.go b/internal/runtime/z_string.go index f4d20906..e34ae730 100644 --- a/internal/runtime/z_string.go +++ b/internal/runtime/z_string.go @@ -70,4 +70,119 @@ func NewStringSlice(base String, i, j int) String { return String{nil, 0} } +type StringIter struct { + s string + pos int +} + +func NewStringIter(s string) *StringIter { + return &StringIter{s, 0} +} + +func StringIterNext(it *StringIter) (ok bool, k int, v rune) { + if it.pos >= len(it.s) { + return false, 0, 0 + } + k = it.pos + if c := it.s[it.pos]; c < runeSelf { + it.pos++ + v = rune(c) + } else { + v, it.pos = decoderune(it.s, it.pos) + } + ok = true + return +} + +func StringToBytes(s String) []byte { + if s.len == 0 { + return nil + } + data := make([]byte, s.len) + c.Memcpy(unsafe.Pointer(&data[0]), s.data, uintptr(s.len)) + return data +} + +func StringToRunes(s string) []rune { + if len(s) == 0 { + return nil + } + data := make([]rune, len(s)) + var index uint + for i := 0; i < len(s); { + if c := s[i]; c < runeSelf { + data[index] = rune(c) + i++ + } else { + data[index], i = decoderune(s, i) + } + index++ + } + return data[:index:index] +} + +func StringFromBytes(b Slice) (s String) { + if b.len == 0 { + return + } + s.len = b.len + s.data = AllocU(uintptr(s.len)) + c.Memcpy(s.data, b.data, uintptr(b.len)) + return +} + +func StringFromRunes(rs []rune) (s String) { + if len(rs) == 0 { + return + } + data := make([]byte, len(rs)*4) + var index int + for _, r := range rs { + n := encoderune(data[index:], r) + index += n + } + s.len = index + s.data = unsafe.Pointer(&data[0]) + return +} + +func StringFromRune(r rune) (s String) { + var buf [4]byte + n := encoderune(buf[:], r) + s.len = n + s.data = unsafe.Pointer(&buf[0]) + return +} + +func StringEqual(x, y String) bool { + if x.len != y.len { + return false + } + if x.data != y.data { + for i := 0; i < x.len; i++ { + if *(*byte)(c.Advance(x.data, i)) != *(*byte)(c.Advance(y.data, i)) { + return false + } + } + } + return true +} + +func StringLess(x, y String) bool { + n := x.len + if n > y.len { + n = y.len + } + for i := 0; i < n; i++ { + ix := *(*byte)(c.Advance(x.data, i)) + iy := *(*byte)(c.Advance(y.data, i)) + if ix < iy { + return true + } else if ix > iy { + return false + } + } + return x.len < y.len +} + // ----------------------------------------------------------------------------- diff --git a/ssa/expr.go b/ssa/expr.go index 6fce4fbe..d54090e3 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -315,7 +315,7 @@ var uintPredOpToLLVM = []llvm.IntPredicate{ var floatPredOpToLLVM = []llvm.FloatPredicate{ token.EQL - predOpBase: llvm.FloatOEQ, - token.NEQ - predOpBase: llvm.FloatONE, + token.NEQ - predOpBase: llvm.FloatUNE, token.LSS - predOpBase: llvm.FloatOLT, token.LEQ - predOpBase: llvm.FloatOLE, token.GTR - predOpBase: llvm.FloatOGT, @@ -405,7 +405,26 @@ func (b Builder) BinOp(op token.Token, x, y Expr) Expr { pred := boolPredOpToLLVM[op-predOpBase] return Expr{llvm.CreateICmp(b.impl, pred, x.impl, y.impl), tret} case vkString, vkComplex: - panic("todo") + switch op { + case token.EQL: + return b.InlineCall(b.Pkg.rtFunc("StringEqual"), x, y) + case token.NEQ: + ret := b.InlineCall(b.Pkg.rtFunc("StringEqual"), x, y) + ret.impl = llvm.CreateNot(b.impl, ret.impl) + return ret + case token.LSS: + return b.InlineCall(b.Pkg.rtFunc("StringLess"), x, y) + case token.LEQ: + ret := b.InlineCall(b.Pkg.rtFunc("StringLess"), y, x) + ret.impl = llvm.CreateNot(b.impl, ret.impl) + return ret + case token.GTR: + return b.InlineCall(b.Pkg.rtFunc("StringLess"), y, x) + case token.GEQ: + ret := b.InlineCall(b.Pkg.rtFunc("StringLess"), x, y) + ret.impl = llvm.CreateNot(b.impl, ret.impl) + return ret + } } } panic("todo") @@ -833,6 +852,27 @@ func (b Builder) Convert(t Type, x Expr) (ret Expr) { case types.UnsafePointer: ret.impl = castPtr(b.impl, x.impl, t.ll) return + case types.String: + switch xtyp := x.RawType().Underlying().(type) { + case *types.Slice: + if etyp, ok := xtyp.Elem().Underlying().(*types.Basic); ok { + switch etyp.Kind() { + case types.Byte: + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringFromBytes"), x).impl + return + case types.Rune: + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringFromRunes"), x).impl + return + } + } + case *types.Basic: + if x.Type != b.Prog.Int32() { + x.Type = b.Prog.Int32() + x.impl = castInt(b, x.impl, b.Prog.Int32()) + } + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringFromRune"), x).impl + return + } } switch xtyp := x.RawType().Underlying().(type) { case *types.Basic: @@ -867,6 +907,19 @@ func (b Builder) Convert(t Type, x Expr) (ret Expr) { case *types.Pointer: ret.impl = castPtr(b.impl, x.impl, t.ll) return + case *types.Slice: + if x.kind == vkString { + if etyp, ok := typ.Elem().Underlying().(*types.Basic); ok { + switch etyp.Kind() { + case types.Byte: + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringToBytes"), x).impl + return + case types.Rune: + ret.impl = b.InlineCall(b.Func.Pkg.rtFunc("StringToRunes"), x).impl + return + } + } + } } panic("todo") } @@ -969,6 +1022,51 @@ func (b Builder) Call(fn Expr, args ...Expr) (ret Expr) { return } +// The Range instruction yields an iterator over the domain and range +// of X, which must be a string or map. +// +// Elements are accessed via Next. +// +// Type() returns an opaque and degenerate "rangeIter" type. +// +// Pos() returns the ast.RangeStmt.For. +// +// Example printed form: +// +// t0 = range "hello":string +func (b Builder) Range(x Expr) Expr { + switch x.kind { + case vkString: + return b.InlineCall(b.Pkg.rtFunc("NewStringIter"), x) + } + panic("todo") +} + +// The Next instruction reads and advances the (map or string) +// iterator Iter and returns a 3-tuple value (ok, k, v). If the +// iterator is not exhausted, ok is true and k and v are the next +// elements of the domain and range, respectively. Otherwise ok is +// false and k and v are undefined. +// +// Components of the tuple are accessed using Extract. +// +// The IsString field distinguishes iterators over strings from those +// over maps, as the Type() alone is insufficient: consider +// map[int]rune. +// +// Type() returns a *types.Tuple for the triple (ok, k, v). +// The types of k and/or v may be types.Invalid. +// +// Example printed form: +// +// t1 = next t0 +func (b Builder) Next(iter Expr, isString bool) (ret Expr) { + if isString { + return b.InlineCall(b.Pkg.rtFunc("StringIterNext"), iter) + } + panic("todo") +} + // A Builtin represents a specific use of a built-in function, e.g. len. // // Builtins are immutable values. Builtins do not have addresses.