URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [debug/] [dwarf/] [type.go] - Rev 848
Go to most recent revision | Compare with Previous | Blame | View Log
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// DWARF type information structures.// The format is heavily biased toward C, but for simplicity// the String methods use a pseudo-Go syntax.package dwarfimport "strconv"// A Type conventionally represents a pointer to any of the// specific Type structures (CharType, StructType, etc.).type Type interface {Common() *CommonTypeString() stringSize() int64}// A CommonType holds fields common to multiple types.// If a field is not known or not applicable for a given type,// the zero value is used.type CommonType struct {ByteSize int64 // size of value of this type, in bytesName string // name that can be used to refer to type}func (c *CommonType) Common() *CommonType { return c }func (c *CommonType) Size() int64 { return c.ByteSize }// Basic types// A BasicType holds fields common to all basic types.type BasicType struct {CommonTypeBitSize int64BitOffset int64}func (b *BasicType) Basic() *BasicType { return b }func (t *BasicType) String() string {if t.Name != "" {return t.Name}return "?"}// A CharType represents a signed character type.type CharType struct {BasicType}// A UcharType represents an unsigned character type.type UcharType struct {BasicType}// An IntType represents a signed integer type.type IntType struct {BasicType}// A UintType represents an unsigned integer type.type UintType struct {BasicType}// A FloatType represents a floating point type.type FloatType struct {BasicType}// A ComplexType represents a complex floating point type.type ComplexType struct {BasicType}// A BoolType represents a boolean type.type BoolType struct {BasicType}// An AddrType represents a machine address type.type AddrType struct {BasicType}// qualifiers// A QualType represents a type that has the C/C++ "const", "restrict", or "volatile" qualifier.type QualType struct {CommonTypeQual stringType Type}func (t *QualType) String() string { return t.Qual + " " + t.Type.String() }func (t *QualType) Size() int64 { return t.Type.Size() }// An ArrayType represents a fixed size array type.type ArrayType struct {CommonTypeType TypeStrideBitSize int64 // if > 0, number of bits to hold each elementCount int64 // if == -1, an incomplete array, like char x[].}func (t *ArrayType) String() string {return "[" + strconv.FormatInt(t.Count, 10) + "]" + t.Type.String()}func (t *ArrayType) Size() int64 { return t.Count * t.Type.Size() }// A VoidType represents the C void type.type VoidType struct {CommonType}func (t *VoidType) String() string { return "void" }// A PtrType represents a pointer type.type PtrType struct {CommonTypeType Type}func (t *PtrType) String() string { return "*" + t.Type.String() }// A StructType represents a struct, union, or C++ class type.type StructType struct {CommonTypeStructName stringKind string // "struct", "union", or "class".Field []*StructFieldIncomplete bool // if true, struct, union, class is declared but not defined}// A StructField represents a field in a struct, union, or C++ class type.type StructField struct {Name stringType TypeByteOffset int64ByteSize int64BitOffset int64 // within the ByteSize bytes at ByteOffsetBitSize int64 // zero if not a bit field}func (t *StructType) String() string {if t.StructName != "" {return t.Kind + " " + t.StructName}return t.Defn()}func (t *StructType) Defn() string {s := t.Kindif t.StructName != "" {s += " " + t.StructName}if t.Incomplete {s += " /*incomplete*/"return s}s += " {"for i, f := range t.Field {if i > 0 {s += "; "}s += f.Name + " " + f.Type.String()s += "@" + strconv.FormatInt(f.ByteOffset, 10)if f.BitSize > 0 {s += " : " + strconv.FormatInt(f.BitSize, 10)s += "@" + strconv.FormatInt(f.BitOffset, 10)}}s += "}"return s}// An EnumType represents an enumerated type.// The only indication of its native integer type is its ByteSize// (inside CommonType).type EnumType struct {CommonTypeEnumName stringVal []*EnumValue}// An EnumValue represents a single enumeration value.type EnumValue struct {Name stringVal int64}func (t *EnumType) String() string {s := "enum"if t.EnumName != "" {s += " " + t.EnumName}s += " {"for i, v := range t.Val {if i > 0 {s += "; "}s += v.Name + "=" + strconv.FormatInt(v.Val, 10)}s += "}"return s}// A FuncType represents a function type.type FuncType struct {CommonTypeReturnType TypeParamType []Type}func (t *FuncType) String() string {s := "func("for i, t := range t.ParamType {if i > 0 {s += ", "}s += t.String()}s += ")"if t.ReturnType != nil {s += " " + t.ReturnType.String()}return s}// A DotDotDotType represents the variadic ... function parameter.type DotDotDotType struct {CommonType}func (t *DotDotDotType) String() string { return "..." }// A TypedefType represents a named type.type TypedefType struct {CommonTypeType Type}func (t *TypedefType) String() string { return t.Name }func (t *TypedefType) Size() int64 { return t.Type.Size() }func (d *Data) Type(off Offset) (Type, error) {if t, ok := d.typeCache[off]; ok {return t, nil}r := d.Reader()r.Seek(off)e, err := r.Next()if err != nil {return nil, err}if e == nil || e.Offset != off {return nil, DecodeError{"info", off, "no type at offset"}}// Parse type from Entry.// Must always set d.typeCache[off] before calling// d.Type recursively, to handle circular types correctly.var typ Type// Get next child; set err if error happens.next := func() *Entry {if !e.Children {return nil}kid, err1 := r.Next()if err1 != nil {err = err1return nil}if kid == nil {err = DecodeError{"info", r.b.off, "unexpected end of DWARF entries"}return nil}if kid.Tag == 0 {return nil}return kid}// Get Type referred to by Entry's AttrType field.// Set err if error happens. Not having a type is an error.typeOf := func(e *Entry) Type {toff, ok := e.Val(AttrType).(Offset)if !ok {// It appears that no Type means "void".return new(VoidType)}var t Typeif t, err = d.Type(toff); err != nil {return nil}return t}switch e.Tag {case TagArrayType:// Multi-dimensional array. (DWARF v2 §5.4)// Attributes:// AttrType:subtype [required]// AttrStrideSize: size in bits of each element of the array// AttrByteSize: size of entire array// Children:// TagSubrangeType or TagEnumerationType giving one dimension.// dimensions are in left to right order.t := new(ArrayType)typ = td.typeCache[off] = tif t.Type = typeOf(e); err != nil {goto Error}t.StrideBitSize, _ = e.Val(AttrStrideSize).(int64)// Accumulate dimensions,ndim := 0for kid := next(); kid != nil; kid = next() {// TODO(rsc): Can also be TagEnumerationType// but haven't seen that in the wild yet.switch kid.Tag {case TagSubrangeType:max, ok := kid.Val(AttrUpperBound).(int64)if !ok {max = -2 // Count == -1, as in x[].}if ndim == 0 {t.Count = max + 1} else {// Multidimensional array.// Create new array type underneath this one.t.Type = &ArrayType{Type: t.Type, Count: max + 1}}ndim++case TagEnumerationType:err = DecodeError{"info", kid.Offset, "cannot handle enumeration type as array bound"}goto Error}}if ndim == 0 {// LLVM generates this for x[].t.Count = -1}case TagBaseType:// Basic type. (DWARF v2 §5.1)// Attributes:// AttrName: name of base type in programming language of the compilation unit [required]// AttrEncoding: encoding value for type (encFloat etc) [required]// AttrByteSize: size of type in bytes [required]// AttrBitOffset: for sub-byte types, size in bits// AttrBitSize: for sub-byte types, bit offset of high order bit in the AttrByteSize bytesname, _ := e.Val(AttrName).(string)enc, ok := e.Val(AttrEncoding).(int64)if !ok {err = DecodeError{"info", e.Offset, "missing encoding attribute for " + name}goto Error}switch enc {default:err = DecodeError{"info", e.Offset, "unrecognized encoding attribute value"}goto Errorcase encAddress:typ = new(AddrType)case encBoolean:typ = new(BoolType)case encComplexFloat:typ = new(ComplexType)case encFloat:typ = new(FloatType)case encSigned:typ = new(IntType)case encUnsigned:typ = new(UintType)case encSignedChar:typ = new(CharType)case encUnsignedChar:typ = new(UcharType)}d.typeCache[off] = typt := typ.(interface {Basic() *BasicType}).Basic()t.Name = namet.BitSize, _ = e.Val(AttrBitSize).(int64)t.BitOffset, _ = e.Val(AttrBitOffset).(int64)case TagClassType, TagStructType, TagUnionType:// Structure, union, or class type. (DWARF v2 §5.5)// Attributes:// AttrName: name of struct, union, or class// AttrByteSize: byte size [required]// AttrDeclaration: if true, struct/union/class is incomplete// Children:// TagMember to describe one member.// AttrName: name of member [required]// AttrType: type of member [required]// AttrByteSize: size in bytes// AttrBitOffset: bit offset within bytes for bit fields// AttrBitSize: bit size for bit fields// AttrDataMemberLoc: location within struct [required for struct, class]// There is much more to handle C++, all ignored for now.t := new(StructType)typ = td.typeCache[off] = tswitch e.Tag {case TagClassType:t.Kind = "class"case TagStructType:t.Kind = "struct"case TagUnionType:t.Kind = "union"}t.StructName, _ = e.Val(AttrName).(string)t.Incomplete = e.Val(AttrDeclaration) != nilt.Field = make([]*StructField, 0, 8)for kid := next(); kid != nil; kid = next() {if kid.Tag == TagMember {f := new(StructField)if f.Type = typeOf(kid); err != nil {goto Error}if loc, ok := kid.Val(AttrDataMemberLoc).([]byte); ok {b := makeBuf(d, "location", 0, loc, d.addrsize)if b.uint8() != opPlusUconst {err = DecodeError{"info", kid.Offset, "unexpected opcode"}goto Error}f.ByteOffset = int64(b.uint())if b.err != nil {err = b.errgoto Error}}f.Name, _ = kid.Val(AttrName).(string)f.ByteSize, _ = kid.Val(AttrByteSize).(int64)f.BitOffset, _ = kid.Val(AttrBitOffset).(int64)f.BitSize, _ = kid.Val(AttrBitSize).(int64)t.Field = append(t.Field, f)}}case TagConstType, TagVolatileType, TagRestrictType:// Type modifier (DWARF v2 §5.2)// Attributes:// AttrType: subtypet := new(QualType)typ = td.typeCache[off] = tif t.Type = typeOf(e); err != nil {goto Error}switch e.Tag {case TagConstType:t.Qual = "const"case TagRestrictType:t.Qual = "restrict"case TagVolatileType:t.Qual = "volatile"}case TagEnumerationType:// Enumeration type (DWARF v2 §5.6)// Attributes:// AttrName: enum name if any// AttrByteSize: bytes required to represent largest value// Children:// TagEnumerator:// AttrName: name of constant// AttrConstValue: value of constantt := new(EnumType)typ = td.typeCache[off] = tt.EnumName, _ = e.Val(AttrName).(string)t.Val = make([]*EnumValue, 0, 8)for kid := next(); kid != nil; kid = next() {if kid.Tag == TagEnumerator {f := new(EnumValue)f.Name, _ = kid.Val(AttrName).(string)f.Val, _ = kid.Val(AttrConstValue).(int64)n := len(t.Val)if n >= cap(t.Val) {val := make([]*EnumValue, n, n*2)copy(val, t.Val)t.Val = val}t.Val = t.Val[0 : n+1]t.Val[n] = f}}case TagPointerType:// Type modifier (DWARF v2 §5.2)// Attributes:// AttrType: subtype [not required! void* has no AttrType]// AttrAddrClass: address class [ignored]t := new(PtrType)typ = td.typeCache[off] = tif e.Val(AttrType) == nil {t.Type = &VoidType{}break}t.Type = typeOf(e)case TagSubroutineType:// Subroutine type. (DWARF v2 §5.7)// Attributes:// AttrType: type of return value if any// AttrName: possible name of type [ignored]// AttrPrototyped: whether used ANSI C prototype [ignored]// Children:// TagFormalParameter: typed parameter// AttrType: type of parameter// TagUnspecifiedParameter: final ...t := new(FuncType)typ = td.typeCache[off] = tif t.ReturnType = typeOf(e); err != nil {goto Error}t.ParamType = make([]Type, 0, 8)for kid := next(); kid != nil; kid = next() {var tkid Typeswitch kid.Tag {default:continuecase TagFormalParameter:if tkid = typeOf(kid); err != nil {goto Error}case TagUnspecifiedParameters:tkid = &DotDotDotType{}}t.ParamType = append(t.ParamType, tkid)}case TagTypedef:// Typedef (DWARF v2 §5.3)// Attributes:// AttrName: name [required]// AttrType: type definition [required]t := new(TypedefType)typ = td.typeCache[off] = tt.Name, _ = e.Val(AttrName).(string)t.Type = typeOf(e)}if err != nil {goto Error}{b, ok := e.Val(AttrByteSize).(int64)if !ok {b = -1}typ.Common().ByteSize = b}return typ, nilError:// If the parse fails, take the type out of the cache// so that the next call with this offset doesn't hit// the cache and return success.delete(d.typeCache, off)return nil, err}
Go to most recent revision | Compare with Previous | Blame | View Log
