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  }