Coverage for /Syzygy/block_graph/basic_block_assembler.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%48480.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  E :        : 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  E :        : 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  E :        : 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  E :        : 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  E :        : 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  E :      return basic_block_ == other.basic_block_ &&
  99    :          block_ == other.block_ &&
 100    :          offset_ == other.offset_ &&
 101    :          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_t 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    :    void jmp(const Register32& dst);
 165    :    // @}
 166    :  
 167    :    // @name Conditional branch instruction.
 168    :    // @{
 169    :    void j(ConditionCode code, const Immediate& dst);
 170    :    // @}
 171    :  
 172    :   private:
 173    :    typedef BlockGraph::ReferenceType ReferenceType;
 174    :  
 175    :    class BasicBlockSerializer
 176    :        : public assm::AssemblerBase<UntypedReference>::InstructionSerializer {
 177    :     public:
 178    :      BasicBlockSerializer(const Instructions::iterator& where,
 179    :                           Instructions* list);
 180    :  
 181    :      void AppendInstruction(uint32_t location,
 182    :                             const uint8_t* bytes,
 183    :                             uint32_t num_bytes,
 184    :                             const ReferenceInfo* refs,
 185    :                             size_t num_refs) override;
 186    :      bool FinalizeLabel(uint32_t location,
 187    :                         const uint8_t* bytes,
 188    :                         size_t num_bytes) override;
 189    :  
 190  E :      SourceRange source_range() const { return source_range_; }
 191  E :      void set_source_range(const SourceRange& source_range) {
 192  E :        source_range_ = source_range;
 193  E :      }
 194    :  
 195    :      // Pushes back a reference type to be associated with a untyped reference.
 196    :      // @param type The type of the reference.
 197    :      // @param size The size of the reference, as a ValueSize.
 198    :      void PushReferenceInfo(ReferenceType type, assm::ValueSize size);
 199    :  
 200    :     private:
 201    :      Instructions::iterator where_;
 202    :      Instructions* list_;
 203    :  
 204    :      // Source range set to instructions appended by this serializer.
 205    :      SourceRange source_range_;
 206    :    };
 207    :  
 208    :    BasicBlockSerializer serializer_;
 209    :  };
 210    :  
 211    :  // @name Immediate factory functions.
 212    :  // @{
 213    :  
 214    :  // Default construction.
 215    :  BasicBlockAssembler::Immediate Immediate();
 216    :  
 217    :  // Constructs an 8- or 32-bit Immediate, depending on the minimum number of
 218    :  // bits required to represent the Immediate. If the Immediate can be encoded
 219    :  // using 8-bits to have the same representation under sign extension, then an
 220    :  // 8-bit Immediate will be created; otherwise, a 32-bit absolute Immediate will
 221    :  // be created.
 222    :  // @param value The value to be stored.
 223    :  BasicBlockAssembler::Immediate Immediate(uint32_t value);
 224    :  
 225    :  // Constructs an absolute Immediate having a specific bit width.
 226    :  // @param value The value to be stored.
 227    :  // @param size The size of the value.
 228    :  BasicBlockAssembler::Immediate Immediate(uint32_t value, assm::ValueSize size);
 229    :  
 230    :  // Constructs a 32-bit direct reference to the basic block @p bb.
 231    :  // @param bb The basic block to be referred to.
 232    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 233    :  //     references) as the BB layout algorithm will use the shortest jmp
 234    :  //     possible.
 235    :  BasicBlockAssembler::Immediate Immediate(BasicBlock* bb);
 236    :  
 237    :  // Constructs a 32-bit direct reference to @p block at the given @p offset.
 238    :  // @param block The block to be referred to.
 239    :  // @param offset The offset to be referred to, both semantically and
 240    :  //     literally. The base and offset of the reference will be set to this.
 241    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 242    :  //     references) as the BB layout algorithm will use the shortest jmp
 243    :  //     possible.
 244    :  BasicBlockAssembler::Immediate Immediate(
 245    :      BlockGraph::Block* block, BlockGraph::Offset offset);
 246    :  
 247    :  // Constructs a 32-bit reference to @p block at the given @p offset and
 248    :  // @p base.
 249    :  // @param block The block to be referred to.
 250    :  // @param offset The offset to be literally referred to.
 251    :  // @param base The offset to be semantically referred to. This must be
 252    :  //     within the data of @p block.
 253    :  BasicBlockAssembler::Immediate Immediate(
 254    :      BlockGraph::Block* block, BlockGraph::Offset offset,
 255    :      BlockGraph::Offset base);
 256    :  
 257    :  // Full constructor.
 258    :  // @param value The value to be stored.
 259    :  // @param size The size of the Immediate.
 260    :  // @param ref The untyped reference backing this Immediate. The reference must
 261    :  //     be valid.
 262    :  BasicBlockAssembler::Immediate Immediate(uint32_t value,
 263    :                                           ValueSize size,
 264    :                                           const UntypedReference& ref);
 265    :  
 266    :  // @}
 267    :  
 268    :  // @name Displacement factory functions.
 269    :  // @{
 270    :  
 271    :  // Default construction.
 272    :  BasicBlockAssembler::Displacement Displacement();
 273    :  
 274    :  // Constructs an 8- or 32-bit Displacement, depending on the minimum number of
 275    :  // bits required to represent the Displacement. If the Displacement can be
 276    :  // encoded using 8-bits to have the same representation under sign extension,
 277    :  // then an 8-bit Displacement will be created; otherwise, a 32-bit absolute
 278    :  // Displacement will be created.
 279    :  // @param value The value to be stored.
 280    :  BasicBlockAssembler::Displacement Displacement(uint32_t value);
 281    :  
 282    :  // Constructs an absolute Displacement having a specific bit width.
 283    :  // @param value The value to be stored.
 284    :  // @param size The size of the Displacement.
 285    :  BasicBlockAssembler::Displacement Displacement(uint32_t value, ValueSize size);
 286    :  
 287    :  // Constructs a 32-bit direct reference to the basic block @p bb.
 288    :  // @param bb The basic block to be referred to.
 289    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 290    :  //     references) as the BB layout algorithm will use the shortest jmp
 291    :  //     possible.
 292    :  BasicBlockAssembler::Displacement Displacement(BasicBlock* bb);
 293    :  
 294    :  // Constructs a 32-bit direct reference to @p block at the given @p offset.
 295    :  // @param block The block to be referred to.
 296    :  // @param offset The offset to be referred to, both semantically and
 297    :  //     literally. The base and offset of the reference will be set to this.
 298    :  // @note This is fine even for jmps (which may be encoded using 8-bit
 299    :  //     references) as the BB layout algorithm will use the shortest jmp
 300    :  //     possible.
 301    :  BasicBlockAssembler::Displacement Displacement(
 302    :      BlockGraph::Block* block, BlockGraph::Offset offset);
 303    :  
 304    :  // Constructs a 32-bit reference to @p block at the given @p offset and
 305    :  // @p base.
 306    :  // @param block The block to be referred to.
 307    :  // @param offset The offset to be literally referred to.
 308    :  // @param base The offset to be semantically referred to. This must be
 309    :  //     within the data of @p block.
 310    :  BasicBlockAssembler::Displacement Displacement(BlockGraph::Block* block,
 311    :                                                 BlockGraph::Offset offset,
 312    :                                                 BlockGraph::Offset base);
 313    :  
 314    :  // Full constructor.
 315    :  // @param value The value to be stored.
 316    :  // @param size The size of the Displacement.
 317    :  // @param ref The untyped reference backing this Displacement. The reference
 318    :  //     must be valid.
 319    :  BasicBlockAssembler::Displacement Displacement(uint32_t value,
 320    :                                                 ValueSize size,
 321    :                                                 const UntypedReference& ref);
 322    :  
 323    :  // @}
 324    :  
 325    :  // @name Operand factory functions.
 326    :  // @{
 327    :  
 328    :  // A register-indirect mode.
 329    :  BasicBlockAssembler::Operand Operand(const assm::Register32& base);
 330    :  
 331    :  // A register-indirect with displacement mode.
 332    :  BasicBlockAssembler::Operand Operand(
 333    :      const assm::Register32& base,
 334    :      const BasicBlockAssembler::Displacement& displ);
 335    :  
 336    :  // A displacement-only mode.
 337    :  BasicBlockAssembler::Operand Operand(
 338    :      const BasicBlockAssembler::Displacement& displ);
 339    :  
 340    :  // The full [base + index * scale + displ32] mode.
 341    :  // @note esp cannot be used as an index register.
 342    :  BasicBlockAssembler::Operand Operand(
 343    :      const assm::Register32& base, const assm::Register32& index,
 344    :      assm::ScaleFactor scale, const BasicBlockAssembler::Displacement& displ);
 345    :  
 346    :  // The full [base + index * scale] mode.
 347    :  // @note esp cannot be used as an index register.
 348    :  BasicBlockAssembler::Operand Operand(const assm::Register32& base,
 349    :                                       const assm::Register32& index,
 350    :                                       assm::ScaleFactor scale);
 351    :  
 352    :  // The [index * scale + displ32] mode.
 353    :  // @note esp cannot be used as an index register.
 354    :  BasicBlockAssembler::Operand Operand(
 355    :      const assm::Register32& index, assm::ScaleFactor scale,
 356    :      const BasicBlockAssembler::Displacement& displ);
 357    :  
 358    :  // @}
 359    :  
 360    :  }  // namespace block_graph
 361    :  
 362    :  #endif  // SYZYGY_BLOCK_GRAPH_BASIC_BLOCK_ASSEMBLER_H_

Coverage information generated Fri Jul 29 11:00:21 2016.