github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/lift/x86/type.go (about) 1 package x86 2 3 import ( 4 "fmt" 5 6 "github.com/llir/llvm/asm" 7 "github.com/llir/llvm/ir" 8 "github.com/llir/llvm/ir/types" 9 ) 10 11 // sizeOfTypeInBits returns the size in bits of the given type. 12 func (l *Lifter) sizeOfTypeInBits(t types.Type) uint64 { 13 switch t := t.(type) { 14 case *types.VoidType: 15 panic("invalid type to sizeof; void type has no size") 16 case *types.FuncType: 17 panic("invalid type to sizeof; function type has no size") 18 case *types.IntType: 19 return t.BitSize 20 case *types.FloatType: 21 switch t.Kind { 22 case types.FloatKindHalf: 23 return 16 24 case types.FloatKindFloat: 25 return 32 26 case types.FloatKindDouble: 27 return 64 28 case types.FloatKindFP128: 29 return 128 30 case types.FloatKindX86_FP80: 31 return 80 32 case types.FloatKindPPC_FP128: 33 return 128 34 default: 35 panic(fmt.Errorf("support for floating-point kind %v not yet implemented", t.Kind)) 36 } 37 case *types.PointerType: 38 return uint64(l.Mode) 39 case *types.VectorType: 40 return t.Len * l.sizeOfTypeInBits(t.ElemType) 41 case *types.LabelType: 42 panic("invalid type to sizeof; label type has no size") 43 case *types.MetadataType: 44 panic("invalid type to sizeof; metadata type has no size") 45 case *types.ArrayType: 46 return t.Len * l.sizeOfTypeInBits(t.ElemType) 47 case *types.StructType: 48 total := uint64(0) 49 for _, field := range t.Fields { 50 total += l.sizeOfTypeInBits(field) 51 } 52 return total 53 default: 54 panic(fmt.Errorf("support for type %T not yet implemented", t)) 55 } 56 } 57 58 // sizeOfType returns the size of the given type in number of bytes. 59 func (l *Lifter) sizeOfType(t types.Type) uint64 { 60 bits := l.sizeOfTypeInBits(t) 61 if bits%8 != 0 { 62 panic(fmt.Errorf("invalid type to sizeof; expected size in bits to be divisible by 8, got %d bits remainder", bits%8)) 63 } 64 return bits / 8 65 } 66 67 // parseType returns the LLVM IR type represented by the given string. 68 func (l *Lifter) parseType(typStr string) types.Type { 69 module := &ir.Module{ 70 TypeDefs: l.TypeDefs, 71 } 72 // HACK but works :) 73 s := fmt.Sprintf("%s\n\n@dummy = external global %s", module, typStr) 74 m, err := asm.ParseString("<stdin>", s) 75 if err != nil { 76 panic(fmt.Errorf("unable to parse type %q; %v", s, err)) 77 } 78 return m.Globals[0].Typ.ElemType 79 }