Source code for ducky.cc.types

import collections

from pycparser import c_ast

import ducky.cpu
import ducky.util

from . import dump_node, UndefinedStructMemberError

[docs]class CType(object): types = {} def __init__(self, visitor, decl = None): self.visitor = visitor self.decl = decl def __repr__(self): raise NotImplementedError('Type %s does not provide its representation' % self.__class__.__name__) def __len__(self): raise NotImplementedError('Type %s does not provide its size' % self.__class__.__name__) def __cmp__(self, other): return 0 if repr(self) == repr(other) else -1 def __eq__(self, other): return repr(self) == repr(other) def __neq__(self, other): return repr(self) != repr(other) @staticmethod
[docs] def get_from_desc(visitor, desc): visitor.DEBUG(visitor.log_prefix + 'Type.get_from_desc: desc=%s', desc) visitor.DOWN() T = visitor.types.get(desc) if T is None: raise RuntimeError('Unknown type: %s' % desc) visitor.UP() return T
@staticmethod
[docs] def get_from_decl(visitor, decl): visitor.DEBUG(visitor.log_prefix + 'Type.get_from_decl: decl=%s', dump_node(decl)) visitor.DOWN() T = None if isinstance(decl, c_ast.PtrDecl): T = PointerType(CType.get_from_decl(visitor, decl.type), visitor, decl) elif isinstance(decl.type, c_ast.IdentifierType): name = ' '.join(decl.type.names) elif isinstance(decl.type, c_ast.Struct): name = 'struct ' + decl.type.name elif isinstance(decl.type, c_ast.PtrDecl): T = PointerType(CType.get_from_decl(visitor, decl.type), visitor, decl) elif isinstance(decl, c_ast.ArrayDecl): T = ArrayType(CType.get_from_decl(visitor, decl.type), visitor, decl) else: visitor.WARN(visitor.log_prefix + 'Unhandled get_from_decl branch: %s', decl.type.__class__.__name__) visitor.UP() return None if T is None: visitor.DEBUG(visitor.log_prefix + 'searching for "%s"', name) visitor.DEBUG(visitor.log_prefix + 'known types: %s', visitor.types) T = visitor.types.get(name) if T is None: raise RuntimeError('Unknown type: %s' % name) visitor.UP() return T
@staticmethod
[docs] def create_from_decl(visitor, decl): visitor.DEBUG(visitor.log_prefix + 'Type.create_from_decl: decl=%s', dump_node(decl)) visitor.DOWN() T = None if isinstance(decl, c_ast.PtrDecl): T = PointerType(CType.get_from_decl(visitor, decl.type), visitor, decl) elif isinstance(decl, c_ast.FuncDecl): T = FunctionType(visitor, decl) elif isinstance(decl, c_ast.ArrayDecl): T = ArrayType(CType.get_from_decl(visitor, decl.type), visitor, decl) elif isinstance(decl.type, c_ast.Struct): if decl.type.decls is None and decl.type.name is not None: T = CType.get_from_decl(visitor, decl) else: name = visitor.get_new_label() if decl.type.name is None else decl.type.name visitor.DEBUG(visitor.log_prefix + 'Type.create_from_decl: struct: %s', dump_node(decl.type)) T = StructType(name, visitor, decl.type) elif isinstance(decl.type, c_ast.IdentifierType): T = CType.get_from_decl(visitor, decl) else: visitor.WARN(visitor.log_prefix + 'Unhandled branch') visitor.DEBUG(visitor.log_prefix + 'Type.create_from_decl: %s => %s', dump_node(decl), T) visitor.UP() return T
[docs]class VoidType(CType): def __repr__(self): return 'void' def __len__(self): return 0
[docs]class IntType(CType): def __repr__(self): return 'int' def __len__(self): return 4
[docs]class UnsignedIntType(IntType): def __repr__(self): return 'unsigned int'
[docs]class CharType(CType): def __repr__(self): return 'char' def __len__(self): return 1
[docs]class UnsignedCharType(CharType): def __repr__(self): return 'unsigned char'
[docs]class PointerType(CType): def __init__(self, ptr_to_type, *args, **kwargs): super(PointerType, self).__init__(*args, **kwargs) self.ptr_to_type = ptr_to_type def __repr__(self): return repr(self.ptr_to_type) + '*' def __len__(self): return 4
[docs]class StructType(CType): def __init__(self, name, *args, **kwargs): super(StructType, self).__init__(*args, **kwargs) self.name = name self.fields = collections.OrderedDict() self._size = 0 class Field(object): def __init__(self, name, type, offset): self.name = name self.type = type self.offset = offset field_offset = 0 for field in self.decl.decls: if isinstance(field.type, c_ast.PtrDecl): field_type = PointerType(CType.get_from_decl(self.visitor, field.type.type), self.visitor, field.type.type) else: field_type = CType.get_from_decl(self.visitor, field.type) self.fields[field.name] = field = Field(field.name, field_type, field_offset) field_offset = ducky.util.align(4, field_offset + len(field.type)) self._size = ducky.util.align(4, field_offset) def __repr__(self): return 'struct %s' % self.name def __len__(self): return self._size
[docs] def field_offset(self, name): if name not in self.fields: raise UndefinedStructMemberError(None, self, name) return self.fields[name].offset
[docs] def field_type(self, name): return self.fields[name].type
[docs]class FunctionType(CType): def __init__(self, *args, **kwargs): super(FunctionType, self).__init__(*args, **kwargs) self.rtype = None self.args = [] self.visitor.DEBUG(self.visitor.log_prefix + 'create rtype') self.rtype = CType.get_from_decl(self.visitor, self.decl.type) if self.decl.args is not None: for arg in self.decl.args.params: self.args.append(CType.get_from_decl(self.visitor, arg.type)) def __repr__(self): return '%s(%s)' % (repr(self.rtype), ', '.join([repr(param) for param in self.args]))
[docs]class ArrayType(CType): def __init__(self, item_type, size = None, *args, **kwargs): super(ArrayType, self).__init__(*args, **kwargs) self.item_type = item_type self.size = None def __repr__(self): return repr(self.item_type) + '[]' def __len__(self): if self.size is not None: return self.size return 4