本文整理汇总了Golang中github.com/axw/llgo/types.Identical函数的典型用法代码示例。如果您正苦于以下问题:Golang Identical函数的具体用法?Golang Identical怎么用?Golang Identical使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了Identical函数的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: UnaryOp
func (v *LLVMValue) UnaryOp(op token.Token) Value {
b := v.compiler.builder
switch op {
case token.SUB:
var value llvm.Value
isfp := types.Identical(types.Underlying(v.typ), types.Float32) ||
types.Identical(types.Underlying(v.typ), types.Float64)
if isfp {
zero := llvm.ConstNull(v.compiler.types.ToLLVM(v.Type()))
value = b.CreateFSub(zero, v.LLVMValue(), "")
} else {
value = b.CreateNeg(v.LLVMValue(), "")
}
return v.compiler.NewLLVMValue(value, v.typ)
case token.ADD:
return v // No-op
case token.AND:
return v.pointer
case token.NOT:
value := b.CreateNot(v.LLVMValue(), "")
return v.compiler.NewLLVMValue(value, v.typ)
case token.XOR:
lhs := v.LLVMValue()
rhs := llvm.ConstAllOnes(lhs.Type())
value := b.CreateXor(lhs, rhs, "")
return v.compiler.NewLLVMValue(value, v.typ)
default:
panic("Unhandled operator: ") // + expr.Op)
}
panic("unreachable")
}
示例2: Convert
func (v ConstValue) Convert(dst_typ types.Type) Value {
// Get the underlying type, if any.
if name, isname := dst_typ.(*types.Name); isname {
dst_typ = types.Underlying(name)
}
if !types.Identical(v.typ, dst_typ) {
// Get the Basic type.
isBasic := false
if name, isname := types.Underlying(dst_typ).(*types.Name); isname {
_, isBasic = name.Underlying.(*types.Basic)
}
compiler := v.compiler
if isBasic {
return ConstValue{*v.Const.Convert(&dst_typ), compiler, dst_typ}
} else {
return compiler.NewLLVMValue(v.LLVMValue(), v.Type()).Convert(dst_typ)
//panic(fmt.Errorf("unhandled conversion from %v to %v", v.typ, dst_typ))
}
} else {
// TODO convert to dst type. ConstValue may need to change to allow
// storage of types other than Basic.
}
return v
}
示例3: Convert
func (v ConstValue) Convert(dstTyp types.Type) Value {
// Get the underlying type, if any.
origDstTyp := dstTyp
dstTyp = types.Underlying(dstTyp)
if !types.Identical(v.typ, dstTyp) {
isBasic := false
if name, isname := types.Underlying(dstTyp).(*types.Name); isname {
_, isBasic = name.Underlying.(*types.Basic)
}
compiler := v.compiler
if isBasic {
return ConstValue{v.Const.Convert(&dstTyp), compiler, origDstTyp}
} else {
return compiler.NewLLVMValue(v.LLVMValue(), v.Type()).Convert(origDstTyp)
//panic(fmt.Errorf("unhandled conversion from %v to %v", v.typ, dstTyp))
}
} else {
v.typ = origDstTyp
}
return v
}
示例4: VisitSelectorExpr
//.........这里部分代码省略.........
ftype.Recv = nil
method := c.NewLLVMValue(f, ftype)
method.receiver = c.NewLLVMValue(receiver, i8ptr)
return method
}
// Search through embedded types for field/method.
var result selectorCandidate
curr := []selectorCandidate{{nil, lhs.Type()}}
for result.Type == nil && len(curr) > 0 {
var next []selectorCandidate
for _, candidate := range curr {
indices := candidate.Indices[0:]
t := candidate.Type
if p, ok := types.Underlying(t).(*types.Pointer); ok {
if _, ok := types.Underlying(p.Base).(*types.Struct); ok {
t = p.Base
}
}
if n, ok := t.(*types.Name); ok {
i := sort.Search(len(n.Methods), func(i int) bool {
return n.Methods[i].Name >= name
})
if i < len(n.Methods) && n.Methods[i].Name == name {
result.Indices = indices
result.Type = t
}
}
if t, ok := types.Underlying(t).(*types.Struct); ok {
if i, ok := t.FieldIndices[name]; ok {
result.Indices = append(indices, int(i))
result.Type = t
} else {
// Add embedded types to the next set of types
// to check.
for i, field := range t.Fields {
if field.Name == "" {
indices = append(indices[0:], i)
t := field.Type.(types.Type)
candidate := selectorCandidate{indices, t}
next = append(next, candidate)
}
}
}
}
}
curr = next
}
// Get a pointer to the field/receiver.
recvValue := lhs.(*LLVMValue)
if len(result.Indices) > 0 {
if _, ok := types.Underlying(lhs.Type()).(*types.Pointer); !ok {
recvValue = recvValue.pointer
//recvValue = c.NewLLVMValue(recvValue.LLVMValue(), recvValue.Type())
}
for _, v := range result.Indices {
ptr := recvValue.LLVMValue()
field := types.Underlying(types.Deref(recvValue.typ)).(*types.Struct).Fields[v]
fieldPtr := c.builder.CreateStructGEP(ptr, v, "")
fieldPtrTyp := &types.Pointer{Base: field.Type.(types.Type)}
recvValue = c.NewLLVMValue(fieldPtr, fieldPtrTyp)
// GEP returns a pointer; if the field is a pointer,
// we must load our pointer-to-a-pointer.
if _, ok := field.Type.(*types.Pointer); ok {
recvValue = recvValue.makePointee()
}
}
}
// Method?
if expr.Sel.Obj.Kind == ast.Fun {
method := c.Resolve(expr.Sel.Obj).(*LLVMValue)
methodType := expr.Sel.Obj.Type.(*types.Func)
receiverType := methodType.Recv.Type.(types.Type)
if types.Identical(recvValue.Type(), receiverType) {
method.receiver = recvValue
} else if types.Identical(&types.Pointer{Base: recvValue.Type()}, receiverType) {
method.receiver = recvValue.pointer
} else {
method.receiver = recvValue.makePointee()
}
return method
} else {
resultType := expr.Sel.Obj.Type.(types.Type)
if types.Identical(recvValue.Type(), resultType) {
// no-op
} else if types.Identical(&types.Pointer{Base: recvValue.Type()}, resultType) {
recvValue = recvValue.pointer
} else {
recvValue = recvValue.makePointee()
}
return recvValue
}
panic("unreachable")
}
示例5: VisitSelectorExpr
func (c *compiler) VisitSelectorExpr(expr *ast.SelectorExpr) Value {
lhs := c.VisitExpr(expr.X)
if lhs == nil {
// The only time we should get a nil result is if the object is
// a package.
obj := expr.Sel.Obj
if obj.Kind == ast.Typ {
return TypeValue{obj.Type.(types.Type)}
}
return c.Resolve(obj)
}
// TODO(?) record path to field/method during typechecking, so we don't
// have to search again here.
name := expr.Sel.Name
if iface, ok := types.Underlying(lhs.Type()).(*types.Interface); ok {
// validity checked during typechecking.
i := sort.Search(len(iface.Methods), func(i int) bool {
return iface.Methods[i].Name >= name
})
struct_value := lhs.LLVMValue()
receiver_value := c.builder.CreateStructGEP(struct_value, 0, "")
fn_value := c.builder.CreateStructGEP(struct_value, i+2, "")
method_type := c.ObjGetType(iface.Methods[i]).(*types.Func)
method := c.NewLLVMValue(
c.builder.CreateBitCast(
c.builder.CreateLoad(fn_value, ""),
c.types.ToLLVM(method_type), ""), method_type)
method.receiver = c.NewLLVMValue(
c.builder.CreateLoad(receiver_value, ""),
method_type.Recv.Type.(types.Type))
return method
}
// Search through embedded types for field/method.
var result selectorCandidate
curr := []selectorCandidate{{nil, lhs.Type()}}
for result.Type == nil && len(curr) > 0 {
var next []selectorCandidate
for _, candidate := range curr {
indices := candidate.Indices[0:]
t := candidate.Type
if p, ok := types.Underlying(t).(*types.Pointer); ok {
if _, ok := types.Underlying(p.Base).(*types.Struct); ok {
indices = append(indices, 0)
t = p.Base
}
}
if n, ok := t.(*types.Name); ok {
i := sort.Search(len(n.Methods), func(i int) bool {
return n.Methods[i].Name >= name
})
if i < len(n.Methods) && n.Methods[i].Name == name {
result.Indices = indices
result.Type = t
}
}
if t, ok := types.Underlying(t).(*types.Struct); ok {
if i, ok := t.FieldIndices[name]; ok {
result.Indices = append(indices, i)
result.Type = t
} else {
// Add embedded types to the next set of types
// to check.
for i, field := range t.Fields {
if field.Name == "" {
indices = append(indices[0:], uint64(i))
t := field.Type.(types.Type)
candidate := selectorCandidate{indices, t}
next = append(next, candidate)
}
}
}
}
}
curr = next
}
// Get a pointer to the field/struct for field/method invocation.
indices := make([]llvm.Value, len(result.Indices))
for i, v := range result.Indices {
indices[i] = llvm.ConstInt(llvm.Int32Type(), v, false)
}
// Method?
if expr.Sel.Obj.Kind == ast.Fun {
method := c.Resolve(expr.Sel.Obj).(*LLVMValue)
methodType := expr.Sel.Obj.Type.(*types.Func)
receiverType := methodType.Recv.Type.(types.Type)
if len(indices) > 0 {
receiverValue := c.builder.CreateGEP(lhs.LLVMValue(), indices, "")
if types.Identical(result.Type, receiverType) {
receiverValue = c.builder.CreateLoad(receiverValue, "")
}
method.receiver = c.NewLLVMValue(receiverValue, receiverType)
} else {
//.........这里部分代码省略.........
示例6: convertV2I
//.........这里部分代码省略.........
} else {
// If the value fits exactly in a pointer, then we can just
// bitcast it. Otherwise we need to malloc, and create a shim
// function to load the receiver.
c := v.compiler
ptrsize := c.target.PointerSize()
if c.target.TypeStoreSize(lv.Type()) <= uint64(ptrsize) {
bits := c.target.TypeSizeInBits(lv.Type())
if bits > 0 {
lv = c.coerce(lv, llvm.IntType(int(bits)))
ptr = builder.CreateIntToPtr(lv, element_types[1], "")
} else {
ptr = llvm.ConstNull(element_types[1])
}
} else {
ptr = c.createTypeMalloc(v.compiler.types.ToLLVM(srctyp))
builder.CreateStore(lv, ptr)
ptr = builder.CreateBitCast(ptr, element_types[1], "")
overwide = true
}
}
runtimeType := v.compiler.types.ToRuntime(v.Type())
runtimeType = builder.CreateBitCast(runtimeType, element_types[0], "")
iface_struct = builder.CreateInsertValue(iface_struct, runtimeType, 0, "")
iface_struct = builder.CreateInsertValue(iface_struct, ptr, 1, "")
// TODO assert either source is a named type (or pointer to), or the
// interface has an empty methodset.
if srcname != nil {
// TODO check whether the functions in the struct take
// value or pointer receivers.
// Look up the method by name.
// TODO check embedded types.
for i, m := range iface.Methods {
// TODO make this loop linear by iterating through the
// interface methods and type methods together.
var methodobj *ast.Object
curr := []types.Type{srcname}
for methodobj == nil && len(curr) > 0 {
var next []types.Type
for _, typ := range curr {
if p, ok := types.Underlying(typ).(*types.Pointer); ok {
if _, ok := types.Underlying(p.Base).(*types.Struct); ok {
typ = p.Base
}
}
if n, ok := typ.(*types.Name); ok {
methods := n.Methods
mi := sort.Search(len(methods), func(i int) bool {
return methods[i].Name >= m.Name
})
if mi < len(methods) && methods[mi].Name == m.Name {
methodobj = methods[mi]
break
}
}
if typ, ok := types.Underlying(typ).(*types.Struct); ok {
for _, field := range typ.Fields {
if field.Name == "" {
typ := field.Type.(types.Type)
next = append(next, typ)
}
}
}
}
curr = next
}
if methodobj == nil {
msg := fmt.Sprintf("Failed to locate (%s).%s", srcname.Obj.Name, m.Name)
panic(msg)
}
method := v.compiler.Resolve(methodobj).(*LLVMValue)
llvm_value := method.LLVMValue()
// If we have a receiver wider than a word, or a pointer
// receiver value and non-pointer receiver method, then
// we must use the "wrapper" pointer method.
fntyp := methodobj.Type.(*types.Func)
recvtyp := fntyp.Recv.Type.(types.Type)
needload := overwide
if !needload {
// TODO handle embedded types here.
//needload = types.Identical(v.Type(), recvtyp)
if p, ok := v.Type().(*types.Pointer); ok {
needload = types.Identical(p.Base, recvtyp)
}
}
if needload {
ifname := fmt.Sprintf("*%s.%s", recvtyp, methodobj.Name)
llvm_value = v.compiler.module.NamedFunction(ifname)
}
llvm_value = builder.CreateBitCast(llvm_value, element_types[i+2], "")
iface_struct = builder.CreateInsertValue(iface_struct, llvm_value, i+2, "")
}
}
return v.compiler.NewLLVMValue(iface_struct, iface)
}
示例7: BinaryOp
func (lhs *LLVMValue) BinaryOp(op token.Token, rhs_ Value) Value {
if op == token.NEQ {
result := lhs.BinaryOp(token.EQL, rhs_)
return result.UnaryOp(token.NOT)
}
var result llvm.Value
c := lhs.compiler
b := lhs.compiler.builder
// Later we can do better by treating constants specially. For now, let's
// convert to LLVMValue's.
var rhs *LLVMValue
rhsisnil := false
switch rhs_ := rhs_.(type) {
case *LLVMValue:
rhs = rhs_
case NilValue:
rhsisnil = true
switch rhs_ := rhs_.Convert(lhs.Type()).(type) {
case ConstValue:
rhs = c.NewLLVMValue(rhs_.LLVMValue(), rhs_.Type())
case *LLVMValue:
rhs = rhs_
}
case ConstValue:
value := rhs_.Convert(lhs.Type())
rhs = c.NewLLVMValue(value.LLVMValue(), value.Type())
}
switch typ := types.Underlying(lhs.typ).(type) {
case *types.Struct:
// TODO check types are the same.
element_types_count := lhs.LLVMValue().Type().StructElementTypesCount()
struct_fields := typ.Fields
if element_types_count > 0 {
t := c.ObjGetType(struct_fields[0])
first_lhs := c.NewLLVMValue(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), t)
first_rhs := c.NewLLVMValue(b.CreateExtractValue(rhs.LLVMValue(), 0, ""), t)
first := first_lhs.BinaryOp(op, first_rhs)
logical_op := token.LAND
if op == token.NEQ {
logical_op = token.LOR
}
result := first
for i := 1; i < element_types_count; i++ {
t := c.ObjGetType(struct_fields[i])
next_lhs := c.NewLLVMValue(b.CreateExtractValue(lhs.LLVMValue(), i, ""), t)
next_rhs := c.NewLLVMValue(b.CreateExtractValue(rhs.LLVMValue(), i, ""), t)
next := next_lhs.BinaryOp(op, next_rhs)
result = result.BinaryOp(logical_op, next)
}
return result
}
case *types.Interface:
if rhsisnil {
valueNull := b.CreateIsNull(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), "")
typeNull := b.CreateIsNull(b.CreateExtractValue(lhs.LLVMValue(), 1, ""), "")
result := b.CreateAnd(typeNull, valueNull, "")
return c.NewLLVMValue(result, types.Bool)
}
// TODO check for interface/interface comparison vs. interface/value comparison.
return lhs.compareI2I(rhs)
case *types.Slice:
// []T == nil
isnil := b.CreateIsNull(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), "")
return c.NewLLVMValue(isnil, types.Bool)
}
// Strings.
if types.Underlying(lhs.typ) == types.String {
if types.Underlying(rhs.typ) == types.String {
switch op {
case token.ADD:
return c.concatenateStrings(lhs, rhs)
case token.EQL, token.LSS, token.GTR, token.LEQ, token.GEQ:
return c.compareStrings(lhs, rhs, op)
default:
panic(fmt.Sprint("Unimplemented operator: ", op))
}
}
panic("unimplemented")
}
// Determine whether to use integer or floating point instructions.
// TODO determine the NaN rules.
isfp := types.Identical(types.Underlying(lhs.typ), types.Float32) ||
types.Identical(types.Underlying(lhs.typ), types.Float64)
switch op {
case token.MUL:
if isfp {
result = b.CreateFMul(lhs.LLVMValue(), rhs.LLVMValue(), "")
} else {
result = b.CreateMul(lhs.LLVMValue(), rhs.LLVMValue(), "")
}
//.........这里部分代码省略.........
示例8: VisitSelectorExpr
func (c *compiler) VisitSelectorExpr(expr *ast.SelectorExpr) Value {
lhs := c.VisitExpr(expr.X)
if lhs == nil {
// The only time we should get a nil result is if the object is
// a package.
obj := expr.Sel.Obj
if obj.Kind == ast.Typ {
return TypeValue{obj.Type.(types.Type)}
}
return c.Resolve(obj)
}
// TODO(?) record path to field/method during typechecking, so we don't
// have to search again here.
name := expr.Sel.Name
if iface, ok := types.Underlying(lhs.Type()).(*types.Interface); ok {
i := sort.Search(len(iface.Methods), func(i int) bool {
return iface.Methods[i].Name >= name
})
structValue := lhs.LLVMValue()
receiver := c.builder.CreateExtractValue(structValue, 0, "")
f := c.builder.CreateExtractValue(structValue, i+2, "")
ftype := c.ObjGetType(iface.Methods[i]).(*types.Func)
method := c.NewLLVMValue(c.builder.CreateBitCast(f, c.types.ToLLVM(ftype), ""), ftype)
method.receiver = c.NewLLVMValue(receiver, ftype.Recv.Type.(types.Type))
return method
}
// Search through embedded types for field/method.
var result selectorCandidate
curr := []selectorCandidate{{nil, lhs.Type()}}
for result.Type == nil && len(curr) > 0 {
var next []selectorCandidate
for _, candidate := range curr {
indices := candidate.Indices[0:]
t := candidate.Type
if p, ok := types.Underlying(t).(*types.Pointer); ok {
if _, ok := types.Underlying(p.Base).(*types.Struct); ok {
t = p.Base
}
}
if n, ok := t.(*types.Name); ok {
i := sort.Search(len(n.Methods), func(i int) bool {
return n.Methods[i].Name >= name
})
if i < len(n.Methods) && n.Methods[i].Name == name {
result.Indices = indices
result.Type = t
}
}
if t, ok := types.Underlying(t).(*types.Struct); ok {
if i, ok := t.FieldIndices[name]; ok {
result.Indices = append(indices, int(i))
result.Type = t
} else {
// Add embedded types to the next set of types
// to check.
for i, field := range t.Fields {
if field.Name == "" {
indices = append(indices[0:], i)
t := field.Type.(types.Type)
candidate := selectorCandidate{indices, t}
next = append(next, candidate)
}
}
}
}
}
curr = next
}
// Get a pointer to the field/receiver.
recvValue := lhs.(*LLVMValue)
if _, ok := types.Underlying(lhs.Type()).(*types.Pointer); !ok {
recvValue = recvValue.pointer
}
recvValue = c.NewLLVMValue(recvValue.LLVMValue(), recvValue.Type())
if len(result.Indices) > 0 {
for _, v := range result.Indices {
ptr := recvValue.LLVMValue()
field := types.Underlying(types.Deref(recvValue.typ)).(*types.Struct).Fields[v]
fieldPtr := c.builder.CreateStructGEP(ptr, v, "")
fieldPtrTyp := &types.Pointer{Base: field.Type.(types.Type)}
recvValue = c.NewLLVMValue(fieldPtr, fieldPtrTyp)
// GEP returns a pointer; if the field is a pointer,
// we must load our pointer-to-a-pointer.
if _, ok := field.Type.(*types.Pointer); ok {
recvValue = recvValue.makePointee()
}
}
}
if !types.Identical(recvValue.typ, expr.Sel.Obj.Type.(types.Type)) {
recvValue = recvValue.makePointee()
}
//.........这里部分代码省略.........
示例9: Convert
func (v *LLVMValue) Convert(dst_typ types.Type) Value {
b := v.compiler.builder
// If it's a stack allocated value, we'll want to compare the
// value type, not the pointer type.
src_typ := v.typ
// Get the underlying type, if any.
orig_dst_typ := dst_typ
dst_typ = types.Underlying(dst_typ)
src_typ = types.Underlying(src_typ)
// Identical (underlying) types? Just swap in the destination type.
if types.Identical(src_typ, dst_typ) {
// TODO avoid load here by reusing pointer value, if exists.
return v.compiler.NewLLVMValue(v.LLVMValue(), orig_dst_typ)
}
// Both pointer types with identical underlying types? Same as above.
if src_typ, ok := src_typ.(*types.Pointer); ok {
if dst_typ, ok := dst_typ.(*types.Pointer); ok {
src_typ := types.Underlying(src_typ.Base)
dst_typ := types.Underlying(dst_typ.Base)
if types.Identical(src_typ, dst_typ) {
return v.compiler.NewLLVMValue(v.LLVMValue(), orig_dst_typ)
}
}
}
// Convert from an interface type.
if _, isinterface := src_typ.(*types.Interface); isinterface {
if interface_, isinterface := dst_typ.(*types.Interface); isinterface {
result, _ := v.convertI2I(interface_)
return result
} else {
result, _ := v.convertI2V(orig_dst_typ)
return result
}
}
// Converting to an interface type.
if interface_, isinterface := dst_typ.(*types.Interface); isinterface {
return v.convertV2I(interface_)
}
// string -> []byte
byteslice := &types.Slice{Elt: types.Byte}
if src_typ == types.String && types.Identical(dst_typ, byteslice) {
c := v.compiler
value := v.LLVMValue()
strdata := c.builder.CreateExtractValue(value, 0, "")
strlen := c.builder.CreateExtractValue(value, 1, "")
struct_ := llvm.Undef(c.types.ToLLVM(byteslice))
struct_ = c.builder.CreateInsertValue(struct_, strdata, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, strlen, 1, "")
struct_ = c.builder.CreateInsertValue(struct_, strlen, 2, "")
return c.NewLLVMValue(struct_, byteslice)
}
// []byte -> string
if types.Identical(src_typ, byteslice) && dst_typ == types.String {
c := v.compiler
value := v.LLVMValue()
data := c.builder.CreateExtractValue(value, 0, "")
len := c.builder.CreateExtractValue(value, 1, "")
struct_ := llvm.Undef(c.types.ToLLVM(types.String))
struct_ = c.builder.CreateInsertValue(struct_, data, 0, "")
struct_ = c.builder.CreateInsertValue(struct_, len, 1, "")
return c.NewLLVMValue(struct_, types.String)
}
// Rune to string conversion.
if dst_typ == types.String && isIntType(src_typ) {
return v.runeToString()
}
// TODO other special conversions?
llvm_type := v.compiler.types.ToLLVM(dst_typ)
// Unsafe pointer conversions.
if dst_typ == types.UnsafePointer { // X -> unsafe.Pointer
if _, isptr := src_typ.(*types.Pointer); isptr {
value := b.CreatePtrToInt(v.LLVMValue(), llvm_type, "")
return v.compiler.NewLLVMValue(value, orig_dst_typ)
} else if src_typ == types.Uintptr {
return v.compiler.NewLLVMValue(v.LLVMValue(), orig_dst_typ)
}
} else if src_typ == types.UnsafePointer { // unsafe.Pointer -> X
if _, isptr := dst_typ.(*types.Pointer); isptr {
value := b.CreateIntToPtr(v.LLVMValue(), llvm_type, "")
return v.compiler.NewLLVMValue(value, orig_dst_typ)
} else if dst_typ == types.Uintptr {
return v.compiler.NewLLVMValue(v.LLVMValue(), orig_dst_typ)
}
}
// FIXME select the appropriate cast here, depending on size, type (int/float)
// and sign.
lv := v.LLVMValue()
srcType := lv.Type()
//.........这里部分代码省略.........
示例10: BinaryOp
func (lhs *LLVMValue) BinaryOp(op token.Token, rhs_ Value) Value {
if op == token.NEQ {
result := lhs.BinaryOp(token.EQL, rhs_)
return result.UnaryOp(token.NOT)
}
var result llvm.Value
c := lhs.compiler
b := lhs.compiler.builder
// Later we can do better by treating constants specially. For now, let's
// convert to LLVMValue's.
var rhs *LLVMValue
switch rhs_ := rhs_.(type) {
case *LLVMValue:
rhs = rhs_
case NilValue:
switch rhs_ := rhs_.Convert(lhs.Type()).(type) {
case ConstValue:
rhs = c.NewLLVMValue(rhs_.LLVMValue(), rhs_.Type())
case *LLVMValue:
rhs = rhs_
}
case ConstValue:
value := rhs_.Convert(lhs.Type())
rhs = c.NewLLVMValue(value.LLVMValue(), value.Type())
}
// Special case for structs.
// TODO handle strings as an even more special case.
if struct_type, ok := types.Underlying(lhs.typ).(*types.Struct); ok {
// TODO check types are the same.
element_types_count := lhs.LLVMValue().Type().StructElementTypesCount()
struct_fields := struct_type.Fields
if element_types_count > 0 {
t := c.ObjGetType(struct_fields[0])
first_lhs := c.NewLLVMValue(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), t)
first_rhs := c.NewLLVMValue(b.CreateExtractValue(rhs.LLVMValue(), 0, ""), t)
first := first_lhs.BinaryOp(op, first_rhs)
logical_op := token.LAND
if op == token.NEQ {
logical_op = token.LOR
}
result := first
for i := 1; i < element_types_count; i++ {
t := c.ObjGetType(struct_fields[i])
next_lhs := c.NewLLVMValue(b.CreateExtractValue(lhs.LLVMValue(), i, ""), t)
next_rhs := c.NewLLVMValue(b.CreateExtractValue(rhs.LLVMValue(), i, ""), t)
next := next_lhs.BinaryOp(op, next_rhs)
result = result.BinaryOp(logical_op, next)
}
return result
}
}
// Interfaces.
if _, ok := types.Underlying(lhs.typ).(*types.Interface); ok {
// TODO check for interface/interface comparison vs. interface/value comparison.
// nil comparison
if /*rhs.LLVMValue().IsConstant() &&*/ rhs.LLVMValue().IsNull() {
var result llvm.Value
if op == token.EQL {
valueNull := b.CreateIsNull(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), "")
typeNull := b.CreateIsNull(b.CreateExtractValue(lhs.LLVMValue(), 1, ""), "")
result = b.CreateAnd(typeNull, valueNull, "")
} else {
valueNotNull := b.CreateIsNotNull(b.CreateExtractValue(lhs.LLVMValue(), 0, ""), "")
typeNotNull := b.CreateIsNotNull(b.CreateExtractValue(lhs.LLVMValue(), 1, ""), "")
result = b.CreateOr(typeNotNull, valueNotNull, "")
}
return c.NewLLVMValue(result, types.Bool)
}
// First, check that the dynamic types are identical.
// FIXME provide runtime function for type identity comparison, and
// value comparisons.
lhsType := b.CreateExtractValue(lhs.LLVMValue(), 1, "")
rhsType := b.CreateExtractValue(rhs.LLVMValue(), 1, "")
diff := b.CreatePtrDiff(lhsType, rhsType, "")
zero := llvm.ConstNull(diff.Type())
var result llvm.Value
if op == token.EQL {
typesIdentical := b.CreateICmp(llvm.IntEQ, diff, zero, "")
//valuesEqual := ...
//result = b.CreateAnd(typesIdentical, valuesEqual, "")
result = typesIdentical
} else {
typesDifferent := b.CreateICmp(llvm.IntNE, diff, zero, "")
//valuesUnequal := ...
//result = b.CreateOr(typesDifferent, valuesUnequal, "")
result = typesDifferent
}
return c.NewLLVMValue(result, types.Bool)
}
//.........这里部分代码省略.........
示例11: uncommonType
func (tm *TypeMap) uncommonType(n *types.Name, ptr bool) llvm.Value {
uncommonTypeInit := llvm.ConstNull(tm.runtimeUncommonType)
namePtr := tm.globalStringPtr(n.Obj.Name)
uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, namePtr, []uint32{0})
var pkgpathPtr llvm.Value
if n.Package != "" {
pkgpathPtr = tm.globalStringPtr(n.Package)
uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, pkgpathPtr, []uint32{1})
}
// Store methods.
methods := make([]llvm.Value, 0, len(n.Methods))
for _, m := range n.Methods {
ftyp := m.Type.(*types.Func)
ptrrecv := !types.Identical(ftyp.Recv.Type.(types.Type), n)
if !ptr && ptrrecv {
// For a type T, we only store methods where the
// receiver is T and not *T. For *T we store both.
continue
}
method := llvm.ConstNull(tm.runtimeMethod)
name := tm.globalStringPtr(m.Name)
name = llvm.ConstBitCast(name, tm.runtimeMethod.StructElementTypes()[0])
// name
method = llvm.ConstInsertValue(method, name, []uint32{0})
// pkgPath
method = llvm.ConstInsertValue(method, pkgpathPtr, []uint32{1})
// mtyp (method type, no receiver)
{
recv := ftyp.Recv
ftyp.Recv = nil
mtyp := tm.ToRuntime(ftyp)
method = llvm.ConstInsertValue(method, mtyp, []uint32{2})
ftyp.Recv = recv
}
// typ (function type, with receiver)
typ := tm.ToRuntime(ftyp)
method = llvm.ConstInsertValue(method, typ, []uint32{3})
// tfn (standard method/function pointer for plain method calls)
tfn := tm.resolver.Resolve(m).LLVMValue()
tfn = llvm.ConstPtrToInt(tfn, tm.target.IntPtrType())
// ifn (single-word receiver function pointer for interface calls)
ifn := tfn
needload := ptr && !ptrrecv
if !needload {
recvtyp := tm.ToLLVM(ftyp.Recv.Type.(types.Type))
needload = int(tm.target.TypeAllocSize(recvtyp)) > tm.target.PointerSize()
}
if needload {
// If the receiver type is wider than a word, we
// need to use an intermediate function which takes
// a pointer-receiver, loads it, and then calls the
// standard receiver function.
fname := fmt.Sprintf("*%s.%s", ftyp.Recv.Type, m.Name)
ifn = tm.module.NamedFunction(fname)
ifn = llvm.ConstPtrToInt(ifn, tm.target.IntPtrType())
}
method = llvm.ConstInsertValue(method, ifn, []uint32{4})
method = llvm.ConstInsertValue(method, tfn, []uint32{5})
methods = append(methods, method)
}
var methodsGlobalPtr llvm.Value
if len(methods) > 0 {
methodsArray := llvm.ConstArray(tm.runtimeMethod, methods)
methodsGlobalPtr = llvm.AddGlobal(tm.module, methodsArray.Type(), "")
methodsGlobalPtr.SetInitializer(methodsArray)
i32zero := llvm.ConstNull(llvm.Int32Type())
methodsGlobalPtr = llvm.ConstGEP(methodsGlobalPtr, []llvm.Value{i32zero, i32zero})
} else {
methodsGlobalPtr = llvm.ConstNull(llvm.PointerType(tm.runtimeMethod, 0))
}
len_ := llvm.ConstInt(llvm.Int32Type(), uint64(len(methods)), false)
methodsSliceType := tm.runtimeUncommonType.StructElementTypes()[2]
methodsSlice := llvm.ConstNull(methodsSliceType)
methodsSlice = llvm.ConstInsertValue(methodsSlice, methodsGlobalPtr, []uint32{0})
methodsSlice = llvm.ConstInsertValue(methodsSlice, len_, []uint32{1})
methodsSlice = llvm.ConstInsertValue(methodsSlice, len_, []uint32{2})
uncommonTypeInit = llvm.ConstInsertValue(uncommonTypeInit, methodsSlice, []uint32{2})
return uncommonTypeInit
}