示例#1
0
文件: typemap.go 项目: hzmangel/llgo
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) {
	// Is the base type a named type from another package? If so, we'll
	// create a reference to the externally defined symbol.
	var globalname string
	if n, ok := p.Elem().(*types.Named); ok {
		// FIXME horrible circular relationship
		var path string
		if data, ok := tm.functions.objectdata[n.Obj()]; ok {
			path = pkgpath(data.Package)
		}
		if path == "" {
			path = "runtime"
		}
		globalname = "__llgo.type.*" + path + "." + n.Obj().Name()
		if path != tm.pkgpath {
			global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname)
			global.SetInitializer(llvm.ConstNull(tm.runtimeType))
			global.SetLinkage(llvm.CommonLinkage)
			return global, global
		}
	}

	rtype := tm.makeRtype(p, reflect.Ptr)
	if n, ok := p.Elem().(*types.Named); ok {
		uncommonTypeInit := tm.uncommonType(n, true)
		uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "")
		uncommonType.SetInitializer(uncommonTypeInit)
		rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9})
	}

	ptrType := llvm.ConstNull(tm.runtimePtrType)
	var baseTypeGlobal llvm.Value
	if p.Elem().Underlying() == p {
		// Recursive pointer.
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType)
		baseTypeGlobal = global

		// Update the global with its own pointer in the elem field.
		ptrType = global.Initializer()
		ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1})
		global.SetInitializer(ptrType)
	} else {
		var baseTypePtr llvm.Value
		baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem())
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType)
	}
	global.SetName(globalname)

	// Set ptrToThis in the base type's rtype.
	baseType := baseTypeGlobal.Initializer()
	if baseType.Type() == tm.runtimeType {
		baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10})
	} else {
		rtype := llvm.ConstExtractValue(baseType, []uint32{0})
		rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10})
		baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0})
	}
	baseTypeGlobal.SetInitializer(baseType)

	return global, ptr
}
示例#2
0
文件: typemap.go 项目: minux/llgo
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) {
	// Is the base type a named type from another package? If so, we'll
	// create a reference to the externally defined symbol.
	linkage := llvm.LinkOnceAnyLinkage
	switch elem := p.Elem().(type) {
	case *types.Basic:
		if tm.pkgpath != "runtime" {
			global := llvm.AddGlobal(tm.module, tm.runtime.rtype.llvm, typeSymbol(typeString(p)))
			global.SetInitializer(llvm.ConstNull(tm.runtime.rtype.llvm))
			global.SetLinkage(llvm.CommonLinkage)
			return global, global
		}
		linkage = llvm.ExternalLinkage
	case *types.Named:
		path := "runtime"
		if pkg := elem.Obj().Pkg(); pkg != nil {
			path = pkg.Path()
		}
		if path != tm.pkgpath {
			global := llvm.AddGlobal(tm.module, tm.runtime.rtype.llvm, typeSymbol(typeString(p)))
			global.SetInitializer(llvm.ConstNull(tm.runtime.rtype.llvm))
			global.SetLinkage(llvm.CommonLinkage)
			return global, global
		}
		linkage = llvm.ExternalLinkage
	}

	rtype := tm.makeRtype(p, reflect.Ptr)
	if n, ok := p.Elem().(*types.Named); ok {
		uncommonTypeInit := tm.uncommonType(n, p)
		uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "")
		uncommonType.SetInitializer(uncommonTypeInit)
		rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9})
	}

	ptrType := llvm.ConstNull(tm.runtime.ptrType.llvm)
	var baseTypeGlobal llvm.Value
	if p.Elem().Underlying() == p {
		// Recursive pointer.
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType, typeString(p))
		baseTypeGlobal = global
		// Update the global with its own pointer in the elem field.
		ptrType = global.Initializer()
		ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1})
		global.SetInitializer(ptrType)
	} else {
		var baseTypePtr llvm.Value
		baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem())
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType, typeString(p))
	}
	global.SetLinkage(linkage)

	// Set ptrToThis in the base type's rtype.
	baseType := baseTypeGlobal.Initializer()
	if !baseType.IsNull() {
		if baseType.Type() == tm.runtime.rtype.llvm {
			baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10})
		} else {
			rtype := llvm.ConstExtractValue(baseType, []uint32{0})
			rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10})
			baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0})
		}
		baseTypeGlobal.SetInitializer(baseType)
	}
	return global, ptr
}
示例#3
0
文件: typemap.go 项目: quarnster/llgo
func (tm *TypeMap) pointerRuntimeType(p *types.Pointer) (global, ptr llvm.Value) {
	// Is the base type a named type from another package? If so, we'll
	// create a reference to the externally defined symbol.
	var globalname string
	switch elem := p.Elem().(type) {
	case *types.Basic:
		globalname = "__llgo.type.*runtime." + tm.TypeString(elem)
		if tm.pkgpath != "runtime" {
			global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname)
			global.SetInitializer(llvm.ConstNull(tm.runtimeType))
			global.SetLinkage(llvm.CommonLinkage)
			return global, global
		}
	case *types.Named:
		qname, path := tm.qualifiedName(elem)
		globalname = "__llgo.type.*" + qname
		if path != tm.pkgpath {
			global := llvm.AddGlobal(tm.module, tm.runtimeType, globalname)
			global.SetInitializer(llvm.ConstNull(tm.runtimeType))
			global.SetLinkage(llvm.CommonLinkage)
			return global, global
		} else if !isGlobalObject(elem.Obj()) {
			globalname = ""
		}
	}

	rtype := tm.makeRtype(p, reflect.Ptr)
	if n, ok := p.Elem().(*types.Named); ok {
		uncommonTypeInit := tm.uncommonType(n, true)
		uncommonType := llvm.AddGlobal(tm.module, uncommonTypeInit.Type(), "")
		uncommonType.SetInitializer(uncommonTypeInit)
		rtype = llvm.ConstInsertValue(rtype, uncommonType, []uint32{9})
	}

	ptrType := llvm.ConstNull(tm.runtimePtrType)
	var baseTypeGlobal llvm.Value
	if p.Elem().Underlying() == p {
		// Recursive pointer.
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType)
		baseTypeGlobal = global

		// Update the global with its own pointer in the elem field.
		ptrType = global.Initializer()
		ptrType = llvm.ConstInsertValue(ptrType, ptr, []uint32{1})
		global.SetInitializer(ptrType)
	} else {
		var baseTypePtr llvm.Value
		baseTypeGlobal, baseTypePtr = tm.toRuntime(p.Elem())
		ptrType = llvm.ConstInsertValue(ptrType, rtype, []uint32{0})
		ptrType = llvm.ConstInsertValue(ptrType, baseTypePtr, []uint32{1})
		global, ptr = tm.makeRuntimeTypeGlobal(ptrType)
	}
	global.SetName(globalname)

	// Set ptrToThis in the base type's rtype.
	baseType := baseTypeGlobal.Initializer()
	if baseType.Type() == tm.runtimeType {
		baseType = llvm.ConstInsertValue(baseType, ptr, []uint32{10})
	} else {
		rtype := llvm.ConstExtractValue(baseType, []uint32{0})
		rtype = llvm.ConstInsertValue(rtype, ptr, []uint32{10})
		baseType = llvm.ConstInsertValue(baseType, rtype, []uint32{0})
	}
	baseTypeGlobal.SetInitializer(baseType)

	return global, ptr
}