Пример #1
0
func (tm *TypeMap) makeRuntimeTypeGlobal(v llvm.Value, name string) (global, ptr llvm.Value) {
	global = llvm.AddGlobal(tm.module, v.Type(), typeSymbol(name))
	global.SetInitializer(v)
	global.SetLinkage(llvm.LinkOnceAnyLinkage)
	ptr = llvm.ConstBitCast(global, llvm.PointerType(tm.runtime.rtype.llvm, 0))
	return global, ptr
}
Пример #2
0
func (tm *TypeMap) makeAlgorithmTable(t types.Type) llvm.Value {
	// TODO set these to actual functions.
	hashAlg := llvm.ConstNull(llvm.PointerType(tm.hashAlgFunctionType, 0))
	printAlg := llvm.ConstNull(llvm.PointerType(tm.printAlgFunctionType, 0))
	copyAlg := llvm.ConstNull(llvm.PointerType(tm.copyAlgFunctionType, 0))

	const eqalgsig = "func(uintptr, unsafe.Pointer, unsafe.Pointer) bool"
	var equalAlg llvm.Value
	switch t := t.(type) {
	case *types.Basic:
		switch t.Kind() {
		case types.String:
			equalAlg = tm.functions.NamedFunction("runtime.streqalg", eqalgsig)
		case types.Float32:
			equalAlg = tm.functions.NamedFunction("runtime.f32eqalg", eqalgsig)
		case types.Float64:
			equalAlg = tm.functions.NamedFunction("runtime.f64eqalg", eqalgsig)
		case types.Complex64:
			equalAlg = tm.functions.NamedFunction("runtime.c64eqalg", eqalgsig)
		case types.Complex128:
			equalAlg = tm.functions.NamedFunction("runtime.c128eqalg", eqalgsig)
		}
	}
	if equalAlg.IsNil() {
		equalAlg = tm.functions.NamedFunction("runtime.memequal", eqalgsig)
	}
	elems := []llvm.Value{hashAlg, equalAlg, printAlg, copyAlg}
	return llvm.ConstStruct(elems, false)
}
Пример #3
0
func (c *compiler) createMalloc(size llvm.Value) llvm.Value {
	malloc := c.NamedFunction("runtime.malloc", "func f(uintptr) unsafe.Pointer")
	if size.Type().IntTypeWidth() > c.target.IntPtrType().IntTypeWidth() {
		size = c.builder.CreateTrunc(size, c.target.IntPtrType(), "")
	}
	return c.builder.CreateCall(malloc, []llvm.Value{size}, "")
}
Пример #4
0
func (c *compiler) defineFreeFunction(fn llvm.Value) {
	entry := llvm.AddBasicBlock(fn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	ptr := fn.FirstParam()
	ptrtyp := llvm.PointerType(llvm.Int8Type(), 0)
	c.builder.CreateFree(c.builder.CreateIntToPtr(ptr, ptrtyp, ""))
	c.builder.CreateRetVoid()
}
Пример #5
0
// Debug intrinsic collectors.
func createGlobalVariableMetadata(global llvm.Value) llvm.DebugDescriptor {
	return &llvm.GlobalVariableDescriptor{
		Name:        global.Name(),
		DisplayName: global.Name(),
		//File:
		//Line:
		Type:  int32_debug_type, // FIXME
		Value: global}
}
Пример #6
0
func (c *compiler) createMalloc(size llvm.Value) llvm.Value {
	malloc := c.NamedFunction("runtime.malloc", "func(uintptr) unsafe.Pointer")
	switch n := size.Type().IntTypeWidth() - c.target.IntPtrType().IntTypeWidth(); {
	case n < 0:
		size = c.builder.CreateZExt(size, c.target.IntPtrType(), "")
	case n > 0:
		size = c.builder.CreateTrunc(size, c.target.IntPtrType(), "")
	}
	return c.builder.CreateCall(malloc, []llvm.Value{size}, "")
}
Пример #7
0
func (c *compiler) createMalloc(size llvm.Value) llvm.Value {
	malloc := c.runtime.malloc.LLVMValue()
	switch n := size.Type().IntTypeWidth() - c.target.IntPtrType().IntTypeWidth(); {
	case n < 0:
		size = c.builder.CreateZExt(size, c.target.IntPtrType(), "")
	case n > 0:
		size = c.builder.CreateTrunc(size, c.target.IntPtrType(), "")
	}
	return c.builder.CreateCall(malloc, []llvm.Value{size}, "")
}
Пример #8
0
func (c *compiler) defineMallocFunction(fn llvm.Value) {
	entry := llvm.AddBasicBlock(fn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	size := fn.FirstParam()
	ptr := c.builder.CreateArrayMalloc(llvm.Int8Type(), size, "")
	// XXX memset to zero, or leave that to Go runtime code?
	fn_type := fn.Type().ElementType()
	result := c.builder.CreatePtrToInt(ptr, fn_type.ReturnType(), "")
	c.builder.CreateRet(result)
}
Пример #9
0
func (b *Builder) CreateLoad(v llvm.Value, name string) llvm.Value {
	if v.Type().ElementType() == b.types.ptrstandin {
		// We represent recursive pointer types (T = *T)
		// in LLVM as a pointer to "ptrstdin", where
		// ptrstandin is a unique named struct.
		//
		// Cast the the pointer to a pointer to its own type first.
		v = b.CreateBitCast(v, llvm.PointerType(v.Type(), 0), "")
	}
	return b.Builder.CreateLoad(v, name)
}
Пример #10
0
func (c *compiler) makeFunc(ident *ast.Ident, ftyp *types.Signature) *LLVMValue {
	fname := ident.String()
	if ftyp.Recv() == nil && fname == "init" {
		// Make "init" functions anonymous.
		fname = ""
	} else {
		var pkgname string
		if recv := ftyp.Recv(); recv != nil {
			var recvname string
			switch recvtyp := recv.Type().(type) {
			case *types.Pointer:
				if named, ok := recvtyp.Elem().(*types.Named); ok {
					obj := named.Obj()
					recvname = "*" + obj.Name()
					pkgname = obj.Pkg().Path()
				}
			case *types.Named:
				named := recvtyp
				obj := named.Obj()
				recvname = obj.Name()
				pkgname = obj.Pkg().Path()
			}

			if recvname != "" {
				fname = fmt.Sprintf("%s.%s", recvname, fname)
			} else {
				// If the receiver is an unnamed struct, we're
				// synthesising a method for an unnamed struct
				// type. There's no meaningful name to give the
				// function, so leave it up to LLVM.
				fname = ""
			}
		} else {
			obj := c.typeinfo.Objects[ident]
			pkgname = obj.Pkg().Path()
		}
		if fname != "" {
			fname = pkgname + "." + fname
		}
	}

	// gcimporter may produce multiple AST objects for the same function.
	llvmftyp := c.types.ToLLVM(ftyp)
	var fn llvm.Value
	if fname != "" {
		fn = c.module.Module.NamedFunction(fname)
	}
	if fn.IsNil() {
		llvmfptrtyp := llvmftyp.StructElementTypes()[0].ElementType()
		fn = llvm.AddFunction(c.module.Module, fname, llvmfptrtyp)
	}
	fn = llvm.ConstInsertValue(llvm.ConstNull(llvmftyp), fn, []uint32{0})
	return c.NewValue(fn, ftyp)
}
Пример #11
0
// coerce yields a value of the the type specified, initialised
// to the exact bit pattern as in the specified value.
//
// Note: the specified value must be a non-aggregate, and its type
// and the specified type must have the same size.
func (c *compiler) coerce(v llvm.Value, t llvm.Type) llvm.Value {
	switch t.TypeKind() {
	case llvm.ArrayTypeKind, llvm.StructTypeKind:
		ptr := c.builder.CreateAlloca(t, "")
		ptrv := c.builder.CreateBitCast(ptr, llvm.PointerType(v.Type(), 0), "")
		c.builder.CreateStore(v, ptrv)
		return c.builder.CreateLoad(ptr, "")
	default:
		return c.builder.CreateBitCast(v, t, "")
	}
	panic("unreachable")
}
Пример #12
0
func (c *compiler) newStackVarEx(argument int, stackf *LLVMValue, v types.Object, value llvm.Value, name string) (stackvalue llvm.Value, stackvar *LLVMValue) {
	typ := v.Type()

	// We need to put alloca instructions in the top block or the values
	// displayed when inspecting these variables in a debugger will be
	// completely messed up.
	curBlock := c.builder.GetInsertBlock()
	if p := curBlock.Parent(); !p.IsNil() {
		fb := p.FirstBasicBlock()
		fi := fb.FirstInstruction()
		if !fb.IsNil() && !fi.IsNil() {
			c.builder.SetInsertPointBefore(fi)
		}
	}
	old := c.builder.CurrentDebugLocation()
	c.builder.SetCurrentDebugLocation(llvm.Value{})
	stackvalue = c.builder.CreateAlloca(c.types.ToLLVM(typ), name)

	// For arguments we want to insert the store instruction
	// without debug information to ensure that they are executed
	// (and hence have proper values) before the debugger hits the
	// first line in a function.
	if argument == 0 {
		c.builder.SetCurrentDebugLocation(old)
		c.builder.SetInsertPointAtEnd(curBlock)
	}

	if !value.IsNil() {
		c.builder.CreateStore(value, stackvalue)
	}
	c.builder.SetCurrentDebugLocation(old)
	c.builder.SetInsertPointAtEnd(curBlock)

	ptrvalue := c.NewValue(stackvalue, types.NewPointer(typ))
	stackvar = ptrvalue.makePointee()
	stackvar.stack = stackf
	c.objectdata[v].Value = stackvar

	file := c.fileset.File(v.Pos())
	tag := llvm.DW_TAG_auto_variable
	if argument > 0 {
		tag = llvm.DW_TAG_arg_variable
	}
	ld := llvm.NewLocalVariableDescriptor(tag)
	ld.Argument = uint32(argument)
	ld.Line = uint32(file.Line(v.Pos()))
	ld.Name = name
	ld.File = &llvm.ContextDescriptor{llvm.FileDescriptor(file.Name())}
	ld.Type = c.tollvmDebugDescriptor(typ)
	ld.Context = c.currentDebugContext()
	c.builder.InsertDeclare(c.module.Module, llvm.MDNode([]llvm.Value{stackvalue}), c.debug_info.MDNode(ld))
	return stackvalue, stackvar
}
Пример #13
0
func (b *Builder) CreateStore(v, ptr llvm.Value) {
	if !b.types.ptrstandin.IsNil() {
		vtyp, ptrtyp := v.Type(), ptr.Type()
		if vtyp == ptrtyp {
			// We must be dealing with a pointer to a recursive pointer
			// type, so bitcast the pointer to a pointer to its own
			// type first.
			ptr = b.CreateBitCast(ptr, llvm.PointerType(ptrtyp, 0), "")
		}
	}
	b.Builder.CreateStore(v, ptr)
}
Пример #14
0
func (c *compiler) memsetZero(ptr llvm.Value, size llvm.Value) {
	memset := c.runtime.memset.LLVMValue()
	switch n := size.Type().IntTypeWidth() - c.target.IntPtrType().IntTypeWidth(); {
	case n < 0:
		size = c.builder.CreateZExt(size, c.target.IntPtrType(), "")
	case n > 0:
		size = c.builder.CreateTrunc(size, c.target.IntPtrType(), "")
	}
	ptr = c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
	fill := llvm.ConstNull(llvm.Int8Type())
	c.builder.CreateCall(memset, []llvm.Value{ptr, fill, size}, "")
}
Пример #15
0
func (c *compiler) memsetZero(ptr llvm.Value, size llvm.Value) {
	memset := c.NamedFunction("runtime.memset", "func f(dst unsafe.Pointer, fill byte, size uintptr)")
	switch n := size.Type().IntTypeWidth() - c.target.IntPtrType().IntTypeWidth(); {
	case n < 0:
		size = c.builder.CreateZExt(size, c.target.IntPtrType(), "")
	case n > 0:
		size = c.builder.CreateTrunc(size, c.target.IntPtrType(), "")
	}
	ptr = c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
	fill := llvm.ConstNull(llvm.Int8Type())
	c.builder.CreateCall(memset, []llvm.Value{ptr, fill, size}, "")
}
Пример #16
0
func (b *Builder) CreateStore(v, ptr llvm.Value) {
	if !b.types.ptrstandin.IsNil() {
		vtyp, ptrtyp := v.Type(), ptr.Type()
		if vtyp == ptrtyp || ptrtyp.ElementType() == b.types.ptrstandin {
			// We must be dealing with a pointer to a recursive pointer
			// type, so bitcast the value to the pointer's base, opaque
			// pointer type.
			v = b.CreateBitCast(v, ptrtyp.ElementType(), "")
		}
	}
	b.Builder.CreateStore(v, ptr)
}
Пример #17
0
func (b *Builder) CreateLoad(v llvm.Value, name string) llvm.Value {
	result := b.Builder.CreateLoad(v, name)
	if !b.types.ptrstandin.IsNil() && result.Type() == b.types.ptrstandin {
		// We represent recursive pointer types (T = *T)
		// in LLVM as a pointer to "ptrstdin", where
		// ptrstandin is a pointer to a unique named struct.
		//
		// Cast the result of loading the pointer back to
		// the same type as the pointer loaded from.
		result = b.CreateBitCast(result, v.Type(), "")
	}
	return result
}
Пример #18
0
func (c *compiler) newStackVarEx(argument int, stackf *LLVMValue, v types.Object, value llvm.Value, name string) (stackvalue llvm.Value, stackvar *LLVMValue) {
	typ := v.Type()

	// We need to put alloca instructions in the top block or the values
	// displayed when inspecting these variables in a debugger will be
	// completely messed up.
	curBlock := c.builder.GetInsertBlock()
	if p := curBlock.Parent(); !p.IsNil() {
		fb := p.FirstBasicBlock()
		fi := fb.FirstInstruction()
		if !fb.IsNil() && !fi.IsNil() {
			c.builder.SetInsertPointBefore(fi)
		}
	}
	old := c.builder.CurrentDebugLocation()
	c.builder.SetCurrentDebugLocation(llvm.Value{})
	stackvalue = c.builder.CreateAlloca(c.types.ToLLVM(typ), name)

	// For arguments we want to insert the store instruction
	// without debug information to ensure that they are executed
	// (and hence have proper values) before the debugger hits the
	// first line in a function.
	if argument == 0 {
		c.builder.SetCurrentDebugLocation(old)
		c.builder.SetInsertPointAtEnd(curBlock)
	}

	if !value.IsNil() {
		c.builder.CreateStore(value, stackvalue)
	}
	c.builder.SetCurrentDebugLocation(old)
	c.builder.SetInsertPointAtEnd(curBlock)

	ptrvalue := c.NewValue(stackvalue, types.NewPointer(typ))
	stackvar = ptrvalue.makePointee()
	stackvar.stack = stackf
	c.objectdata[v].Value = stackvar

	// Generate debug metadata (will return nil
	// if debug-data generation is disabled).
	if descriptor := c.createLocalVariableMetadata(v, argument); descriptor != nil {
		c.builder.InsertDeclare(
			c.module.Module,
			llvm.MDNode([]llvm.Value{stackvalue}),
			c.debug_info.MDNode(descriptor),
		)
	}
	return stackvalue, stackvar
}
Пример #19
0
func (v *LLVMValue) chanSend(value Value) {
	var ptr llvm.Value
	if value, ok := value.(*LLVMValue); ok && value.pointer != nil {
		ptr = value.pointer.LLVMValue()
	}
	elttyp := types.Underlying(v.typ).(*types.Chan).Elt
	c := v.compiler
	if ptr.IsNil() {
		ptr = c.builder.CreateAlloca(c.types.ToLLVM(elttyp), "")
		value := value.Convert(elttyp).LLVMValue()
		c.builder.CreateStore(value, ptr)
	}
	uintptr_ := c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
	f := c.NamedFunction("runtime.chansend", "func f(c, ptr uintptr)")
	c.builder.CreateCall(f, []llvm.Value{v.LLVMValue(), uintptr_}, "")
}
Пример #20
0
// declare creates an llvm.dbg.declare call for the specified function
// parameter or local variable.
func (d *debugInfo) declare(b llvm.Builder, v ssa.Value, llv llvm.Value, paramIndex int) {
	tag := tagAutoVariable
	if paramIndex >= 0 {
		tag = tagArgVariable
	}
	ld := debug.NewLocalVariableDescriptor(tag)
	ld.Argument = uint32(paramIndex + 1)
	ld.Name = llv.Name()
	if file := d.Fset.File(v.Pos()); file != nil {
		ld.Line = uint32(file.Position(v.Pos()).Line)
		ld.File = &d.getCompileUnit(file).Path
	}
	ld.Type = d.TypeDebugDescriptor(deref(v.Type()))
	ld.Context = d.context()
	b.InsertDeclare(d.module, llvm.MDNode([]llvm.Value{llv}), d.MDNode(ld))
}
Пример #21
0
func (tm *TypeMap) makeRuntimeTypeGlobal(v llvm.Value) (global, ptr llvm.Value) {
	// Each runtime type is preceded by an interface{}.
	initType := llvm.StructType([]llvm.Type{tm.runtimeType, v.Type()}, false)
	global = llvm.AddGlobal(tm.module, initType, "")
	ptr = llvm.ConstBitCast(global, llvm.PointerType(tm.runtimeType, 0))

	// interface{} containing v's *commonType representation.
	runtimeTypeValue := llvm.Undef(tm.runtimeType)
	zero := llvm.ConstNull(llvm.Int32Type())
	one := llvm.ConstInt(llvm.Int32Type(), 1, false)
	i8ptr := llvm.PointerType(llvm.Int8Type(), 0)
	if tm.commonTypePtrRuntimeType.IsNil() {
		// Create a dummy pointer value, which we'll update straight after
		// defining the runtime type info for commonType.
		tm.commonTypePtrRuntimeType = llvm.Undef(i8ptr)
		commonTypePtr := &types.Pointer{Base: tm.commonType}
		commonTypeGlobal, commonTypeRuntimeType := tm.makeRuntimeType(tm.commonType)
		tm.types[tm.commonType.String()] = runtimeTypeInfo{commonTypeGlobal, commonTypeRuntimeType}
		commonTypePtrGlobal, commonTypePtrRuntimeType := tm.makeRuntimeType(commonTypePtr)
		tm.types[commonTypePtr.String()] = runtimeTypeInfo{commonTypePtrGlobal, commonTypePtrRuntimeType}
		tm.commonTypePtrRuntimeType = llvm.ConstBitCast(commonTypePtrRuntimeType, i8ptr)
		if tm.pkgpath == tm.commonType.Package {
			// Update the interace{} header of the commonType/*commonType
			// runtime types we just created.
			for _, g := range [...]llvm.Value{commonTypeGlobal, commonTypePtrGlobal} {
				init := g.Initializer()
				typptr := tm.commonTypePtrRuntimeType
				runtimeTypeValue := llvm.ConstExtractValue(init, []uint32{0})
				runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, typptr, []uint32{0})
				init = llvm.ConstInsertValue(init, runtimeTypeValue, []uint32{0})
				g.SetInitializer(init)
			}
		}
	}
	commonTypePtr := llvm.ConstGEP(global, []llvm.Value{zero, one})
	commonTypePtr = llvm.ConstBitCast(commonTypePtr, i8ptr)
	runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, tm.commonTypePtrRuntimeType, []uint32{0})
	runtimeTypeValue = llvm.ConstInsertValue(runtimeTypeValue, commonTypePtr, []uint32{1})

	init := llvm.Undef(initType)
	init = llvm.ConstInsertValue(init, runtimeTypeValue, []uint32{0})
	init = llvm.ConstInsertValue(init, v, []uint32{1})
	global.SetInitializer(init)

	return global, ptr
}
Пример #22
0
func (c *compiler) buildPtrRecvFunction(fn llvm.Value) llvm.Value {
	defer c.builder.SetInsertPointAtEnd(c.builder.GetInsertBlock())
	ifname := "*" + fn.Name()
	ifn := c.module.Module.NamedFunction(ifname)
	fntyp := fn.Type().ElementType()
	entry := llvm.AddBasicBlock(ifn, "entry")
	c.builder.SetInsertPointAtEnd(entry)
	args := ifn.Params()
	args[0] = c.builder.CreateLoad(args[0], "recv")
	result := c.builder.CreateCall(fn, args, "")
	if fntyp.ReturnType().TypeKind() == llvm.VoidTypeKind {
		c.builder.CreateRetVoid()
	} else {
		c.builder.CreateRet(result)
	}
	return ifn
}
Пример #23
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
}
Пример #24
0
// coerce yields a value of the the type specified, initialised
// to the exact bit pattern as in the specified value.
//
// Note: the value's type and the specified target type must have
// the same size. If the source is an aggregate, then the target
// must also be an aggregate with the same number of fields, each
// of which must have the same size.
func coerce(b llvm.Builder, v llvm.Value, t llvm.Type) llvm.Value {
	// FIXME don't do this with alloca
	switch t.TypeKind() {
	case llvm.ArrayTypeKind, llvm.StructTypeKind:
		ptr := b.CreateAlloca(t, "")
		ptrv := b.CreateBitCast(ptr, llvm.PointerType(v.Type(), 0), "")
		b.CreateStore(v, ptrv)
		return b.CreateLoad(ptr, "")
	}
	vt := v.Type()
	switch vt.TypeKind() {
	case llvm.ArrayTypeKind, llvm.StructTypeKind:
		ptr := b.CreateAlloca(vt, "")
		b.CreateStore(v, ptr)
		ptrt := b.CreateBitCast(ptr, llvm.PointerType(t, 0), "")
		return b.CreateLoad(ptrt, "")
	}
	return b.CreateBitCast(v, t, "")
}
Пример #25
0
func (v *LLVMValue) UnaryOp(op token.Token) Value {
	b := v.compiler.builder
	switch op {
	case token.SUB:
		var value llvm.Value
		if isFloat(v.typ) {
			zero := llvm.ConstNull(v.compiler.types.ToLLVM(v.Type()))
			value = b.CreateFSub(zero, v.LLVMValue(), "")
		} else {
			value = b.CreateNeg(v.LLVMValue(), "")
		}
		return v.compiler.NewValue(value, v.typ)
	case token.ADD:
		return v // No-op
	case token.AND:
		if typ, ok := v.typ.Underlying().(*types.Pointer); ok {
			if typ.Elem().Underlying() == typ {
				// Taking the address of a recursive pointer
				// yields a value with the same type.
				value := v.pointer.value
				basetyp := value.Type().ElementType()
				value = b.CreateBitCast(value, basetyp, "")
				return v.compiler.NewValue(value, v.typ)
			}
		}
		return v.pointer
	case token.NOT:
		value := b.CreateNot(v.LLVMValue(), "")
		return v.compiler.NewValue(value, v.typ)
	case token.XOR:
		lhs := v.LLVMValue()
		rhs := llvm.ConstAllOnes(lhs.Type())
		value := b.CreateXor(lhs, rhs, "")
		return v.compiler.NewValue(value, v.typ)
	case token.ARROW:
		value, _ := v.chanRecv(false)
		return value
	default:
		panic(fmt.Sprintf("Unhandled operator: %s", op))
	}
	panic("unreachable")
}
Пример #26
0
func (d *debugInfo) pushFunctionContext(fnptr llvm.Value, sig *types.Signature, pos token.Pos) {
	subprog := &debug.SubprogramDescriptor{
		Name:        fnptr.Name(),
		DisplayName: fnptr.Name(),
		Function:    fnptr,
	}
	file := d.Fset.File(pos)
	cu := d.getCompileUnit(file)
	subprog.File = file.Name()
	subprog.Context = &cu.Path
	if file != nil {
		subprog.Line = uint32(file.Line(pos))
		subprog.ScopeLine = uint32(file.Line(pos)) // TODO(axw)
	}
	sigType := d.TypeDebugDescriptor(sig).(*debug.CompositeTypeDescriptor)
	subroutineType := sigType.Members[0]
	subprog.Type = subroutineType
	cu.Subprograms = append(cu.Subprograms, subprog)
	d.pushContext(subprog)
}
Пример #27
0
// coerce yields a value of the the type specified, initialised
// to the exact bit pattern as in the specified value.
//
// Note: the specified value must be a non-aggregate, and its type
// and the specified type must have the same size.
func (c *compiler) coerce(v llvm.Value, t llvm.Type) llvm.Value {
	switch t.TypeKind() {
	case llvm.ArrayTypeKind, llvm.StructTypeKind:
		ptr := c.builder.CreateAlloca(t, "")
		ptrv := c.builder.CreateBitCast(ptr, llvm.PointerType(v.Type(), 0), "")
		c.builder.CreateStore(v, ptrv)
		return c.builder.CreateLoad(ptr, "")
	}

	vt := v.Type()
	switch vt.TypeKind() {
	case llvm.ArrayTypeKind, llvm.StructTypeKind:
		ptr := c.builder.CreateAlloca(vt, "")
		c.builder.CreateStore(v, ptr)
		ptrt := c.builder.CreateBitCast(ptr, llvm.PointerType(t, 0), "")
		return c.builder.CreateLoad(ptrt, "")
	}

	return c.builder.CreateBitCast(v, t, "")
}
Пример #28
0
func (v *LLVMValue) chanSend(value Value) {
	var ptr llvm.Value
	if value, ok := value.(*LLVMValue); ok && value.pointer != nil {
		ptr = value.pointer.LLVMValue()
	}
	elttyp := v.typ.Underlying().(*types.Chan).Elem()
	c := v.compiler
	if ptr.IsNil() {
		ptr = c.builder.CreateAlloca(c.types.ToLLVM(elttyp), "")
		value := value.Convert(elttyp).LLVMValue()
		c.builder.CreateStore(value, ptr)
	}
	uintptr_ := c.builder.CreatePtrToInt(ptr, c.target.IntPtrType(), "")
	nb := boolLLVMValue(false)
	f := c.NamedFunction("runtime.chansend", "func(t *chanType, c, ptr uintptr, nb bool) bool")
	chantyp := c.types.ToRuntime(v.typ.Underlying())
	chantyp = c.builder.CreateBitCast(chantyp, f.Type().ElementType().ParamTypes()[0], "")
	c.builder.CreateCall(f, []llvm.Value{chantyp, v.LLVMValue(), uintptr_, nb}, "")
	// Ignore result; only used in runtime.
}
Пример #29
0
func (tm *TypeMap) interfaceRuntimeType(i *types.Interface) (global, ptr llvm.Value) {
	rtype := tm.makeRtype(i, reflect.Interface)
	interfaceType := llvm.ConstNull(tm.runtimeInterfaceType)
	interfaceType = llvm.ConstInsertValue(interfaceType, rtype, []uint32{0})

	imethods := make([]llvm.Value, i.NumMethods())
	for index := range imethods {
		method := i.Method(index)

		//name, pkgPath, type
		imethod := llvm.ConstNull(tm.runtimeImethod)
		name := tm.globalStringPtr(method.Name())
		name = llvm.ConstBitCast(name, tm.runtimeImethod.StructElementTypes()[0])

		imethod = llvm.ConstInsertValue(imethod, name, []uint32{0})
		//imethod = llvm.ConstInsertValue(imethod, , []uint32{1})
		//imethod = llvm.ConstInsertValue(imethod, , []uint32{2})
		imethods[index] = imethod
	}

	var imethodsGlobalPtr llvm.Value
	imethodPtrType := llvm.PointerType(tm.runtimeImethod, 0)
	if len(imethods) > 0 {
		imethodsArray := llvm.ConstArray(tm.runtimeImethod, imethods)
		imethodsGlobalPtr = llvm.AddGlobal(tm.module, imethodsArray.Type(), "")
		imethodsGlobalPtr.SetInitializer(imethodsArray)
		imethodsGlobalPtr = llvm.ConstBitCast(imethodsGlobalPtr, imethodPtrType)
	} else {
		imethodsGlobalPtr = llvm.ConstNull(imethodPtrType)
	}

	len_ := llvm.ConstInt(tm.inttype, uint64(i.NumMethods()), false)
	imethodsSliceType := tm.runtimeInterfaceType.StructElementTypes()[1]
	imethodsSlice := llvm.ConstNull(imethodsSliceType)
	imethodsSlice = llvm.ConstInsertValue(imethodsSlice, imethodsGlobalPtr, []uint32{0})
	imethodsSlice = llvm.ConstInsertValue(imethodsSlice, len_, []uint32{1})
	imethodsSlice = llvm.ConstInsertValue(imethodsSlice, len_, []uint32{2})
	interfaceType = llvm.ConstInsertValue(interfaceType, imethodsSlice, []uint32{1})
	return tm.makeRuntimeTypeGlobal(interfaceType)
}
Пример #30
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()
}