Coverage for /Syzygy/refinery/types/type.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%46460.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #ifndef SYZYGY_REFINERY_TYPES_TYPE_H_
  16    :  #define SYZYGY_REFINERY_TYPES_TYPE_H_
  17    :  
  18    :  #include <stdint.h>
  19    :  #include <functional>
  20    :  #include <vector>
  21    :  
  22    :  #include "base/logging.h"
  23    :  #include "base/macros.h"
  24    :  #include "base/memory/ref_counted.h"
  25    :  #include "base/strings/string16.h"
  26    :  
  27    :  namespace refinery {
  28    :  
  29    :  // fwd.
  30    :  class TypeRepository;
  31    :  typedef size_t TypeId;
  32    :  
  33    :  // A sentinel value for uninitialized types.
  34    :  const TypeId kNoTypeId = static_cast<TypeId>(-1);
  35    :  
  36    :  // A base class for all Type subclasses. Types are owned by a type repository,
  37    :  // which can vend out type instances by ID on demand.
  38    :  class Type : public base::RefCounted<Type> {
  39    :   public:
  40    :    typedef uint8_t Flags;
  41    :  
  42    :    // The set of type classes is closed, each type is enumerated here.
  43    :    enum TypeKind {
  44    :      BASIC_TYPE_KIND,
  45    :      USER_DEFINED_TYPE_KIND,
  46    :      POINTER_TYPE_KIND,
  47    :      ARRAY_TYPE_KIND,
  48    :      FUNCTION_TYPE_KIND,
  49    :      GLOBAL_TYPE_KIND,
  50    :      WILDCARD_TYPE_KIND,
  51    :    };
  52    :  
  53    :    enum CV_FLAGS {
  54    :      FLAG_CONST        = 0x0001,
  55    :      FLAG_VOLATILE     = 0x0002,
  56    :    };
  57    :  
  58    :    // @name Accessors
  59    :    // @{
  60  E :    TypeRepository* repository() const { return repository_; }
  61  E :    TypeId type_id() const { return type_id_; }
  62  E :    const base::string16& name() const { return name_; }
  63  E :    const base::string16& decorated_name() const { return decorated_name_; }
  64  E :    size_t size() const { return size_; }
  65  E :    TypeKind kind() const { return kind_; }
  66    :    // @}
  67    :  
  68    :    // Safely down-cast this to @p SubType.
  69    :    // @param out the subtype to cast this to.
  70    :    // @returns true on success, false on failure.
  71    :    template <class SubType>
  72    :    bool CastTo(scoped_refptr<SubType>* out);
  73    :  
  74    :    // Set the name of the type.
  75    :    void SetName(const base::string16& name);
  76    :  
  77    :    // Set the decorated name of the type.
  78    :    void SetDecoratedName(const base::string16& decorated_name);
  79    :  
  80    :   protected:
  81    :    friend class base::RefCounted<Type>;
  82    :  
  83    :    // This constructor will eventually be removed.
  84    :    Type(TypeKind kind, const base::string16& name, size_t size);
  85    :    // This is the way to go.
  86    :    Type(TypeKind kind,
  87    :         const base::string16& name,
  88    :         const base::string16& decorated_name,
  89    :         size_t size);
  90    :    virtual ~Type() = 0;
  91    :  
  92    :   private:
  93    :    friend class TypeRepository;
  94    :    void SetRepository(TypeRepository* repository, TypeId type_id);
  95    :  
  96    :    // The type repository this type belongs to and its ID in the repository.
  97    :    TypeRepository* repository_;
  98    :    TypeId type_id_;
  99    :  
 100    :    // The kind of this type is, synonymous with its class.
 101    :    const TypeKind kind_;
 102    :    // Size of type.
 103    :    const size_t size_;
 104    :    // Name of type.
 105    :    base::string16 name_;
 106    :    // Decorated name of type.
 107    :    base::string16 decorated_name_;
 108    :  
 109    :    DISALLOW_COPY_AND_ASSIGN(Type);
 110    :  };
 111    :  
 112    :  using TypePtr = scoped_refptr<Type>;
 113    :  
 114    :  // Constant for no type flags.
 115    :  const Type::Flags kNoTypeFlags = 0x0000;
 116    :  
 117    :  // Represents a basic type, such as e.g. an int, char, void, etc.
 118    :  class BasicType : public Type {
 119    :   public:
 120    :    static const TypeKind ID = BASIC_TYPE_KIND;
 121    :  
 122    :    // Creates a new basictype with name @p name and size @p size.
 123    :    // Sets decorated_name equal to name as basic types have no decorated names.
 124    :    BasicType(const base::string16& name, size_t size);
 125    :  
 126    :   private:
 127    :    DISALLOW_COPY_AND_ASSIGN(BasicType);
 128    :  };
 129    :  
 130    :  using BasicTypePtr = scoped_refptr<BasicType>;
 131    :  
 132    :  // Represents a user defined type such as a struct, union or a class. Also
 133    :  // represents forward references to such types.
 134    :  class UserDefinedType : public Type {
 135    :   public:
 136    :    class Field;
 137    :    class Function;
 138    :    typedef std::vector<Field> Fields;
 139    :    typedef std::vector<Function> Functions;
 140    :    static const TypeKind ID = USER_DEFINED_TYPE_KIND;
 141    :  
 142    :    enum UdtKind { UDT_CLASS, UDT_STRUCT, UDT_UNION };
 143    :  
 144    :    // Creates a new user defined type with name @p name, size @p size.
 145    :    // This creates an un-finalized UDT with no fields.
 146    :    // This will eventually be deleted.
 147    :    UserDefinedType(const base::string16& name, size_t size, UdtKind udt_kind);
 148    :  
 149    :    // Creates a new user defined type with name @p name, decorated name @p
 150    :    // decorated_name and size @p size.
 151    :    // This creates an un-finalized UDT with no fields.
 152    :    UserDefinedType(const base::string16& name,
 153    :                    const base::string16& decorated_name,
 154    :                    size_t size,
 155    :                    UdtKind udt_kind);
 156    :  
 157    :    // Retrieves the type associated with field @p field_no.
 158    :    // @pre field_no < fields().size().
 159    :    // @pre SetRepository has been called.
 160    :    TypePtr GetFieldType(size_t field_no) const;
 161    :  
 162    :    // Retrieves the type associated with function @p function_no.
 163    :    // @pre function_no < functions().size().
 164    :    // @pre SetRepository has been called.
 165    :    TypePtr GetFunctionType(size_t function_no) const;
 166    :  
 167    :    // Accessors.
 168    :    // @{
 169  E :    const Fields& fields() const { return fields_; }
 170  E :    const Functions& functions() const { return functions_; }
 171  E :    bool is_fwd_decl() const { return is_fwd_decl_; }
 172  E :    UdtKind udt_kind() const { return udt_kind_; }
 173    :    // @}
 174    :  
 175    :    // Finalize the type by providing it with a field list.
 176    :    // @param fields the fields for the type.
 177    :    // @param functions the member functions for the type.
 178    :    // @note this can only be called once per type instance. Moreover this and
 179    :    //     setting the type as a forward declaration are mutually exclusive.
 180    :    void Finalize(const Fields& fields, const Functions& functions);
 181    :  
 182    :    // Set this as forward declaration without concrete class.
 183    :    // @note this can only be called once per type instance. Moreover this and
 184    :    //     finalizing the UDT are mutually exclusive.
 185    :    void SetIsForwardDeclaration();
 186    :  
 187    :   private:
 188    :    Fields fields_;
 189    :    Functions functions_;
 190    :    bool is_fwd_decl_;
 191    :    UdtKind udt_kind_;
 192    :  
 193    :    DISALLOW_COPY_AND_ASSIGN(UserDefinedType);
 194    :  };
 195    :  
 196    :  using UserDefinedTypePtr = scoped_refptr<UserDefinedType>;
 197    :  
 198    :  // Represents a field in a user defined type.
 199    :  class UserDefinedType::Field {
 200    :   public:
 201    :    // TODO(siggi): How to represent VTables/Interfaces?
 202    :  
 203    :    // Creates a new field.
 204    :    // @param name the name of the field.
 205    :    // @param offset the byte offset of the field within the UDT.
 206    :    //    Note that many bitfield fields can share the same offset within a UDT,
 207    :    //    as can fields in a union.
 208    :    // @param flags any combination of Flags, denoting properties of the field.
 209    :    // @param bit_pos if this field is a bitfield, this is the bit position.
 210    :    // @param bit_len if this field is a bitfield, this is the bit length.
 211    :    // @param type_id the type ID of the field.
 212    :    // @note bit_pos and bit_len must be in the range 0..63.
 213    :    // @note When bit_len is zero it signifies that the field is not a bitfield.
 214    :    Field(const base::string16& name,
 215    :          ptrdiff_t offset,
 216    :          Flags flags,
 217    :          size_t bit_pos,
 218    :          size_t bit_len,
 219    :          TypeId type_id);
 220    :  
 221    :    // @name Accessors.
 222    :    // @{
 223  E :    const base::string16& name() const { return name_; }
 224  E :    ptrdiff_t offset() const { return offset_; }
 225  E :    TypeId type_id() const { return type_id_; }
 226  E :    size_t bit_pos() const { return bit_pos_; }
 227  E :    size_t bit_len() const { return bit_len_; }
 228  E :    bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
 229  E :    bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
 230    :    // @}
 231    :  
 232    :    bool operator==(const Field& o) const;
 233    :  
 234    :   private:
 235    :    const base::string16 name_;
 236    :    const ptrdiff_t offset_;
 237    :    const Flags flags_;
 238    :    const size_t bit_pos_ : 6;
 239    :    const size_t bit_len_ : 6;
 240    :    const TypeId type_id_;
 241    :  };
 242    :  
 243    :  // Represents a member function in UDT.
 244    :  class UserDefinedType::Function {
 245    :   public:
 246    :    // Creates a new member function.
 247    :    // @param name the name of the field.
 248    :    // @param type_id the type ID of the function type.
 249    :    Function(const base::string16& name, TypeId type_id);
 250    :  
 251    :    // @name Accessors.
 252    :    // @{
 253  E :    const base::string16& name() const { return name_; }
 254  E :    TypeId type_id() const { return type_id_; }
 255    :    // @}
 256    :  
 257    :    bool operator==(const Function& other) const;
 258    :  
 259    :   private:
 260    :    const base::string16 name_;
 261    :    const TypeId type_id_;
 262    :  };
 263    :  
 264    :  // Represents a pointer to some other type.
 265    :  class PointerType : public Type {
 266    :   public:
 267    :    static const TypeKind ID = POINTER_TYPE_KIND;
 268    :  
 269    :    // Enum describing two pointer modes - regular pointer or reference.
 270    :    enum Mode {
 271    :      PTR_MODE_PTR = 0x00,
 272    :      PTR_MODE_REF = 0x01,
 273    :    };
 274    :  
 275    :    // Creates a new (non-finalized) pointer type with size @p size and value @p
 276    :    // ptr_mode which determines whether this is actually pointer or reference.
 277    :    explicit PointerType(size_t size, Mode ptr_mode);
 278    :  
 279    :    // Accessors.
 280    :    // @{
 281  E :    TypeId content_type_id() const { return content_type_id_; }
 282  E :    bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
 283  E :    bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
 284  E :    Mode ptr_mode() const { return ptr_mode_; }
 285    :    // @}
 286    :  
 287    :    // Retrieves the type this pointer refers to.
 288    :    // @pre SetRepository has been called.
 289    :    TypePtr GetContentType() const;
 290    :  
 291    :    // Finalize the pointer type with @p flags and @p content_type_id.
 292    :    void Finalize(Flags flags, TypeId content_type_id);
 293    :  
 294    :   private:
 295    :    // Stores the CV qualifiers of the pointee.
 296    :    Flags flags_;
 297    :    // Stores the type this pointer points to.
 298    :    TypeId content_type_id_;
 299    :  
 300    :    // Determines whether this is a reference or an actual pointer.
 301    :    Mode ptr_mode_;
 302    :  };
 303    :  
 304    :  using PointerTypePtr = scoped_refptr<PointerType>;
 305    :  
 306    :  // Represents an array of some other type.
 307    :  class ArrayType : public Type {
 308    :   public:
 309    :    static const TypeKind ID = ARRAY_TYPE_KIND;
 310    :  
 311    :    explicit ArrayType(size_t size);
 312    :  
 313    :    // Accessors.
 314    :    // @{
 315  E :    TypeId index_type_id() const { return index_type_id_; }
 316  E :    size_t num_elements() const { return num_elements_; }
 317  E :    TypeId element_type_id() const { return element_type_id_; }
 318    :  
 319  E :    bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
 320  E :    bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
 321    :    // @}
 322    :  
 323    :    // @name Retrieve the index/element types.
 324    :    // @pre SetRepository has been called.
 325    :    // @{
 326    :    TypePtr GetIndexType() const;
 327    :    TypePtr GetElementType() const;
 328    :    // @}
 329    :  
 330    :    // Finalize the array type.
 331    :    void Finalize(Flags flags,
 332    :                  TypeId index_type_id,
 333    :                  size_t num_elements,
 334    :                  TypeId element_type_id);
 335    :  
 336    :   private:
 337    :    // The CV qualifiers for the elements.
 338    :    Flags flags_;
 339    :  
 340    :    // The type ID for the the index type.
 341    :    TypeId index_type_id_;
 342    :  
 343    :    // The number of elements in this array.
 344    :    size_t num_elements_;
 345    :  
 346    :    // The type ID for the element type.
 347    :    TypeId element_type_id_;
 348    :  };
 349    :  
 350    :  using ArrayTypePtr = scoped_refptr<ArrayType>;
 351    :  
 352    :  // Represents a function type.
 353    :  class FunctionType : public Type {
 354    :   public:
 355    :    class ArgumentType {
 356    :     public:
 357    :      // Creates a new argument.
 358    :      // @param flags any combination of Flags, denoting properties of the
 359    :      // argument.
 360    :      // @param type_id the type ID of the argument.
 361    :      ArgumentType(Flags flags, TypeId type_id);
 362    :  
 363    :      // Default assignment operator.
 364    :      ArgumentType& operator=(const ArgumentType&) = default;
 365    :  
 366    :      // @name Accessors.
 367    :      // @{
 368  E :      TypeId type_id() const { return type_id_; }
 369  E :      bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
 370  E :      bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
 371    :      // @}
 372    :  
 373    :      bool operator==(const ArgumentType& other) const;
 374    :  
 375    :     private:
 376    :      Flags flags_;
 377    :      TypeId type_id_;
 378    :    };
 379    :  
 380    :    typedef std::vector<ArgumentType> Arguments;
 381    :    enum CallConvention;
 382    :  
 383    :    static const TypeKind ID = FUNCTION_TYPE_KIND;
 384    :  
 385    :    // Creates a new (non-finalized) function type.
 386    :    // @param call_convention calling convention of this function.
 387    :    explicit FunctionType(CallConvention call_convention);
 388    :  
 389    :    // Retrieves the type associated with argument @p arg_no.
 390    :    // @pre arg_no < arguments().size().
 391    :    // @pre SetRepository has been called.
 392    :    TypePtr GetArgumentType(size_t arg_no) const;
 393    :  
 394    :    // Retrieves the type associated with the return value.
 395    :    // @pre SetRepository has been called.
 396    :    TypePtr GetReturnType() const;
 397    :  
 398    :    // Retrieves the type associated with the containing class.
 399    :    // @pre containing_class_id_ != kNoTypeId
 400    :    // @pre SetRepository has been called.
 401    :    TypePtr GetContainingClassType() const;
 402    :  
 403    :    // @name Accessors.
 404    :    // @{
 405  E :    const Arguments& argument_types() const { return arg_types_; }
 406  E :    const CallConvention call_convention() const { return call_convention_; }
 407  E :    const TypeId containing_class_id() const { return containing_class_id_; }
 408  E :    const ArgumentType& return_type() const { return return_type_; }
 409    :    // @}
 410    :  
 411    :    // @returns true if this is a member function.
 412  E :    bool IsMemberFunction() const { return containing_class_id_ != kNoTypeId; }
 413    :  
 414    :    // Finalize the type by providing it with an argument list and return value.
 415    :    // @param return_value the return value of the type.
 416    :    // @param args the arguments for the type.
 417    :    // @param containing_class_id type index of the containing class.
 418    :    // @note this can only be called once per type instance.
 419    :    void Finalize(const ArgumentType& return_type,
 420    :                  const Arguments& arg_types,
 421    :                  TypeId containing_class_id);
 422    :  
 423    :   private:
 424    :    //  Stores the arguments.
 425    :    Arguments arg_types_;
 426    :  
 427    :    // The return value.
 428    :    ArgumentType return_type_;
 429    :  
 430    :    // The calling convention of this function.
 431    :    CallConvention call_convention_;
 432    :  
 433    :    // The type index of the containing class or KNoTypeId if this is not a
 434    :    // member function.
 435    :    TypeId containing_class_id_;
 436    :  
 437    :    DISALLOW_COPY_AND_ASSIGN(FunctionType);
 438    :  };
 439    :  
 440    :  using FunctionTypePtr = scoped_refptr<FunctionType>;
 441    :  
 442    :  class GlobalType : public Type {
 443    :   public:
 444    :    static const TypeKind ID = GLOBAL_TYPE_KIND;
 445    :  
 446    :    // TODO(siggi): Does it even make sense to have size here?
 447    :    GlobalType(const base::string16& name,
 448    :               uint64_t rva,
 449    :               TypeId data_type_id,
 450    :               size_t size);
 451    :  
 452    :    // @name Accessors.
 453    :    // @{
 454  E :    uint64_t rva() const { return rva_; }
 455  E :    TypeId data_type_id() const { return data_type_id_; }
 456    :    // @}
 457    :  
 458    :    // @name Retrieve the data type.
 459    :    // @pre SetRepository has been called.
 460    :    TypePtr GetDataType() const;
 461    :  
 462    :   private:
 463    :    uint64_t rva_;
 464    :    TypeId data_type_id_;
 465    :  
 466    :    DISALLOW_COPY_AND_ASSIGN(GlobalType);
 467    :  };
 468    :  
 469    :  using GlobalTypePtr = scoped_refptr<GlobalType>;
 470    :  
 471    :  // Enum representing different calling conventions, the values are the same as
 472    :  // the ones used in the PDB stream.
 473    :  enum FunctionType::CallConvention {
 474    :    CALL_NEAR_C = 0x00,
 475    :    CALL_FAR_C = 0x01,
 476    :    CALL_NEAR_PASCAL = 0x02,
 477    :    CALL_FAR_PASCAL = 0x03,
 478    :    CALL_NEAR_FASTCALL = 0x04,
 479    :    CALL_FAR_FASTCALL = 0x05,
 480    :    CALL_SKIPPED = 0x06,
 481    :    CALL_NEAR_STDCALL = 0x07,
 482    :    CALL_FAR_STDCALL = 0x08,
 483    :    CALL_NEAR_SYSCALL = 0x09,
 484    :    CALL_FAR_SYSCALL = 0x0A,
 485    :    CALL_THIS_CALL = 0x0B,
 486    :    CALL_MIPS_CALL = 0x0C,
 487    :    CALL_GENERIC = 0x0D,
 488    :    CALL_ALPHACALL = 0x0E,
 489    :    CALL_PPCCALL = 0x0F,
 490    :    CALL_SHCALL = 0x10,
 491    :    CALL_ARMCALL = 0x11,
 492    :    CALL_AM33CALL = 0x12,
 493    :    CALL_TRICALL = 0x13,
 494    :    CALL_SH5CALL = 0x14,
 495    :    CALL_M32RCALL = 0x15,
 496    :    CALL_CLRCALL = 0x16,
 497    :    CALL_RESERVED = 0x17  // first unused call enumeration
 498    :  };
 499    :  
 500    :  // Represents an otherwise unsupported type.
 501    :  // TODO(siggi): This is a stub, which needs to go away ASAP.
 502    :  class WildcardType : public Type {
 503    :   public:
 504    :    static const TypeKind ID = WILDCARD_TYPE_KIND;
 505    :  
 506    :    // Creates a new wildcard type with name @p name, size @p size.
 507    :    WildcardType(const base::string16& name, size_t size);
 508    :    // Creates a new wildcard type with name @p name, @p decorated_name and
 509    :    // size @p size.
 510    :    WildcardType(const base::string16& name,
 511    :                 const base::string16& decorated_name,
 512    :                 size_t size);
 513    :  };
 514    :  
 515    :  using WildcardTypePtr = scoped_refptr<WildcardType>;
 516    :  
 517    :  template <class SubType>
 518  E :  bool Type::CastTo(scoped_refptr<SubType>* out) {
 519  E :    DCHECK(out);
 520  E :    if (SubType::ID != kind()) {
 521  E :      *out = nullptr;
 522  E :      return false;
 523    :    }
 524    :  
 525  E :    *out = static_cast<SubType*>(this);
 526  E :    return true;
 527  E :  }
 528    :  
 529    :  }  // namespace refinery
 530    :  
 531    :  #endif  // SYZYGY_REFINERY_TYPES_TYPE_H_

Coverage information generated Thu Jan 14 17:40:38 2016.