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 (v *Codegen) genDefaultValue(typ parser.Type) llvm.Value { atyp := typ.ActualType() // Generate default struct values if structType, ok := atyp.(parser.StructType); ok { lit := createStructInitializer(typ) if lit != nil { return v.genStructLiteral(lit) } else { return llvm.Undef(v.typeToLLVMType(structType)) } } if tupleType, ok := atyp.(parser.TupleType); ok { values := make([]llvm.Value, len(tupleType.Members)) for idx, member := range tupleType.Members { values[idx] = v.genDefaultValue(member) } return llvm.ConstStruct(values, false) } if atyp.IsIntegerType() || atyp == parser.PRIMITIVE_bool { return llvm.ConstInt(v.typeToLLVMType(atyp), 0, false) } if atyp.IsFloatingType() { return llvm.ConstFloat(v.typeToLLVMType(atyp), 0) } panic("type does not have default value: " + atyp.TypeName()) }
func (v *Codegen) genTupleLiteral(n *parser.TupleLiteral) llvm.Value { // TODO: Is this optimal? var values []llvm.Value for _, mem := range n.Members { values = append(values, v.genExpr(mem)) } return llvm.ConstStruct(values, false) }
func (u *unit) addGlobal(global llvm.Value, ty types.Type) { u.globalInits[global] = new(globalInit) if hasPointers(ty) { global = llvm.ConstBitCast(global, llvm.PointerType(llvm.Int8Type(), 0)) size := llvm.ConstInt(u.types.inttype, uint64(u.types.Sizeof(ty)), false) root := llvm.ConstStruct([]llvm.Value{global, size}, false) u.gcRoots = append(u.gcRoots, root) } }
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) } }