Coverage for /Syzygy/block_graph/basic_block_assembler.h

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

Line-by-line coverage:

   1    :  // Copyright 2012 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    :  // Provides an assembler that assembles to basic block instruction lists.
  16    :  
  17    :  #ifndef SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_
  18    :  #define SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_
  19    :  
  20    :  #include "syzygy/assm/assembler_base.h"
  21    :  #include "syzygy/block_graph/basic_block.h"
  22    :  #include "syzygy/block_graph/block_graph.h"
  23    :  
  24    :  namespace block_graph {
  25    :  
  26    :  using assm::ValueSize;
  27    :  
  28    :  // Declares a BasicBlockReference-like class that has no type or size
  29    :  // information. The size information is stored in the Operand or Value housing
  30    :  // the untyped reference, and the type is inferred from the instruction being
  31    :  // assembled.
  32    :  class UntypedReference {
  33    :   public:
  34    :    typedef BlockGraph::Block Block;
  35    :    typedef BlockGraph::Offset Offset;
  36    :  
  37    :    // Default constructor.
  38  E :    UntypedReference()
  39    :        : basic_block_(NULL), block_(NULL), offset_(0), base_(0) {
  40  E :    }
  41    :  
  42    :    // Copy constructor.
  43    :    // @param other The reference to be copied.
  44    :    UntypedReference(const UntypedReference& other)
  45    :        : basic_block_(other.basic_block_), block_(other.block_),
  46  E :          offset_(other.offset_), base_(other.base_) {
  47  E :    }
  48    :  
  49    :    // Constructor from a basic block reference.
  50    :    // @param bb_ref The basic block reference to be copied.
  51    :    explicit UntypedReference(const BasicBlockReference& bb_ref)
  52    :        : basic_block_(bb_ref.basic_block()), block_(bb_ref.block()),
  53  E :          offset_(bb_ref.offset()), base_(bb_ref.base()) {
  54  E :      DCHECK(block_ != NULL || basic_block_ != NULL);
  55  E :    }
  56    :  
  57    :    // Constructs a reference to a basic block.
  58    :    // @param basic_block The basic block to be referred to.
  59  E :    explicit UntypedReference(BasicBlock* basic_block)
  60    :        : basic_block_(basic_block), block_(NULL), offset_(0), base_(0) {
  61  E :      DCHECK(basic_block != NULL);
  62  E :    }
  63    :  
  64    :    // Constructs a reference to a block.
  65    :    // @param block The block to be referred to.
  66    :    // @param offset The offset from the start of the block actually being
  67    :    //     pointed to.
  68    :    // @param base The offset from the start of the block semantically being
  69    :    //     referred to.
  70  E :    UntypedReference(Block* block, Offset offset, Offset base)
  71    :        : basic_block_(NULL), block_(block), offset_(offset), base_(base) {
  72  E :      DCHECK(block != NULL);
  73  E :    }
  74    :  
  75    :    // @name Accessors.
  76    :    // @{
  77  E :    BasicBlock* basic_block() const { return basic_block_; }
  78  E :    Block* block() const { return block_; }
  79  E :    Offset offset() const { return offset_; }
  80  E :    Offset base() const { return base_; }
  81    :    // @}
  82    :  
  83    :    // @returns true if this reference is valid.
  84  E :    bool IsValid() const { return block_ != NULL || basic_block_ != NULL; }
  85    :  
  86    :    // Returns the type of the object being referred to.
  87  E :    BasicBlockReference::ReferredType referred_type() const {
  88  E :      if (block_ != NULL)
  89  E :        return BasicBlockReference::REFERRED_TYPE_BLOCK;
  90  E :      if (basic_block_ != NULL)
  91  E :        return BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK;
  92  E :      return BasicBlockReference::REFERRED_TYPE_UNKNOWN;
  93  E :    }
  94    :  
  95    :    // Comparison operator.
  96    :    // @returns true if this reference is the same as the @p other.
  97  E :    bool operator==(const UntypedReference& other) const {
  98    :      return basic_block_ == other.basic_block_ &&
  99    :          block_ == other.block_ &&
 100    :          offset_ == other.offset_ &&
 101  E :          base_ == other.base_;
 102  E :    }
 103    :  
 104    :    // Assignment operator.
 105  E :    const UntypedReference& operator=(const UntypedReference& other) {
 106  E :      basic_block_ = other.basic_block_;
 107  E :      block_ = other.block_;
 108  E :      offset_ = other.offset_;
 109  E :      base_ = other.base_;
 110    :  
 111  E :      return *this;
 112  E :    }
 113    :  
 114    :   private:
 115    :    BasicBlock* basic_block_;
 116    :    Block* block_;
 117    :    Offset offset_;
 118    :    Offset base_;
 119    :  };
 120    :  
 121    :  class BasicBlockAssembler : public assm::AssemblerBase<UntypedReference> {
 122    :   public:
 123    :    typedef assm::AssemblerBase<UntypedReference> Super;
 124    :  
 125    :    typedef BlockGraph::Block::SourceRange SourceRange;
 126    :    typedef BasicBlock::Instructions Instructions;
 127    :    typedef assm::Register8 Register8;
 128    :    typedef assm::Register16 Register16;
 129    :    typedef assm::Register32 Register32;
 130    :    typedef assm::ConditionCode ConditionCode;
 131    :  
 132    :    // Constructs a basic block assembler that inserts new instructions
 133    :    // into @p *list at @p where.
 134    :    BasicBlockAssembler(const Instructions::iterator& where,
 135    :                        Instructions *list);
 136    :  
 137    :    // Constructs a basic block assembler that inserts new instructions into
 138    :    // @p *list at @p where, assuming a starting address of @p location.
 139    :    BasicBlockAssembler(uint32 location,
 140    :                        const Instructions::iterator& where,
 141    :                        Instructions *list);
 142    :  
 143    :    // @returns The source range injected into created instructions.
 144  E :    SourceRange source_range() const { return serializer_.source_range(); }
 145    :  
 146    :    // Set the SourceRange injected repeatedly into each instruction created via
 147    :    // the assembler. This should be used with care because it causes the OMAP
 148    :    // information to no longer be 1:1 mapping, and may confuse some debuggers.
 149    :    // @param source_range The source range set to each created instructions.
 150  E :    void set_source_range(const SourceRange& source_range) {
 151  E :      serializer_.set_source_range(source_range);
 152  E :    }
 153    :  
 154    :    // @name Call instructions.
 155    :    // @{
 156    :    void call(const Immediate& dst);
 157    :    void call(const Operand& dst);
 158    :    // @}
 159    :  
 160    :    // @name Jmp instructions.
 161    :    // @{
 162    :    void jmp(const Immediate& dst);
 163    :    void jmp(const Operand& dst);
 164    :    // @}
 165    :  
 166    :    // @name Conditional branch instruction.
 167    :    // @{
 168    :    void j(ConditionCode code, const Immediate& dst);
 169    :    // @}
 170    :  
 171    :   private:
 172    :    typedef BlockGraph::ReferenceType ReferenceType;
 173    :  
 174    :    class BasicBlockSerializer
 175    :        : public assm::AssemblerBase<UntypedReference>::InstructionSerializer {
 176    :     public:
 177    :      BasicBlockSerializer(const Instructions::iterator& where,
 178    :                           Instructions* list);
 179    :  
 180    :      void AppendInstruction(uint32 location,
 181    :                             const uint8* bytes,
 182    :                             size_t num_bytes,
 183    :                             const ReferenceInfo* refs,
 184    :                             size_t num_refs) override;
 185    :      bool FinalizeLabel(uint32 location,
 186    :                         const uint8* bytes,
 187    :                         size_t num_bytes) override;
 188    :  
 189  E :      SourceRange source_range() const { return source_range_; }
 190  E :      void set_source_range(const SourceRange& source_range) {
 191  E :        source_range_ = source_range;
 192  E :      }
 193    :  
 194    :      // Pushes back a reference type to be associated with a untyped reference.
 195    :      // @param type The type of the reference.
 196    :      // @param size The size of the reference, as a ValueSize.
 197    :      void PushReferenceInfo(ReferenceType type, assm::ValueSize size);
 198    :  
 199    :     private:
 200    :      Instructions::iterator where_;
 201    :      Instructions* list_;
 202    :  
 203    :      // Source range set to instructions appended by this serializer.
 204    :      SourceRange source_range_;
 205    :    };
 206    :  
 207    :    BasicBlockSerializer serializer_;
 208    :  };
 209    :  
 210    :  // @name Immediate factory functions.
 211    :  // @{
 212    :  
 213    :  // Default construction.
 214    :  BasicBlockAssembler::Immediate Immediate();
 215    :  
 216    :  // Constructs an 8- or 32-bit Immediate, depending on the minimum number of
 217    :  // bits required to represent the Immediate. If the Immediate can be encoded
 218    :  // using 8-bits to have the same representation under sign extension, then an
 219    :  // 8-bit Immediate will be created; otherwise, a 32-bit absolute Immediate will
 220    :  // be created.
 221    :  // @param value The value to be stored.
 222    :  BasicBlockAssembler::Immediate Immediate(uint32 value);
 223    :  
 224    :  // Constructs an absolute Immediate having a specific bit width.
 225    :  // @param value The value to be stored.
 226    :  // @param size The size of the value.
 227    :  BasicBlockAssembler::Immediate Immediate(uint32 value, assm::ValueSize size);
 228    :  
 229    :  // Constructs a 32-bit direct reference to the basic block @p bb.
 230    :  // @param bb The basic block to be referred to.
 231    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 232    :  //     references) as the BB layout algorithm will use the shortest jmp
 233    :  //     possible.
 234    :  BasicBlockAssembler::Immediate Immediate(BasicBlock* bb);
 235    :  
 236    :  // Constructs a 32-bit direct reference to @p block at the given @p offset.
 237    :  // @param block The block to be referred to.
 238    :  // @param offset The offset to be referred to, both semantically and
 239    :  //     literally. The base and offset of the reference will be set to this.
 240    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 241    :  //     references) as the BB layout algorithm will use the shortest jmp
 242    :  //     possible.
 243    :  BasicBlockAssembler::Immediate Immediate(
 244    :      BlockGraph::Block* block, BlockGraph::Offset offset);
 245    :  
 246    :  // Constructs a 32-bit reference to @p block at the given @p offset and
 247    :  // @p base.
 248    :  // @param block The block to be referred to.
 249    :  // @param offset The offset to be literally referred to.
 250    :  // @param base The offset to be semantically referred to. This must be
 251    :  //     within the data of @p block.
 252    :  BasicBlockAssembler::Immediate Immediate(
 253    :      BlockGraph::Block* block, BlockGraph::Offset offset,
 254    :      BlockGraph::Offset base);
 255    :  
 256    :  // Full constructor.
 257    :  // @param value The value to be stored.
 258    :  // @param size The size of the Immediate.
 259    :  // @param ref The untyped reference backing this Immediate. The reference must
 260    :  //     be valid.
 261    :  BasicBlockAssembler::Immediate Immediate(
 262    :      uint32 value, ValueSize size, const UntypedReference& ref);
 263    :  
 264    :  // @}
 265    :  
 266    :  // @name Displacement factory functions.
 267    :  // @{
 268    :  
 269    :  // Default construction.
 270    :  BasicBlockAssembler::Displacement Displacement();
 271    :  
 272    :  // Constructs an 8- or 32-bit Displacement, depending on the minimum number of
 273    :  // bits required to represent the Displacement. If the Displacement can be
 274    :  // encoded using 8-bits to have the same representation under sign extension,
 275    :  // then an 8-bit Displacement will be created; otherwise, a 32-bit absolute
 276    :  // Displacement will be created.
 277    :  // @param value The value to be stored.
 278    :  BasicBlockAssembler::Displacement Displacement(uint32 value);
 279    :  
 280    :  // Constructs an absolute Displacement having a specific bit width.
 281    :  // @param value The value to be stored.
 282    :  // @param size The size of the Displacement.
 283    :  BasicBlockAssembler::Displacement Displacement(uint32 value, ValueSize size);
 284    :  
 285    :  // Constructs a 32-bit direct reference to the basic block @p bb.
 286    :  // @param bb The basic block to be referred to.
 287    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 288    :  //     references) as the BB layout algorithm will use the shortest jmp
 289    :  //     possible.
 290    :  BasicBlockAssembler::Displacement Displacement(BasicBlock* bb);
 291    :  
 292    :  // Constructs a 32-bit direct reference to @p block at the given @p offset.
 293    :  // @param block The block to be referred to.
 294    :  // @param offset The offset to be referred to, both semantically and
 295    :  //     literally. The base and offset of the reference will be set to this.
 296    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 297    :  //     references) as the BB layout algorithm will use the shortest jmp
 298    :  //     possible.
 299    :  BasicBlockAssembler::Displacement Displacement(
 300    :      BlockGraph::Block* block, BlockGraph::Offset offset);
 301    :  
 302    :  // Constructs a 32-bit reference to @p block at the given @p offset and
 303    :  // @p base.
 304    :  // @param block The block to be referred to.
 305    :  // @param offset The offset to be literally referred to.
 306    :  // @param base The offset to be semantically referred to. This must be
 307    :  //     within the data of @p block.
 308    :  BasicBlockAssembler::Displacement Displacement(BlockGraph::Block* block,
 309    :                                                 BlockGraph::Offset offset,
 310    :                                                 BlockGraph::Offset base);
 311    :  
 312    :  // Full constructor.
 313    :  // @param value The value to be stored.
 314    :  // @param size The size of the Displacement.
 315    :  // @param ref The untyped reference backing this Displacement. The reference
 316    :  //     must be valid.
 317    :  BasicBlockAssembler::Displacement Displacement(
 318    :      uint32 value, ValueSize size, const UntypedReference& ref);
 319    :  
 320    :  // @}
 321    :  
 322    :  // @name Operand factory functions.
 323    :  // @{
 324    :  
 325    :  // A register-indirect mode.
 326    :  BasicBlockAssembler::Operand Operand(const assm::Register32& base);
 327    :  
 328    :  // A register-indirect with displacement mode.
 329    :  BasicBlockAssembler::Operand Operand(
 330    :      const assm::Register32& base,
 331    :      const BasicBlockAssembler::Displacement& displ);
 332    :  
 333    :  // A displacement-only mode.
 334    :  BasicBlockAssembler::Operand Operand(
 335    :      const BasicBlockAssembler::Displacement& displ);
 336    :  
 337    :  // The full [base + index * scale + displ32] mode.
 338    :  // @note esp cannot be used as an index register.
 339    :  BasicBlockAssembler::Operand Operand(
 340    :      const assm::Register32& base, const assm::Register32& index,
 341    :      assm::ScaleFactor scale, const BasicBlockAssembler::Displacement& displ);
 342    :  
 343    :  // The full [base + index * scale] mode.
 344    :  // @note esp cannot be used as an index register.
 345    :  BasicBlockAssembler::Operand Operand(const assm::Register32& base,
 346    :                                       const assm::Register32& index,
 347    :                                       assm::ScaleFactor scale);
 348    :  
 349    :  // The [index * scale + displ32] mode.
 350    :  // @note esp cannot be used as an index register.
 351    :  BasicBlockAssembler::Operand Operand(
 352    :      const assm::Register32& index, assm::ScaleFactor scale,
 353    :      const BasicBlockAssembler::Displacement& displ);
 354    :  
 355    :  // @}
 356    :  
 357    :  }  // namespace block_graph
 358    :  
 359    :  #endif  // SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_

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