Ejemplo n.º 1
0
// 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, "")
}
Ejemplo n.º 2
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)
	}
}
Ejemplo n.º 3
0
Archivo: codegen.go Proyecto: vnev/ark
// 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
}
Ejemplo n.º 4
0
Archivo: type.go Proyecto: vnev/ark
func (v *Codegen) enumTypeToLLVMTypeFields(typ parser.EnumType) []llvm.Type {
	longestLength := uint64(0)
	for _, member := range typ.Members {
		memLength := v.targetData.TypeAllocSize(v.typeToLLVMType(member.Type))
		if memLength > longestLength {
			longestLength = memLength
		}
	}

	// TODO: verify no overflow
	return []llvm.Type{llvm.IntType(32), llvm.ArrayType(llvm.IntType(8), int(longestLength))}
}
Ejemplo n.º 5
0
Archivo: codegen.go Proyecto: vnev/ark
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
	}
}
Ejemplo n.º 6
0
Archivo: cabi.go Proyecto: hinike/llgo
func (t arrayBType) ToLLVM(c llvm.Context) llvm.Type {
	return llvm.ArrayType(t.elem.ToLLVM(c), int(t.length))
}
Ejemplo n.º 7
0
func (v *Codegen) arrayTypeToLLVMType(typ parser.ArrayType) llvm.Type {
	fields := []llvm.Type{llvm.IntType(32), llvm.PointerType(llvm.ArrayType(v.typeToLLVMType(typ.MemberType), 0), 0)}

	return llvm.StructType(fields, false)
}
Ejemplo n.º 8
0
// mapIterNext advances the iterator, and returns the tuple (ok, k, v).
func (fr *frame) mapIterNext(iter []*govalue) []*govalue {
	maptyp := iter[0].Type().Underlying().(*types.Map)
	ktyp := maptyp.Key()
	klltyp := fr.types.ToLLVM(ktyp)
	vtyp := maptyp.Elem()
	vlltyp := fr.types.ToLLVM(vtyp)

	m, isinitptr := iter[0], iter[1]

	i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
	mapiterbufty := llvm.ArrayType(i8ptr, 4)
	mapiterbuf := fr.allocaBuilder.CreateAlloca(mapiterbufty, "")
	mapiterbufelem0ptr := fr.builder.CreateStructGEP(mapiterbuf, 0, "")

	keybuf := fr.allocaBuilder.CreateAlloca(klltyp, "")
	keyptr := fr.builder.CreateBitCast(keybuf, i8ptr, "")
	valbuf := fr.allocaBuilder.CreateAlloca(vlltyp, "")
	valptr := fr.builder.CreateBitCast(valbuf, i8ptr, "")

	isinit := fr.builder.CreateLoad(isinitptr.value, "")

	initbb := llvm.AddBasicBlock(fr.function, "")
	nextbb := llvm.AddBasicBlock(fr.function, "")
	contbb := llvm.AddBasicBlock(fr.function, "")

	fr.builder.CreateCondBr(isinit, nextbb, initbb)

	fr.builder.SetInsertPointAtEnd(initbb)
	fr.builder.CreateStore(llvm.ConstAllOnes(llvm.Int1Type()), isinitptr.value)
	fr.runtime.mapiterinit.call(fr, m.value, mapiterbufelem0ptr)
	fr.builder.CreateBr(contbb)

	fr.builder.SetInsertPointAtEnd(nextbb)
	fr.runtime.mapiternext.call(fr, mapiterbufelem0ptr)
	fr.builder.CreateBr(contbb)

	fr.builder.SetInsertPointAtEnd(contbb)
	mapiterbufelem0 := fr.builder.CreateLoad(mapiterbufelem0ptr, "")
	okbit := fr.builder.CreateIsNotNull(mapiterbufelem0, "")
	ok := fr.builder.CreateZExt(okbit, llvm.Int8Type(), "")

	loadbb := llvm.AddBasicBlock(fr.function, "")
	cont2bb := llvm.AddBasicBlock(fr.function, "")
	fr.builder.CreateCondBr(okbit, loadbb, cont2bb)

	fr.builder.SetInsertPointAtEnd(loadbb)
	fr.runtime.mapiter2.call(fr, mapiterbufelem0ptr, keyptr, valptr)
	loadbb = fr.builder.GetInsertBlock()
	loadedkey := fr.builder.CreateLoad(keybuf, "")
	loadedval := fr.builder.CreateLoad(valbuf, "")
	fr.builder.CreateBr(cont2bb)

	fr.builder.SetInsertPointAtEnd(cont2bb)
	k := fr.builder.CreatePHI(klltyp, "")
	k.AddIncoming(
		[]llvm.Value{llvm.ConstNull(klltyp), loadedkey},
		[]llvm.BasicBlock{contbb, loadbb},
	)
	v := fr.builder.CreatePHI(vlltyp, "")
	v.AddIncoming(
		[]llvm.Value{llvm.ConstNull(vlltyp), loadedval},
		[]llvm.BasicBlock{contbb, loadbb},
	)

	return []*govalue{newValue(ok, types.Typ[types.Bool]), newValue(k, ktyp), newValue(v, vtyp)}
}