github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/irgen/strings.go (about) 1 //===- strings.go - IR generation for string ops --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements IR generation for string operations. 11 // 12 //===----------------------------------------------------------------------===// 13 14 package irgen 15 16 import ( 17 "go/token" 18 19 "llvm.org/llgo/third_party/gotools/go/types" 20 "llvm.org/llvm/bindings/go/llvm" 21 ) 22 23 func (fr *frame) concatenateStrings(lhs, rhs *govalue) *govalue { 24 result := fr.runtime.stringPlus.call(fr, lhs.value, rhs.value) 25 return newValue(result[0], types.Typ[types.String]) 26 } 27 28 func (fr *frame) compareStringEmpty(v llvm.Value) *govalue { 29 len := fr.builder.CreateExtractValue(v, 1, "") 30 result := fr.builder.CreateIsNull(len, "") 31 result = fr.builder.CreateZExt(result, llvm.Int8Type(), "") 32 return newValue(result, types.Typ[types.Bool]) 33 } 34 35 func (fr *frame) compareStrings(lhs, rhs *govalue, op token.Token) *govalue { 36 if op == token.EQL { 37 if lhs.value.IsNull() { 38 return fr.compareStringEmpty(rhs.value) 39 } 40 if rhs.value.IsNull() { 41 return fr.compareStringEmpty(lhs.value) 42 } 43 } 44 45 result := fr.runtime.strcmp.call(fr, lhs.value, rhs.value)[0] 46 zero := llvm.ConstNull(fr.types.inttype) 47 var pred llvm.IntPredicate 48 switch op { 49 case token.EQL: 50 pred = llvm.IntEQ 51 case token.LSS: 52 pred = llvm.IntSLT 53 case token.GTR: 54 pred = llvm.IntSGT 55 case token.LEQ: 56 pred = llvm.IntSLE 57 case token.GEQ: 58 pred = llvm.IntSGE 59 case token.NEQ: 60 panic("NEQ is handled in govalue.BinaryOp") 61 default: 62 panic("unreachable") 63 } 64 result = fr.builder.CreateICmp(pred, result, zero, "") 65 result = fr.builder.CreateZExt(result, llvm.Int8Type(), "") 66 return newValue(result, types.Typ[types.Bool]) 67 } 68 69 // stringIndex implements v = m[i] 70 func (fr *frame) stringIndex(s, i *govalue) *govalue { 71 ptr := fr.builder.CreateExtractValue(s.value, 0, "") 72 ptr = fr.builder.CreateGEP(ptr, []llvm.Value{i.value}, "") 73 return newValue(fr.builder.CreateLoad(ptr, ""), types.Typ[types.Byte]) 74 } 75 76 func (fr *frame) stringIterInit(str *govalue) []*govalue { 77 indexptr := fr.allocaBuilder.CreateAlloca(fr.types.inttype, "") 78 fr.builder.CreateStore(llvm.ConstNull(fr.types.inttype), indexptr) 79 return []*govalue{str, newValue(indexptr, types.Typ[types.Int])} 80 } 81 82 // stringIterNext advances the iterator, and returns the tuple (ok, k, v). 83 func (fr *frame) stringIterNext(iter []*govalue) []*govalue { 84 str, indexptr := iter[0], iter[1] 85 k := fr.builder.CreateLoad(indexptr.value, "") 86 87 result := fr.runtime.stringiter2.call(fr, str.value, k) 88 fr.builder.CreateStore(result[0], indexptr.value) 89 ok := fr.builder.CreateIsNotNull(result[0], "") 90 ok = fr.builder.CreateZExt(ok, llvm.Int8Type(), "") 91 v := result[1] 92 93 return []*govalue{newValue(ok, types.Typ[types.Bool]), newValue(k, types.Typ[types.Int]), newValue(v, types.Typ[types.Rune])} 94 } 95 96 func (fr *frame) runeToString(v *govalue) *govalue { 97 v = fr.convert(v, types.Typ[types.Int]) 98 result := fr.runtime.intToString.call(fr, v.value) 99 return newValue(result[0], types.Typ[types.String]) 100 } 101 102 func (fr *frame) stringToRuneSlice(v *govalue) *govalue { 103 result := fr.runtime.stringToIntArray.call(fr, v.value) 104 runeslice := types.NewSlice(types.Typ[types.Rune]) 105 return newValue(result[0], runeslice) 106 } 107 108 func (fr *frame) runeSliceToString(v *govalue) *govalue { 109 llv := v.value 110 ptr := fr.builder.CreateExtractValue(llv, 0, "") 111 len := fr.builder.CreateExtractValue(llv, 1, "") 112 result := fr.runtime.intArrayToString.call(fr, ptr, len) 113 return newValue(result[0], types.Typ[types.String]) 114 }