blob: 5762485d807fb850d1127a7f025a6c23516000b5 [file] [log] [blame]
Peter Collingbournead9841e2014-11-27 00:06:42 +00001//===- 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
14package irgen
15
16import (
17 "go/token"
Andrew Wilkinsc17d0bb2014-12-19 02:45:48 +000018
Peter Collingbourne56109b72015-01-13 20:45:08 +000019 "llvm.org/llgo/third_party/gotools/go/types"
Peter Collingbournead9841e2014-11-27 00:06:42 +000020 "llvm.org/llvm/bindings/go/llvm"
21)
22
23func (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
Peter Collingbournec5b84a52014-12-09 01:02:12 +000028func (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
Peter Collingbournead9841e2014-11-27 00:06:42 +000035func (fr *frame) compareStrings(lhs, rhs *govalue, op token.Token) *govalue {
Peter Collingbournec5b84a52014-12-09 01:02:12 +000036 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
Peter Collingbournead9841e2014-11-27 00:06:42 +000045 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]
70func (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
76func (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).
83func (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
96func (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
102func (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
108func (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}