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  }