| //===- strings.go - IR generation for string ops --------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements IR generation for string operations. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| package irgen |
| |
| import ( |
| "go/token" |
| |
| "llvm.org/llgo/third_party/gotools/go/types" |
| "llvm.org/llvm/bindings/go/llvm" |
| ) |
| |
| func (fr *frame) concatenateStrings(lhs, rhs *govalue) *govalue { |
| result := fr.runtime.stringPlus.call(fr, lhs.value, rhs.value) |
| return newValue(result[0], types.Typ[types.String]) |
| } |
| |
| func (fr *frame) compareStringEmpty(v llvm.Value) *govalue { |
| len := fr.builder.CreateExtractValue(v, 1, "") |
| result := fr.builder.CreateIsNull(len, "") |
| result = fr.builder.CreateZExt(result, llvm.Int8Type(), "") |
| return newValue(result, types.Typ[types.Bool]) |
| } |
| |
| func (fr *frame) compareStrings(lhs, rhs *govalue, op token.Token) *govalue { |
| if op == token.EQL { |
| if lhs.value.IsNull() { |
| return fr.compareStringEmpty(rhs.value) |
| } |
| if rhs.value.IsNull() { |
| return fr.compareStringEmpty(lhs.value) |
| } |
| } |
| |
| result := fr.runtime.strcmp.call(fr, lhs.value, rhs.value)[0] |
| zero := llvm.ConstNull(fr.types.inttype) |
| var pred llvm.IntPredicate |
| switch op { |
| case token.EQL: |
| pred = llvm.IntEQ |
| case token.LSS: |
| pred = llvm.IntSLT |
| case token.GTR: |
| pred = llvm.IntSGT |
| case token.LEQ: |
| pred = llvm.IntSLE |
| case token.GEQ: |
| pred = llvm.IntSGE |
| case token.NEQ: |
| panic("NEQ is handled in govalue.BinaryOp") |
| default: |
| panic("unreachable") |
| } |
| result = fr.builder.CreateICmp(pred, result, zero, "") |
| result = fr.builder.CreateZExt(result, llvm.Int8Type(), "") |
| return newValue(result, types.Typ[types.Bool]) |
| } |
| |
| // stringIndex implements v = m[i] |
| func (fr *frame) stringIndex(s, i *govalue) *govalue { |
| ptr := fr.builder.CreateExtractValue(s.value, 0, "") |
| ptr = fr.builder.CreateGEP(ptr, []llvm.Value{i.value}, "") |
| return newValue(fr.builder.CreateLoad(ptr, ""), types.Typ[types.Byte]) |
| } |
| |
| func (fr *frame) stringIterInit(str *govalue) []*govalue { |
| indexptr := fr.allocaBuilder.CreateAlloca(fr.types.inttype, "") |
| fr.builder.CreateStore(llvm.ConstNull(fr.types.inttype), indexptr) |
| return []*govalue{str, newValue(indexptr, types.Typ[types.Int])} |
| } |
| |
| // stringIterNext advances the iterator, and returns the tuple (ok, k, v). |
| func (fr *frame) stringIterNext(iter []*govalue) []*govalue { |
| str, indexptr := iter[0], iter[1] |
| k := fr.builder.CreateLoad(indexptr.value, "") |
| |
| result := fr.runtime.stringiter2.call(fr, str.value, k) |
| fr.builder.CreateStore(result[0], indexptr.value) |
| ok := fr.builder.CreateIsNotNull(result[0], "") |
| ok = fr.builder.CreateZExt(ok, llvm.Int8Type(), "") |
| v := result[1] |
| |
| return []*govalue{newValue(ok, types.Typ[types.Bool]), newValue(k, types.Typ[types.Int]), newValue(v, types.Typ[types.Rune])} |
| } |
| |
| func (fr *frame) runeToString(v *govalue) *govalue { |
| v = fr.convert(v, types.Typ[types.Int]) |
| result := fr.runtime.intToString.call(fr, v.value) |
| return newValue(result[0], types.Typ[types.String]) |
| } |
| |
| func (fr *frame) stringToRuneSlice(v *govalue) *govalue { |
| result := fr.runtime.stringToIntArray.call(fr, v.value) |
| runeslice := types.NewSlice(types.Typ[types.Rune]) |
| return newValue(result[0], runeslice) |
| } |
| |
| func (fr *frame) runeSliceToString(v *govalue) *govalue { |
| llv := v.value |
| ptr := fr.builder.CreateExtractValue(llv, 0, "") |
| len := fr.builder.CreateExtractValue(llv, 1, "") |
| result := fr.runtime.intArrayToString.call(fr, ptr, len) |
| return newValue(result[0], types.Typ[types.String]) |
| } |