Exemple #1
0
// coerceSlice takes a slice of one element type and coerces it to a
// slice of another.
func (c *compiler) coerceSlice(src llvm.Value, dsttyp llvm.Type) llvm.Value {
	dst := llvm.Undef(dsttyp)
	srcmem := c.builder.CreateExtractValue(src, 0, "")
	srclen := c.builder.CreateExtractValue(src, 1, "")
	srccap := c.builder.CreateExtractValue(src, 2, "")
	dstmemtyp := dsttyp.StructElementTypes()[0]
	dstmem := c.builder.CreateBitCast(srcmem, dstmemtyp, "")
	dst = c.builder.CreateInsertValue(dst, dstmem, 0, "")
	dst = c.builder.CreateInsertValue(dst, srclen, 1, "")
	dst = c.builder.CreateInsertValue(dst, srccap, 2, "")
	return dst
}
Exemple #2
0
func (tm *TypeMap) makeSlice(values []llvm.Value, slicetyp llvm.Type) llvm.Value {
	ptrtyp := slicetyp.StructElementTypes()[0]
	var globalptr llvm.Value
	if len(values) > 0 {
		array := llvm.ConstArray(ptrtyp.ElementType(), values)
		globalptr = llvm.AddGlobal(tm.module, array.Type(), "")
		globalptr.SetInitializer(array)
		globalptr = llvm.ConstBitCast(globalptr, ptrtyp)
	} else {
		globalptr = llvm.ConstNull(ptrtyp)
	}
	len_ := llvm.ConstInt(tm.inttype, uint64(len(values)), false)
	slice := llvm.ConstNull(slicetyp)
	slice = llvm.ConstInsertValue(slice, globalptr, []uint32{0})
	slice = llvm.ConstInsertValue(slice, len_, []uint32{1})
	slice = llvm.ConstInsertValue(slice, len_, []uint32{2})
	return slice
}
Exemple #3
0
func (c *compiler) VisitAppend(expr *ast.CallExpr) Value {
	// TODO handle ellpisis arg
	s := c.VisitExpr(expr.Args[0])
	elem := c.VisitExpr(expr.Args[1])

	appendName := "runtime.sliceappend"
	appendFun := c.module.NamedFunction(appendName)
	uintptrTyp := c.target.IntPtrType()
	var i8slice llvm.Type
	if appendFun.IsNil() {
		i8slice = c.types.ToLLVM(&types.Slice{Elt: types.Int8})
		args := []llvm.Type{uintptrTyp, i8slice, i8slice}
		appendFunTyp := llvm.FunctionType(i8slice, args, false)
		appendFun = llvm.AddFunction(c.module.Module, appendName, appendFunTyp)
	} else {
		i8slice = appendFun.Type().ReturnType()
	}
	i8ptr := i8slice.StructElementTypes()[0]

	// Coerce first argument into an []int8.
	a_ := s.LLVMValue()
	sliceTyp := a_.Type()
	a := c.coerceSlice(a_, i8slice)

	// Construct a fresh []int8 for the temporary slice.
	b_ := elem.LLVMValue()
	one := llvm.ConstInt(llvm.Int32Type(), 1, false)
	mem := c.builder.CreateAlloca(elem.LLVMValue().Type(), "")
	c.builder.CreateStore(b_, mem)
	b := llvm.Undef(i8slice)
	b = c.builder.CreateInsertValue(b, c.builder.CreateBitCast(mem, i8ptr, ""), 0, "")
	b = c.builder.CreateInsertValue(b, one, 1, "")
	b = c.builder.CreateInsertValue(b, one, 2, "")

	// Call runtime function, then coerce the result.
	runtimeTyp := c.types.ToRuntime(s.Type())
	runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, uintptrTyp, "")
	args := []llvm.Value{runtimeTyp, a, b}
	result := c.builder.CreateCall(appendFun, args, "")
	return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), s.Type())
}