Exemple #1
0
func (d subrangeDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		llvm.ConstInt(llvm.Int64Type(), uint64(d.low), true),
		llvm.ConstInt(llvm.Int64Type(), uint64(d.high), true),
	})
}
Exemple #2
0
func (c *compiler) VisitLen(expr *ast.CallExpr) Value {
	value := c.VisitExpr(expr.Args[0])
	typ := value.Type()
	if name, ok := typ.Underlying().(*types.Named); ok {
		typ = name.Underlying()
	}
	var lenvalue llvm.Value
	switch typ := typ.Underlying().(type) {
	case *types.Pointer:
		atyp := typ.Elem().Underlying().(*types.Array)
		lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
	case *types.Slice:
		sliceval := value.LLVMValue()
		lenvalue = c.builder.CreateExtractValue(sliceval, 1, "")
	case *types.Map:
		mapval := value.LLVMValue()
		f := c.NamedFunction("runtime.maplen", "func f(m uintptr) int")
		lenvalue = c.builder.CreateCall(f, []llvm.Value{mapval}, "")
	case *types.Array:
		lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
	case *types.Basic:
		if isString(typ) {
			value := value.(*LLVMValue)
			lenvalue = c.builder.CreateExtractValue(value.LLVMValue(), 1, "")
		}
	case *types.Chan:
		panic("len(chan) unimplemented")
	}
	return c.NewValue(lenvalue, types.Typ[types.Int])
}
Exemple #3
0
// makeMapLiteral makes a map with the specified keys and values.
func (c *compiler) makeMapLiteral(typ types.Type, keys, values []Value) *LLVMValue {
	var count, keysptr, valuesptr llvm.Value
	dyntyp := c.types.ToRuntime(typ)
	dyntyp = c.builder.CreatePtrToInt(dyntyp, c.target.IntPtrType(), "")
	if len(keys) == 0 {
		count = llvm.ConstNull(c.types.inttype)
		keysptr = llvm.ConstNull(c.target.IntPtrType())
		valuesptr = keysptr
	} else {
		maptyp := typ.Underlying().(*types.Map)
		keytyp := maptyp.Key()
		valtyp := maptyp.Elem()
		count = llvm.ConstInt(c.types.inttype, uint64(len(keys)), false)
		keysptr = c.builder.CreateArrayAlloca(c.types.ToLLVM(keytyp), count, "")
		valuesptr = c.builder.CreateArrayAlloca(c.types.ToLLVM(valtyp), count, "")
		for i := range keys {
			gepindices := []llvm.Value{llvm.ConstInt(c.types.inttype, uint64(i), false)}
			key := keys[i].Convert(keytyp).LLVMValue()
			ptr := c.builder.CreateGEP(keysptr, gepindices, "")
			c.builder.CreateStore(key, ptr)
			value := values[i].Convert(valtyp).LLVMValue()
			ptr = c.builder.CreateGEP(valuesptr, gepindices, "")
			c.builder.CreateStore(value, ptr)
		}
		keysptr = c.builder.CreatePtrToInt(keysptr, c.target.IntPtrType(), "")
		valuesptr = c.builder.CreatePtrToInt(valuesptr, c.target.IntPtrType(), "")
	}
	f := c.NamedFunction("runtime.makemap", "func(t uintptr, n int, keys, values uintptr) uintptr")
	mapval := c.builder.CreateCall(f, []llvm.Value{dyntyp, count, keysptr, valuesptr}, "")
	return c.NewValue(mapval, typ)
}
Exemple #4
0
// interfaceMethod returns a function pointer for the specified
// interface and method pair.
func (c *compiler) interfaceMethod(iface *LLVMValue, method *types.Func) *LLVMValue {
	lliface := iface.LLVMValue()
	llitab := c.builder.CreateExtractValue(lliface, 0, "")
	llvalue := c.builder.CreateExtractValue(lliface, 1, "")
	sig := method.Type().(*types.Signature)
	methodset := c.types.MethodSet(sig.Recv().Type())
	// TODO(axw) cache ordered method index
	var index int
	for i := 0; i < methodset.Len(); i++ {
		if methodset.At(i).Obj() == method {
			index = i
			break
		}
	}
	llitab = c.builder.CreateBitCast(llitab, llvm.PointerType(c.runtime.itab.llvm, 0), "")
	llifn := c.builder.CreateGEP(llitab, []llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), 0, false),
		llvm.ConstInt(llvm.Int32Type(), 5, false), // index of itab.fun
	}, "")
	_ = index
	llifn = c.builder.CreateGEP(llifn, []llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(index), false),
	}, "")
	llifn = c.builder.CreateLoad(llifn, "")
	// Strip receiver.
	sig = types.NewSignature(nil, nil, sig.Params(), sig.Results(), sig.Variadic())
	llfn := llvm.Undef(c.types.ToLLVM(sig))
	llifn = c.builder.CreateIntToPtr(llifn, llfn.Type().StructElementTypes()[0], "")
	llfn = c.builder.CreateInsertValue(llfn, llifn, 0, "")
	llfn = c.builder.CreateInsertValue(llfn, llvalue, 1, "")
	return c.NewValue(llfn, sig)
}
Exemple #5
0
func (c *compiler) defineMemcpyFunction(fn llvm.Value) {
	entry := llvm.AddBasicBlock(fn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	dst, src, size := fn.Param(0), fn.Param(1), fn.Param(2)

	pint8 := llvm.PointerType(llvm.Int8Type(), 0)
	dst = c.builder.CreateIntToPtr(dst, pint8, "")
	src = c.builder.CreateIntToPtr(src, pint8, "")

	sizeType := size.Type()
	sizeBits := sizeType.IntTypeWidth()
	memcpyName := "llvm.memcpy.p0i8.p0i8.i" + strconv.Itoa(sizeBits)
	memcpy := c.module.NamedFunction(memcpyName)
	if memcpy.IsNil() {
		paramtypes := []llvm.Type{
			pint8, pint8, size.Type(), llvm.Int32Type(), llvm.Int1Type()}
		memcpyType := llvm.FunctionType(llvm.VoidType(), paramtypes, false)
		memcpy = llvm.AddFunction(c.module.Module, memcpyName, memcpyType)
	}

	args := []llvm.Value{
		dst, src, size,
		llvm.ConstInt(llvm.Int32Type(), 1, false), // single byte alignment
		llvm.ConstInt(llvm.Int1Type(), 0, false),  // not volatile
	}
	c.builder.CreateCall(memcpy, args, "")
	c.builder.CreateRetVoid()
}
Exemple #6
0
func (d *debugInfo) setLocation(b llvm.Builder, pos token.Pos) {
	position := d.Fset.Position(pos)
	b.SetCurrentDebugLocation(llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(position.Line), true),
		llvm.ConstInt(llvm.Int32Type(), uint64(position.Column), true),
		d.MDNode(d.context()),
		llvm.Value{},
	}))
}
Exemple #7
0
func (d *BlockDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		info.mdFileNode(d.File),
		info.MDNode(d.Context),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Column), false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Id), false),
	})
}
Exemple #8
0
func (d *LocalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		info.mdFileNode(d.File),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line)|(uint64(d.Argument)<<24), false),
		info.MDNode(d.Type),
		llvm.ConstNull(llvm.Int32Type()), // flags
		llvm.ConstNull(llvm.Int32Type()), // optional reference to inline location
	})
}
Exemple #9
0
func (c *compiler) VisitAppend(expr *ast.CallExpr) Value {
	s := c.VisitExpr(expr.Args[0])
	elemtyp := s.Type().Underlying().(*types.Slice).Elem()
	if len(expr.Args) == 1 {
		return s
	} else if expr.Ellipsis.IsValid() {
		c.convertUntyped(expr.Args[1], s.Type())
	} else {
		for _, arg := range expr.Args[1:] {
			c.convertUntyped(arg, elemtyp)
		}
	}

	sliceappend := c.NamedFunction("runtime.sliceappend", "func(t uintptr, dst, src slice) slice")
	i8slice := sliceappend.Type().ElementType().ReturnType()
	i8ptr := c.types.ToLLVM(types.NewPointer(types.Typ[types.Int8]))

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

	var b llvm.Value
	if expr.Ellipsis.IsValid() {
		// Pass the provided slice straight through. If it's a string,
		// convert it to a []byte first.
		elem := c.VisitExpr(expr.Args[1]).Convert(s.Type())
		b = c.coerceSlice(elem.LLVMValue(), i8slice)
	} else {
		// Construct a fresh []int8 for the temporary slice.
		n := llvm.ConstInt(c.types.inttype, uint64(len(expr.Args)-1), false)
		mem := c.builder.CreateArrayAlloca(c.types.ToLLVM(elemtyp), n, "")
		for i, arg := range expr.Args[1:] {
			elem := c.VisitExpr(arg).Convert(elemtyp)
			indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
			ptr := c.builder.CreateGEP(mem, indices, "")
			c.builder.CreateStore(elem.LLVMValue(), ptr)
		}
		b = llvm.Undef(i8slice)
		b = c.builder.CreateInsertValue(b, c.builder.CreateBitCast(mem, i8ptr, ""), 0, "")
		b = c.builder.CreateInsertValue(b, n, 1, "")
		b = c.builder.CreateInsertValue(b, n, 2, "")
	}

	// Call runtime function, then coerce the result.
	runtimeTyp := c.types.ToRuntime(s.Type())
	runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
	args := []llvm.Value{runtimeTyp, a, b}
	result := c.builder.CreateCall(sliceappend, args, "")
	return c.NewValue(c.coerceSlice(result, sliceTyp), s.Type())
}
Exemple #10
0
func (d *GlobalVariableDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		llvm.ConstNull(llvm.Int32Type()),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		llvm.MDString(d.DisplayName),
		llvm.MDNode(nil),
		info.mdFileNode(d.File),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		info.MDNode(d.Type),
		constInt1(d.Local),
		constInt1(!d.External),
		d.Value})
}
Exemple #11
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])

	sliceappend := c.NamedFunction("runtime.sliceappend", "func f(t uintptr, dst, src slice) slice")
	i8slice := sliceappend.Type().ElementType().ReturnType()
	i8ptr := c.types.ToLLVM(&types.Pointer{Base: types.Int8})

	// 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, c.target.IntPtrType(), "")
	args := []llvm.Value{runtimeTyp, a, b}
	result := c.builder.CreateCall(sliceappend, args, "")
	return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), s.Type())
}
Exemple #12
0
func (c *compiler) callCap(arg *LLVMValue) *LLVMValue {
	var v llvm.Value
	switch typ := arg.Type().Underlying().(type) {
	case *types.Array:
		v = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
	case *types.Pointer:
		atyp := typ.Elem().Underlying().(*types.Array)
		v = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
	case *types.Slice:
		v = c.builder.CreateExtractValue(arg.LLVMValue(), 2, "")
	case *types.Chan:
		f := c.runtime.chancap.LLVMValue()
		v = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
	}
	return c.NewValue(v, types.Typ[types.Int])
}
Exemple #13
0
// makeSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
	llvmelttyp := c.types.ToLLVM(elttyp)
	mem := c.builder.CreateArrayMalloc(llvmelttyp, n, "")
	for i, value := range v {
		indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.Slice{Elt: elttyp}
	struct_ := llvm.Undef(c.types.ToLLVM(&slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
	return struct_
}
Exemple #14
0
func reorderGlobalConstructors(m llvm.Module) error {
	ctors := m.NamedGlobal("llvm.global_ctors")
	if ctors.IsNil() {
		// No global constructors.
		return nil
	}

	init := ctors.Initializer()
	arraylength := init.Type().ArrayLength()
	zeroindex := []uint32{0}

	// The constructors are ordered within each package, but the packages
	// are in reverse order. We must go backwards through the constructors,
	// reassigning priorities.
	ceiling, npackagectors := -1, -1
	for i := arraylength - 1; i >= 0; i-- {
		indices := []uint32{uint32(i)}
		ctor := llvm.ConstExtractValue(init, indices)
		priority := int(llvm.ConstExtractValue(ctor, zeroindex).ZExtValue())
		if npackagectors == -1 {
			ceiling = arraylength - (i + 1) + priority
			npackagectors = priority
		}
		newpriority := ceiling - (npackagectors - priority)
		newpriorityvalue := llvm.ConstInt(llvm.Int32Type(), uint64(newpriority), false)
		ctor = llvm.ConstInsertValue(ctor, newpriorityvalue, zeroindex)
		if priority == 1 {
			npackagectors = -1
		}
		init = llvm.ConstInsertValue(init, ctor, indices)
	}
	ctors.SetInitializer(init)
	return nil
}
Exemple #15
0
func (c *compiler) makeSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(llvm.Int32Type(), uint64(len(v)), false)
	mem := c.builder.CreateArrayMalloc(c.types.ToLLVM(elttyp), n, "")
	for i, value := range v {
		indices := []llvm.Value{
			llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.Slice{Elt: elttyp}
	struct_ := c.builder.CreateAlloca(c.types.ToLLVM(&slicetyp), "")
	c.builder.CreateStore(mem, c.builder.CreateStructGEP(struct_, 0, ""))
	c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 1, ""))
	c.builder.CreateStore(n, c.builder.CreateStructGEP(struct_, 2, ""))
	return c.builder.CreateLoad(struct_, "")
}
Exemple #16
0
func (c *compiler) slice(x, low, high *LLVMValue) *LLVMValue {
	if low != nil {
		low = low.Convert(types.Typ[types.Int]).(*LLVMValue)
	} else {
		low = c.NewValue(llvm.ConstNull(c.types.inttype), types.Typ[types.Int])
	}

	if high != nil {
		high = high.Convert(types.Typ[types.Int]).(*LLVMValue)
	} else {
		// all bits set is -1
		high = c.NewValue(llvm.ConstAllOnes(c.types.inttype), types.Typ[types.Int])
	}

	switch typ := x.Type().Underlying().(type) {
	case *types.Pointer: // *array
		sliceslice := c.runtime.sliceslice.LLVMValue()
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := llvm.Undef(i8slice) // temporary slice
		arraytyp := typ.Elem().Underlying().(*types.Array)
		arrayptr := x.LLVMValue()
		arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "")
		arraylen := llvm.ConstInt(c.llvmtypes.inttype, uint64(arraytyp.Len()), false)
		sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "")
		sliceTyp := types.NewSlice(arraytyp.Elem())
		runtimeTyp := c.types.ToRuntime(sliceTyp)
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low.LLVMValue(), high.LLVMValue()}
		result := c.builder.CreateCall(sliceslice, args, "")
		llvmSliceTyp := c.types.ToLLVM(sliceTyp)
		return c.NewValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp)
	case *types.Slice:
		sliceslice := c.runtime.sliceslice.LLVMValue()
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := x.LLVMValue()
		sliceTyp := sliceValue.Type()
		sliceValue = c.coerceSlice(sliceValue, i8slice)
		runtimeTyp := c.types.ToRuntime(x.Type())
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low.LLVMValue(), high.LLVMValue()}
		result := c.builder.CreateCall(sliceslice, args, "")
		return c.NewValue(c.coerceSlice(result, sliceTyp), x.Type())
	case *types.Basic:
		stringslice := c.runtime.stringslice.LLVMValue()
		llv := x.LLVMValue()
		args := []llvm.Value{
			c.coerceString(llv, stringslice.Type().ElementType().ParamTypes()[0]),
			low.LLVMValue(),
			high.LLVMValue(),
		}
		result := c.builder.CreateCall(stringslice, args, "")
		return c.NewValue(c.coerceString(result, llv.Type()), x.Type())
	default:
		panic("unimplemented")
	}
	panic("unreachable")
}
Exemple #17
0
func (d *CompileUnitDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Tag())+llvm.LLVMDebugVersion, false),
		d.Path.path(),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Language), false),
		llvm.MDString(d.Producer),
		constInt1(d.Optimized),
		llvm.MDString(d.CompilerFlags),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Runtime), false),
		d.mdNodeList(info, d.EnumTypes),
		d.mdNodeList(info, d.RetainedTypes),
		d.mdNodeList(info, d.Subprograms),
		d.mdNodeList(info, d.GlobalVariables),
		d.mdNodeList(info, nil), // List of imported entities
		llvm.MDString(""),       // Split debug filename
	})
}
Exemple #18
0
func (c *compiler) VisitSliceExpr(expr *ast.SliceExpr) Value {
	// expr.X, expr.Low, expr.High
	value := c.VisitExpr(expr.X)
	var low, high llvm.Value
	if expr.Low != nil {
		low = c.VisitExpr(expr.Low).Convert(types.Int32).LLVMValue()
	} else {
		low = llvm.ConstNull(llvm.Int32Type())
	}
	if expr.High != nil {
		high = c.VisitExpr(expr.High).Convert(types.Int32).LLVMValue()
	} else {
		high = llvm.ConstAllOnes(llvm.Int32Type()) // -1
	}

	if _, ok := types.Underlying(value.Type()).(*types.Pointer); ok {
		value = value.(*LLVMValue).makePointee()
	}

	switch typ := types.Underlying(value.Type()).(type) {
	case *types.Array:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := llvm.Undef(i8slice) // temporary slice
		arrayptr := value.(*LLVMValue).pointer.LLVMValue()
		arrayptr = c.builder.CreateBitCast(arrayptr, i8slice.StructElementTypes()[0], "")
		arraylen := llvm.ConstInt(llvm.Int32Type(), typ.Len, false)
		sliceValue = c.builder.CreateInsertValue(sliceValue, arrayptr, 0, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 1, "")
		sliceValue = c.builder.CreateInsertValue(sliceValue, arraylen, 2, "")
		sliceTyp := &types.Slice{Elt: typ.Elt}
		runtimeTyp := c.types.ToRuntime(sliceTyp)
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		llvmSliceTyp := c.types.ToLLVM(sliceTyp)
		return c.NewLLVMValue(c.coerceSlice(result, llvmSliceTyp), sliceTyp)
	case *types.Slice:
		sliceslice := c.NamedFunction("runtime.sliceslice", "func f(t uintptr, s slice, low, high int32) slice")
		i8slice := sliceslice.Type().ElementType().ReturnType()
		sliceValue := value.LLVMValue()
		sliceTyp := sliceValue.Type()
		sliceValue = c.coerceSlice(sliceValue, i8slice)
		runtimeTyp := c.types.ToRuntime(value.Type())
		runtimeTyp = c.builder.CreatePtrToInt(runtimeTyp, c.target.IntPtrType(), "")
		args := []llvm.Value{runtimeTyp, sliceValue, low, high}
		result := c.builder.CreateCall(sliceslice, args, "")
		return c.NewLLVMValue(c.coerceSlice(result, sliceTyp), value.Type())
	case *types.Name: // String
		stringslice := c.NamedFunction("runtime.stringslice", "func f(a string, low, high int32) string")
		args := []llvm.Value{value.LLVMValue(), low, high}
		result := c.builder.CreateCall(stringslice, args, "")
		return c.NewLLVMValue(result, value.Type())
	default:
		panic("unimplemented")
	}
	panic("unreachable")
}
Exemple #19
0
// makeLiteralSlice allocates a new slice, storing in it the provided elements.
func (c *compiler) makeLiteralSlice(v []llvm.Value, elttyp types.Type) llvm.Value {
	n := llvm.ConstInt(c.types.inttype, uint64(len(v)), false)
	eltType := c.types.ToLLVM(elttyp)
	arrayType := llvm.ArrayType(eltType, len(v))
	mem := c.createMalloc(llvm.SizeOf(arrayType))
	mem = c.builder.CreateIntToPtr(mem, llvm.PointerType(eltType, 0), "")
	for i, value := range v {
		indices := []llvm.Value{llvm.ConstInt(llvm.Int32Type(), uint64(i), false)}
		ep := c.builder.CreateGEP(mem, indices, "")
		c.builder.CreateStore(value, ep)
	}
	slicetyp := types.NewSlice(elttyp)
	struct_ := llvm.Undef(c.types.ToLLVM(slicetyp))
	struct_ = c.builder.CreateInsertValue(struct_, mem, 0, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 1, "")
	struct_ = c.builder.CreateInsertValue(struct_, n, 2, "")
	return struct_
}
Exemple #20
0
func (c *compiler) defineMemsetFunction(fn llvm.Value) {
	entry := llvm.AddBasicBlock(fn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	dst, fill, size := fn.Param(0), fn.Param(1), fn.Param(2)
	sizeType := size.Type()
	sizeBits := sizeType.IntTypeWidth()
	memsetName := "llvm.memset.p0i8.i" + strconv.Itoa(sizeBits)
	memset := c.NamedFunction(memsetName, "func f(dst *int8, fill byte, size uintptr, align int32, volatile bool)")
	pint8 := memset.Type().ElementType().ParamTypes()[0]
	dst = c.builder.CreateIntToPtr(dst, pint8, "")
	args := []llvm.Value{
		dst, fill, size,
		llvm.ConstInt(llvm.Int32Type(), 1, false), // single byte alignment
		llvm.ConstInt(llvm.Int1Type(), 0, false),  // not volatile
	}
	c.builder.CreateCall(memset, args, "")
	c.builder.CreateRetVoid()
}
Exemple #21
0
func (d FileDescriptor) mdNode(info *DebugInfo) llvm.Value {
	if d == "" {
		return llvm.Value{}
	}
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false),
		d.path(),
	})
}
Exemple #22
0
// globalStringPtr returns a *string with the specified value.
func (tm *TypeMap) globalStringPtr(value string) llvm.Value {
	strval := llvm.ConstString(value, false)
	strglobal := llvm.AddGlobal(tm.module, strval.Type(), "")
	strglobal.SetInitializer(strval)
	strglobal = llvm.ConstBitCast(strglobal, llvm.PointerType(llvm.Int8Type(), 0))
	strlen := llvm.ConstInt(tm.inttype, uint64(len(value)), false)
	str := llvm.ConstStruct([]llvm.Value{strglobal, strlen}, false)
	g := llvm.AddGlobal(tm.module, str.Type(), "")
	g.SetInitializer(str)
	return g
}
Exemple #23
0
func (tm *TypeMap) arrayRuntimeType(a *types.Array) (global, ptr llvm.Value) {
	commonType := tm.makeCommonType(a, reflect.Array)
	elemRuntimeType := tm.ToRuntime(a.Elt)
	sliceRuntimeType := tm.ToRuntime(&types.Slice{Elt: a.Elt})
	uintptrlen := llvm.ConstInt(tm.target.IntPtrType(), uint64(a.Len), false)
	arrayType := llvm.ConstNull(tm.runtimeArrayType)
	arrayType = llvm.ConstInsertValue(arrayType, commonType, []uint32{0})
	arrayType = llvm.ConstInsertValue(arrayType, elemRuntimeType, []uint32{1})
	arrayType = llvm.ConstInsertValue(arrayType, sliceRuntimeType, []uint32{2})
	arrayType = llvm.ConstInsertValue(arrayType, uintptrlen, []uint32{3})
	return tm.makeRuntimeTypeGlobal(arrayType)
}
Exemple #24
0
func (tm *TypeMap) arrayRuntimeType(a *types.Array) (global, ptr llvm.Value) {
	rtype := tm.makeRtype(a, reflect.Array)
	elemRuntimeType := tm.ToRuntime(a.Elem())
	sliceRuntimeType := tm.ToRuntime(types.NewSlice(a.Elem()))
	uintptrlen := llvm.ConstInt(tm.target.IntPtrType(), uint64(a.Len()), false)
	arrayType := llvm.ConstNull(tm.runtime.arrayType.llvm)
	arrayType = llvm.ConstInsertValue(arrayType, rtype, []uint32{0})
	arrayType = llvm.ConstInsertValue(arrayType, elemRuntimeType, []uint32{1})
	arrayType = llvm.ConstInsertValue(arrayType, sliceRuntimeType, []uint32{2})
	arrayType = llvm.ConstInsertValue(arrayType, uintptrlen, []uint32{3})
	return tm.makeRuntimeTypeGlobal(arrayType, typeString(a))
}
Exemple #25
0
func (c *compiler) VisitCap(expr *ast.CallExpr) Value {
	value := c.VisitExpr(expr.Args[0])
	typ := value.Type()
	if name, ok := typ.Underlying().(*types.Named); ok {
		typ = name.Underlying()
	}
	var capvalue llvm.Value
	switch typ := typ.Underlying().(type) {
	case *types.Pointer:
		atyp := typ.Elem().Underlying().(*types.Array)
		capvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
	case *types.Array:
		capvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
	case *types.Slice:
		sliceval := value.LLVMValue()
		capvalue = c.builder.CreateExtractValue(sliceval, 2, "")
	case *types.Chan:
		panic("cap(chan) unimplemented")
	}
	return c.NewValue(capvalue, types.Typ[types.Int])
}
Exemple #26
0
func (c *compiler) visitRecover() *LLVMValue {
	// Functions that call recover must not be inlined, or we
	// can't tell whether the recover call is valid.
	fn := c.functions.top()
	fnptr := c.builder.CreateExtractValue(fn.value, 0, "")
	fnptr.AddFunctionAttr(llvm.NoInlineAttribute)

	// We need to tell runtime.recover if it's being called from
	// an indirectly invoked deferred function or not.
	var indirect llvm.Value
	sig := fn.Type().(*types.Signature)
	if sig.Params().Len() == 0 {
		indirect = llvm.ConstInt(llvm.Int32Type(), 0, false)
	} else {
		indirect = llvm.ConstInt(llvm.Int32Type(), 1, false)
	}
	eface := &types.Interface{}
	err := c.builder.CreateAlloca(c.types.ToLLVM(eface), "")
	r := c.NamedFunction("runtime.recover", "func f(int32, *interface{})")
	c.builder.CreateCall(r, []llvm.Value{indirect, err}, "")
	return c.NewValue(c.builder.CreateLoad(err, ""), eface)
}
Exemple #27
0
func (c *compiler) callLen(arg *LLVMValue) *LLVMValue {
	var lenvalue llvm.Value
	switch typ := arg.Type().Underlying().(type) {
	case *types.Array:
		lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(typ.Len()), false)
	case *types.Pointer:
		atyp := typ.Elem().Underlying().(*types.Array)
		lenvalue = llvm.ConstInt(c.llvmtypes.inttype, uint64(atyp.Len()), false)
	case *types.Slice:
		lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
	case *types.Map:
		f := c.runtime.maplen.LLVMValue()
		lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
	case *types.Basic:
		if isString(typ) {
			lenvalue = c.builder.CreateExtractValue(arg.LLVMValue(), 1, "")
		}
	case *types.Chan:
		f := c.runtime.chanlen.LLVMValue()
		lenvalue = c.builder.CreateCall(f, []llvm.Value{arg.LLVMValue()}, "")
	}
	return c.NewValue(lenvalue, types.Typ[types.Int])
}
Exemple #28
0
func (d *BasicTypeDescriptor) mdNode(info *DebugInfo) llvm.Value {
	return llvm.MDNode([]llvm.Value{
		llvm.ConstInt(llvm.Int32Type(), llvm.LLVMDebugVersion+uint64(d.Tag()), false),
		FileDescriptor(d.File).path(),
		info.MDNode(d.Context),
		llvm.MDString(d.Name),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Line), false),
		llvm.ConstInt(llvm.Int64Type(), d.Size, false),
		llvm.ConstInt(llvm.Int64Type(), d.Alignment, false),
		llvm.ConstInt(llvm.Int64Type(), d.Offset, false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.Flags), false),
		llvm.ConstInt(llvm.Int32Type(), uint64(d.TypeEncoding), false)})
}
Exemple #29
0
func (tm *TypeMap) funcRuntimeType(f *types.Signature) (global, ptr llvm.Value) {
	rtype := tm.makeRtype(f, reflect.Func)
	funcType := llvm.ConstNull(tm.runtimeFuncType)
	funcType = llvm.ConstInsertValue(funcType, rtype, []uint32{0})
	// dotdotdot
	if f.IsVariadic() {
		variadic := llvm.ConstInt(llvm.Int1Type(), 1, false)
		funcType = llvm.ConstInsertValue(funcType, variadic, []uint32{1})
	}
	// TODO in
	//funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{2})
	// TODO out
	//funcType = llvm.ConstInsertValue(funcType, tm.ToRuntime(p.Elt()), []uint32{3})
	return tm.makeRuntimeTypeGlobal(funcType)
}
Exemple #30
0
func (tm *TypeMap) makeRtype(t types.Type, k reflect.Kind) llvm.Value {
	// Not sure if there's an easier way to do this, but if you just
	// use ConstStruct, you end up getting a different llvm.Type.
	typ := llvm.ConstNull(tm.runtime.rtype.llvm)
	elementTypes := tm.runtime.rtype.llvm.StructElementTypes()

	// Size.
	size := llvm.ConstInt(elementTypes[0], uint64(tm.Sizeof(t)), false)
	typ = llvm.ConstInsertValue(typ, size, []uint32{0})

	// TODO hash
	// TODO padding

	// Alignment.
	align := llvm.ConstInt(llvm.Int8Type(), uint64(tm.Alignof(t)), false)
	typ = llvm.ConstInsertValue(typ, align, []uint32{3}) // var
	typ = llvm.ConstInsertValue(typ, align, []uint32{4}) // field

	// Kind.
	kind := llvm.ConstInt(llvm.Int8Type(), uint64(k), false)
	typ = llvm.ConstInsertValue(typ, kind, []uint32{5})

	// Algorithm table.
	alg := tm.makeAlgorithmTable(t)
	algptr := llvm.AddGlobal(tm.module, alg.Type(), "")
	algptr.SetInitializer(alg)
	algptr = llvm.ConstBitCast(algptr, elementTypes[6])
	typ = llvm.ConstInsertValue(typ, algptr, []uint32{6})

	// String representation.
	stringrep := tm.globalStringPtr(t.String())
	typ = llvm.ConstInsertValue(typ, stringrep, []uint32{8})

	// TODO gc
	return typ
}