// Allocates a literal array on the stack func (v *Codegen) genArrayLiteral(n *parser.ArrayLiteral) llvm.Value { memberLLVMType := v.typeToLLVMType(n.Type.(parser.ArrayType).MemberType) // allocate backing array arrAlloca := v.builder.CreateArrayAlloca(llvm.ArrayType(memberLLVMType, len(n.Members)), llvm.ConstInt(llvm.IntType(32), uint64(len(n.Members)), false), "") // allocate the array object structAlloca := v.builder.CreateAlloca(v.typeToLLVMType(n.Type), "") // set the length of the array lenGEP := v.builder.CreateGEP(structAlloca, []llvm.Value{llvm.ConstInt(llvm.IntType(32), 0, false), llvm.ConstInt(llvm.IntType(32), 0, false)}, "") v.builder.CreateStore(llvm.ConstInt(llvm.IntType(32), uint64(len(n.Members)), false), lenGEP) // set the array pointer to the backing array we allocated arrGEP := v.builder.CreateGEP(structAlloca, []llvm.Value{llvm.ConstInt(llvm.IntType(32), 0, false), llvm.ConstInt(llvm.IntType(32), 1, false)}, "") v.builder.CreateStore(v.builder.CreateBitCast(arrAlloca, llvm.PointerType(llvm.ArrayType(memberLLVMType, 0), 0), ""), arrGEP) // copy the constant array to the backing array arrConstVals := make([]llvm.Value, 0, len(n.Members)) for _, mem := range n.Members { arrConstVals = append(arrConstVals, v.genExpr(mem)) } arrConst := llvm.ConstArray(llvm.ArrayType(memberLLVMType, len(n.Members)), arrConstVals) v.builder.CreateStore(arrConst, arrAlloca) return v.builder.CreateLoad(structAlloca, "") }
func (gi *globalInit) build(typ llvm.Type) llvm.Value { if gi.val.C != nil { return gi.val } if len(gi.elems) == 0 { return llvm.ConstNull(typ) } switch typ.TypeKind() { case llvm.StructTypeKind: eltypes := typ.StructElementTypes() elems := make([]llvm.Value, len(eltypes)) for i, eltyp := range eltypes { elems[i] = gi.elems[i].build(eltyp) } return llvm.ConstStruct(elems, false) case llvm.ArrayTypeKind: eltyp := typ.ElementType() elems := make([]llvm.Value, len(gi.elems)) for i := range gi.elems { elems[i] = gi.elems[i].build(eltyp) } return llvm.ConstArray(eltyp, elems) default: panic("unexpected type") } }
func (fr *frame) registerGcRoots() { if len(fr.gcRoots) != 0 { rootty := fr.gcRoots[0].Type() roots := append(fr.gcRoots, llvm.ConstNull(rootty)) rootsarr := llvm.ConstArray(rootty, roots) rootsstruct := llvm.ConstStruct([]llvm.Value{llvm.ConstNull(llvm.PointerType(llvm.Int8Type(), 0)), rootsarr}, false) rootsglobal := llvm.AddGlobal(fr.module.Module, rootsstruct.Type(), "") rootsglobal.SetInitializer(rootsstruct) rootsglobal.SetLinkage(llvm.InternalLinkage) fr.runtime.registerGcRoots.callOnly(fr, llvm.ConstBitCast(rootsglobal, llvm.PointerType(llvm.Int8Type(), 0))) } }
// Allocates a literal array on the stack func (v *Codegen) genArrayLiteral(n *parser.ArrayLiteral) llvm.Value { arrayLLVMType := v.typeToLLVMType(n.Type) memberLLVMType := v.typeToLLVMType(n.Type.(parser.ArrayType).MemberType) if v.inFunction { // allocate backing array arrAlloca := v.builder.CreateAlloca(llvm.ArrayType(memberLLVMType, len(n.Members)), "") // copy the constant array to the backing array for idx, value := range n.Members { gep := v.builder.CreateGEP(arrAlloca, []llvm.Value{llvm.ConstInt(llvm.IntType(32), 0, false), llvm.ConstInt(llvm.IntType(32), uint64(idx), false)}, "") value := v.genExpr(value) v.builder.CreateStore(value, gep) } // allocate struct structAlloca := v.builder.CreateAlloca(arrayLLVMType, "") // set the length of the array lenGEP := v.builder.CreateGEP(structAlloca, []llvm.Value{llvm.ConstInt(llvm.IntType(32), 0, false), llvm.ConstInt(llvm.IntType(32), 0, false)}, "") v.builder.CreateStore(llvm.ConstInt(llvm.IntType(32), uint64(len(n.Members)), false), lenGEP) // set the array pointer to the backing array we allocated arrGEP := v.builder.CreateGEP(structAlloca, []llvm.Value{llvm.ConstInt(llvm.IntType(32), 0, false), llvm.ConstInt(llvm.IntType(32), 1, false)}, "") v.builder.CreateStore(v.builder.CreateBitCast(arrAlloca, llvm.PointerType(llvm.ArrayType(memberLLVMType, 0), 0), ""), arrGEP) return v.builder.CreateLoad(structAlloca, "") } else { backName := fmt.Sprintf("_globarr_back_%d", v.arrayIndex) v.arrayIndex++ backGlob := llvm.AddGlobal(v.curFile.Module, llvm.ArrayType(memberLLVMType, len(n.Members)), backName) backGlob.SetLinkage(llvm.InternalLinkage) backGlob.SetGlobalConstant(false) arrConstVals := make([]llvm.Value, len(n.Members)) for idx, mem := range n.Members { value := v.genExpr(mem) if !value.IsConstant() { v.err("Encountered non-constant value in global array") } arrConstVals[idx] = v.genExpr(mem) } backGlob.SetInitializer(llvm.ConstArray(memberLLVMType, arrConstVals)) lengthVal := llvm.ConstInt(llvm.IntType(32), uint64(len(n.Members)), false) backRef := llvm.ConstBitCast(backGlob, llvm.PointerType(llvm.ArrayType(memberLLVMType, 0), 0)) return llvm.ConstStruct([]llvm.Value{lengthVal, backRef}, false) } }
// Allocates a literal array on the stack func (v *Codegen) genArrayLiteral(n *parser.CompositeLiteral) llvm.Value { arrayLLVMType := v.typeToLLVMType(n.Type) memberLLVMType := v.typeToLLVMType(n.Type.ActualType().(parser.ArrayType).MemberType) arrayValues := make([]llvm.Value, len(n.Values)) for idx, mem := range n.Values { value := v.genExpr(mem) if !v.inFunction() && !value.IsConstant() { v.err("Encountered non-constant value in global array") } arrayValues[idx] = value } lengthValue := llvm.ConstInt(v.typeToLLVMType(parser.PRIMITIVE_uint), uint64(len(n.Values)), false) var backingArrayPointer llvm.Value if v.inFunction() { // allocate backing array backingArray := v.builder().CreateAlloca(llvm.ArrayType(memberLLVMType, len(n.Values)), "") // copy the constant array to the backing array for idx, value := range arrayValues { gep := v.builder().CreateStructGEP(backingArray, idx, "") v.builder().CreateStore(value, gep) } 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, len(n.Values)), backName) backingArray.SetLinkage(llvm.InternalLinkage) backingArray.SetGlobalConstant(false) backingArray.SetInitializer(llvm.ConstArray(memberLLVMType, arrayValues)) backingArrayPointer = llvm.ConstBitCast(backingArray, llvm.PointerType(memberLLVMType, 0)) } structValue := llvm.Undef(arrayLLVMType) structValue = v.builder().CreateInsertValue(structValue, lengthValue, 0, "") structValue = v.builder().CreateInsertValue(structValue, backingArrayPointer, 1, "") return structValue }
func (c *Codegen) generateStringLiteral(n *parser.StringLitNode) llvm.Value { vals := []llvm.Value{} for i := 0; i != len(n.Value); i++ { char := &parser.CharLitNode{Value: rune(n.Value[i])} vals = append(vals, c.generateExpression(char)) } vals = append(vals, c.generateExpression(&parser.CharLitNode{Value: 0})) arr := llvm.ConstArray(PRIMITIVE_TYPES["char"], vals) chars := c.builder.CreateMalloc(arr.Type(), "") c.builder.CreateStore(arr, chars) str := c.builder.CreateMalloc(c.templates["string"].Type, "") chars = c.builder.CreateBitCast(chars, llvm.PointerType(PRIMITIVE_TYPES["char"], 0), "") c.builder.CreateStore(chars, c.builder.CreateStructGEP(str, 0, "")) c.builder.CreateStore(llvm.ConstInt(PRIMITIVE_TYPES["int"], uint64(len(vals)), false), c.builder.CreateStructGEP(str, 1, "")) c.builder.CreateStore(llvm.ConstInt(PRIMITIVE_TYPES["int"], uint64(len(vals)), false), c.builder.CreateStructGEP(str, 2, "")) return str }