func (v *Codegen) genStringLiteral(n *parser.StringLiteral) llvm.Value { memberLLVMType := v.typeToLLVMType(parser.PRIMITIVE_u8) nullTerm := n.IsCString length := len(n.Value) if nullTerm { length++ } var backingArrayPointer llvm.Value if v.inFunction() { // allocate backing array backingArray := v.builder().CreateAlloca(llvm.ArrayType(memberLLVMType, length), "stackstr") v.builder().CreateStore(llvm.ConstString(n.Value, nullTerm), backingArray) backingArrayPointer = v.builder().CreateBitCast(backingArray, llvm.PointerType(memberLLVMType, 0), "") } else { backName := fmt.Sprintf("_globarr_back_%d", v.arrayIndex) v.arrayIndex++ backingArray := llvm.AddGlobal(v.curFile.LlvmModule, llvm.ArrayType(memberLLVMType, length), backName) backingArray.SetLinkage(llvm.InternalLinkage) backingArray.SetGlobalConstant(false) backingArray.SetInitializer(llvm.ConstString(n.Value, nullTerm)) backingArrayPointer = llvm.ConstBitCast(backingArray, llvm.PointerType(memberLLVMType, 0)) } if n.Type.ActualType().Equals(parser.ArrayOf(parser.PRIMITIVE_u8)) { lengthValue := llvm.ConstInt(v.typeToLLVMType(parser.PRIMITIVE_uint), uint64(length), false) structValue := llvm.Undef(v.typeToLLVMType(n.Type)) structValue = v.builder().CreateInsertValue(structValue, lengthValue, 0, "") structValue = v.builder().CreateInsertValue(structValue, backingArrayPointer, 1, "") return structValue } else { return backingArrayPointer } }
// newValueFromConst converts a constant value to an LLVM value. func (fr *frame) newValueFromConst(v exact.Value, typ types.Type) *govalue { switch { case v == nil: llvmtyp := fr.types.ToLLVM(typ) return newValue(llvm.ConstNull(llvmtyp), typ) case isString(typ): if isUntyped(typ) { typ = types.Typ[types.String] } llvmtyp := fr.types.ToLLVM(typ) strval := exact.StringVal(v) strlen := len(strval) i8ptr := llvm.PointerType(llvm.Int8Type(), 0) var ptr llvm.Value if strlen > 0 { init := llvm.ConstString(strval, false) ptr = llvm.AddGlobal(fr.module.Module, init.Type(), "") ptr.SetInitializer(init) ptr.SetLinkage(llvm.InternalLinkage) ptr = llvm.ConstBitCast(ptr, i8ptr) } else { ptr = llvm.ConstNull(i8ptr) } len_ := llvm.ConstInt(fr.types.inttype, uint64(strlen), false) llvmvalue := llvm.Undef(llvmtyp) llvmvalue = llvm.ConstInsertValue(llvmvalue, ptr, []uint32{0}) llvmvalue = llvm.ConstInsertValue(llvmvalue, len_, []uint32{1}) return newValue(llvmvalue, typ) case isInteger(typ): if isUntyped(typ) { typ = types.Typ[types.Int] } llvmtyp := fr.types.ToLLVM(typ) var llvmvalue llvm.Value if isUnsigned(typ) { v, _ := exact.Uint64Val(v) llvmvalue = llvm.ConstInt(llvmtyp, v, false) } else { v, _ := exact.Int64Val(v) llvmvalue = llvm.ConstInt(llvmtyp, uint64(v), true) } return newValue(llvmvalue, typ) case isBoolean(typ): if isUntyped(typ) { typ = types.Typ[types.Bool] } return newValue(boolLLVMValue(exact.BoolVal(v)), typ) case isFloat(typ): if isUntyped(typ) { typ = types.Typ[types.Float64] } llvmtyp := fr.types.ToLLVM(typ) floatval, _ := exact.Float64Val(v) llvmvalue := llvm.ConstFloat(llvmtyp, floatval) return newValue(llvmvalue, typ) case typ == types.Typ[types.UnsafePointer]: llvmtyp := fr.types.ToLLVM(typ) v, _ := exact.Uint64Val(v) llvmvalue := llvm.ConstInt(fr.types.inttype, v, false) llvmvalue = llvm.ConstIntToPtr(llvmvalue, llvmtyp) return newValue(llvmvalue, typ) case isComplex(typ): if isUntyped(typ) { typ = types.Typ[types.Complex128] } llvmtyp := fr.types.ToLLVM(typ) floattyp := llvmtyp.StructElementTypes()[0] llvmvalue := llvm.ConstNull(llvmtyp) realv := exact.Real(v) imagv := exact.Imag(v) realfloatval, _ := exact.Float64Val(realv) imagfloatval, _ := exact.Float64Val(imagv) llvmre := llvm.ConstFloat(floattyp, realfloatval) llvmim := llvm.ConstFloat(floattyp, imagfloatval) llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmre, []uint32{0}) llvmvalue = llvm.ConstInsertValue(llvmvalue, llvmim, []uint32{1}) return newValue(llvmvalue, typ) } // Special case for string -> [](byte|rune) if u, ok := typ.Underlying().(*types.Slice); ok && isInteger(u.Elem()) { if v.Kind() == exact.String { strval := fr.newValueFromConst(v, types.Typ[types.String]) return fr.convert(strval, typ) } } panic(fmt.Sprintf("unhandled: t=%s(%T), v=%v(%T)", typ, typ, v, v)) }