Global Metrics

path: .metrics.cyclomatic.average
old: 3.4166666666666665
new: 2.7096774193548385

path: .metrics.cyclomatic.sum
old: 41.0
new: 84.0

path: .metrics.nargs.average
old: 1.3636363636363635
new: 0.6666666666666666

path: .metrics.nargs.sum
old: 15.0
new: 18.0

path: .metrics.nom.total
old: 11.0
new: 27.0

path: .metrics.nom.closures
old: 3.0
new: 0.0

path: .metrics.nom.functions
old: 8.0
new: 27.0

path: .metrics.cognitive.sum
old: 30.0
new: 58.0

path: .metrics.cognitive.average
old: 2.727272727272727
new: 2.1481481481481484

path: .metrics.nexits.average
old: 1.0
new: 0.8148148148148148

path: .metrics.nexits.sum
old: 11.0
new: 22.0

path: .metrics.halstead.purity_ratio
old: 1.4832459377145806
new: 0.8856739178023794

path: .metrics.halstead.n1
old: 26.0
new: 42.0

path: .metrics.halstead.level
old: 0.033268790705861646
new: 0.012274475007394262

path: .metrics.halstead.vocabulary
old: 215.0
new: 208.0

path: .metrics.halstead.time
old: 13533.888249009273
new: 57089.20454265513

path: .metrics.halstead.n2
old: 189.0
new: 166.0

path: .metrics.halstead.volume
old: 8104.609720670575
new: 12613.320258315109

path: .metrics.halstead.N2
old: 437.0
new: 644.0

path: .metrics.halstead.difficulty
old: 30.058201058201057
new: 81.46987951807229

path: .metrics.halstead.length
old: 1046.0
new: 1638.0

path: .metrics.halstead.N1
old: 609.0
new: 994.0

path: .metrics.halstead.effort
old: 243609.98848216687
new: 1027605.6817677924

path: .metrics.halstead.estimated_program_length
old: 1551.4752508494512
new: 1450.7338773602974

path: .metrics.halstead.bugs
old: 1.300195941597515
new: 3.394400451525694

path: .metrics.loc.ploc
old: 227.0
new: 322.0

path: .metrics.loc.sloc
old: 301.0
new: 494.0

path: .metrics.loc.cloc
old: 35.0
new: 101.0

path: .metrics.loc.blank
old: 39.0
new: 71.0

path: .metrics.loc.lloc
old: 91.0
new: 210.0

path: .metrics.mi.mi_original
old: 22.31383465454229
new: 2.0978793925055896

path: .metrics.mi.mi_visual_studio
old: 13.04902611376742
new: 1.226830054096836

path: .metrics.mi.mi_sei
old: -14.132159213228183
new: -31.891709388862537

Spaces Data

Minimal test - lines (43, 334)

path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 14.227796268649804
new: 11.771384773878722

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: -12.947079694349554
new: -12.4211089861571

path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 24.32953161939116
new: 20.129067963332616

path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 31.244318181818183
new: 85.51530612244898

path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.03200581923986179
new: 0.01169381301831633

path: .spaces[0].spaces[0].metrics.halstead.n2
old: 176.0
new: 98.0

path: .spaces[0].spaces[0].metrics.halstead.volume
old: 7872.641404268845
new: 7975.571177876286

path: .spaces[0].spaces[0].metrics.halstead.n1
old: 26.0
new: 37.0

path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.3959838497585924
new: 0.7462212415719268

path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 202.0
new: 135.0

path: .spaces[0].spaces[0].metrics.halstead.length
old: 1028.0
new: 1127.0

path: .spaces[0].spaces[0].metrics.halstead.N2
old: 423.0
new: 453.0

path: .spaces[0].spaces[0].metrics.halstead.time
old: 13665.295164796204
new: 37890.74504319287

path: .spaces[0].spaces[0].metrics.halstead.effort
old: 245975.3129663317
new: 682033.4107774716

path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 1.3085985251455552
new: 2.582750842732423

path: .spaces[0].spaces[0].metrics.halstead.N1
old: 605.0
new: 674.0

path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 1435.071397551833
new: 840.9913392515615

path: .spaces[0].spaces[0].metrics.loc.ploc
old: 213.0
new: 197.0

path: .spaces[0].spaces[0].metrics.loc.lloc
old: 91.0
new: 111.0

path: .spaces[0].spaces[0].metrics.loc.sloc
old: 276.0
new: 292.0

path: .spaces[0].spaces[0].metrics.loc.blank
old: 35.0
new: 49.0

path: .spaces[0].spaces[0].metrics.loc.cloc
old: 28.0
new: 46.0

path: .spaces[0].spaces[0].metrics.nexits.average
old: 1.0
new: 0.7391304347826086

path: .spaces[0].spaces[0].metrics.nexits.sum
old: 11.0
new: 17.0

path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 3.9
new: 2.2083333333333335

path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 39.0
new: 53.0

path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 30.0
new: 42.0

path: .spaces[0].spaces[0].metrics.cognitive.average
old: 2.727272727272727
new: 1.826086956521739

path: .spaces[0].spaces[0].metrics.nom.closures
old: 3.0
new: 0.0

path: .spaces[0].spaces[0].metrics.nom.total
old: 11.0
new: 23.0

path: .spaces[0].spaces[0].metrics.nom.functions
old: 8.0
new: 23.0

path: .spaces[0].spaces[0].metrics.nargs.average
old: 1.3636363636363635
new: 0.782608695652174

path: .spaces[0].spaces[0].metrics.nargs.sum
old: 15.0
new: 18.0

Code

namespace test_assembler {

using std::back_insert_iterator;

Label::Label() : value_(new Binding()) {}
Label::Label(uint64_t value) : value_(new Binding(value)) {}
Label::Label(const Label& label) {
  value_ = label.value_;
  value_->Acquire();
}
Label::~Label() {
  if (value_->Release()) delete value_;
}

Label& Label::operator=(uint64_t value) {
  value_->Set(NULL, value);
  return *this;
}

Label& Label::operator=(const Label& label) {
  value_->Set(label.value_, 0);
  return *this;
}

Label Label::operator+(uint64_t addend) const {
  Label l;
  l.value_->Set(this->value_, addend);
  return l;
}

Label Label::operator-(uint64_t subtrahend) const {
  Label l;
  l.value_->Set(this->value_, -subtrahend);
  return l;
}

// When NDEBUG is #defined, assert doesn't evaluate its argument. This
// means you can't simply use assert to check the return value of a
// function with necessary side effects.
//
// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether
// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts
// that x is true.
#ifdef NDEBUG
#  define ALWAYS_EVALUATE_AND_ASSERT(x) x
#else
#  define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x)
#endif

uint64_t Label::operator-(const Label& label) const {
  uint64_t offset;
  ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset));
  return offset;
}

bool Label::IsKnownConstant(uint64_t* value_p) const {
  Binding* base;
  uint64_t addend;
  value_->Get(&base, &addend);
  if (base != NULL) return false;
  if (value_p) *value_p = addend;
  return true;
}

bool Label::IsKnownOffsetFrom(const Label& label, uint64_t* offset_p) const {
  Binding *label_base, *this_base;
  uint64_t label_addend, this_addend;
  label.value_->Get(&label_base, &label_addend);
  value_->Get(&this_base, &this_addend);
  // If this and label are related, Get will find their final
  // common ancestor, regardless of how indirect the relation is. This
  // comparison also handles the constant vs. constant case.
  if (this_base != label_base) return false;
  if (offset_p) *offset_p = this_addend - label_addend;
  return true;
}

Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) {}

Label::Binding::Binding(uint64_t addend)
    : base_(NULL), addend_(addend), reference_count_(1) {}

Label::Binding::~Binding() {
  assert(reference_count_ == 0);
  if (base_ && base_ != this && base_->Release()) delete base_;
}

void Label::Binding::Set(Binding* binding, uint64_t addend) {
  if (!base_ && !binding) {
    // We're equating two constants. This could be okay.
    assert(addend_ == addend);
  } else if (!base_) {
    // We are a known constant, but BINDING may not be, so turn the
    // tables and try to set BINDING's value instead.
    binding->Set(NULL, addend_ - addend);
  } else {
    if (binding) {
      // Find binding's final value. Since the final value is always either
      // completely unconstrained or a constant, never a reference to
      // another variable (otherwise, it wouldn't be final), this
      // guarantees we won't create cycles here, even for code like this:
      //   l = m, m = n, n = l;
      uint64_t binding_addend;
      binding->Get(&binding, &binding_addend);
      addend += binding_addend;
    }

    // It seems likely that setting a binding to itself is a bug
    // (although I can imagine this might turn out to be helpful to
    // permit).
    assert(binding != this);

    if (base_ != this) {
      // Set the other bindings on our chain as well. Note that this
      // is sufficient even though binding relationships form trees:
      // All binding operations traverse their chains to the end, and
      // all bindings related to us share some tail of our chain, so
      // they will see the changes we make here.
      base_->Set(binding, addend - addend_);
      // We're not going to use base_ any more.
      if (base_->Release()) delete base_;
    }

    // Adopt BINDING as our base. Note that it should be correct to
    // acquire here, after the release above, even though the usual
    // reference-counting rules call for acquiring first, and then
    // releasing: the self-reference assertion above should have
    // complained if BINDING were 'this' or anywhere along our chain,
    // so we didn't release BINDING.
    if (binding) binding->Acquire();
    base_ = binding;
    addend_ = addend;
  }
}

void Label::Binding::Get(Binding** base, uint64_t* addend) {
  if (base_ && base_ != this) {
    // Recurse to find the end of our reference chain (the root of our
    // tree), and then rewrite every binding along the chain to refer
    // to it directly, adjusting addends appropriately. (This is why
    // this member function isn't this-const.)
    Binding* final_base;
    uint64_t final_addend;
    base_->Get(&final_base, &final_addend);
    if (final_base) final_base->Acquire();
    if (base_->Release()) delete base_;
    base_ = final_base;
    addend_ += final_addend;
  }
  *base = base_;
  *addend = addend_;
}

template 
static inline void InsertEndian(test_assembler::Endianness endianness,
                                size_t size, uint64_t number, Inserter dest) {
  assert(size > 0);
  if (endianness == kLittleEndian) {
    for (size_t i = 0; i < size; i++) {
      *dest++ = (char)(number & 0xff);
      number >>= 8;
    }
  } else {
    assert(endianness == kBigEndian);
    // The loop condition is odd, but it's correct for size_t.
    for (size_t i = size - 1; i < size; i--)
      *dest++ = (char)((number >> (i * 8)) & 0xff);
  }
}

Section& Section::Append(Endianness endianness, size_t size, uint64_t number) {
  InsertEndian(endianness, size, number,
               back_insert_iterator(contents_));
  return *this;
}

Section& Section::Append(Endianness endianness, size_t size,
                         const Label& label) {
  // If this label's value is known, there's no reason to waste an
  // entry in references_ on it.
  uint64_t value;
  if (label.IsKnownConstant(&value)) return Append(endianness, size, value);

  // This will get caught when the references are resolved, but it's
  // nicer to find out earlier.
  assert(endianness != kUnsetEndian);

  references_.push_back(Reference(contents_.size(), endianness, size, label));
  contents_.append(size, 0);
  return *this;
}

#define ENDIANNESS_L kLittleEndian
#define ENDIANNESS_B kBigEndian
#define ENDIANNESS(e) ENDIANNESS_##e

#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits)         \
  Section& Section::e##bits(uint##bits##_t v) {            \
    InsertEndian(ENDIANNESS(e), bits / 8, v,               \
                 back_insert_iterator(contents_)); \
    return *this;                                          \
  }

#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \
  Section& Section::e##bits(const Label& v) {     \
    return Append(ENDIANNESS(e), bits / 8, v);    \
  }

// Define L16, B32, and friends.
#define DEFINE_SHORT_APPEND_ENDIAN(e, bits)  \
  DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
  DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits)

DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8);
DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8);
DEFINE_SHORT_APPEND_ENDIAN(L, 16);
DEFINE_SHORT_APPEND_ENDIAN(L, 32);
DEFINE_SHORT_APPEND_ENDIAN(L, 64);
DEFINE_SHORT_APPEND_ENDIAN(B, 16);
DEFINE_SHORT_APPEND_ENDIAN(B, 32);
DEFINE_SHORT_APPEND_ENDIAN(B, 64);

#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits)           \
  Section& Section::D##bits(uint##bits##_t v) {            \
    InsertEndian(endianness_, bits / 8, v,                 \
                 back_insert_iterator(contents_)); \
    return *this;                                          \
  }
#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \
  Section& Section::D##bits(const Label& v) {   \
    return Append(endianness_, bits / 8, v);    \
  }
#define DEFINE_SHORT_APPEND_DEFAULT(bits)  \
  DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
  DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits)

DEFINE_SHORT_APPEND_LABEL_DEFAULT(8)
DEFINE_SHORT_APPEND_DEFAULT(16);
DEFINE_SHORT_APPEND_DEFAULT(32);
DEFINE_SHORT_APPEND_DEFAULT(64);

Section& Section::LEB128(long long value) {
  while (value < -0x40 || 0x3f < value) {
    contents_ += (value & 0x7f) | 0x80;
    if (value < 0)
      value = (value >> 7) | ~(((unsigned long long)-1) >> 7);
    else
      value = (value >> 7);
  }
  contents_ += value & 0x7f;
  return *this;
}

Section& Section::ULEB128(uint64_t value) {
  while (value > 0x7f) {
    contents_ += (value & 0x7f) | 0x80;
    value = (value >> 7);
  }
  contents_ += value;
  return *this;
}

Section& Section::Align(size_t alignment, uint8_t pad_byte) {
  // ALIGNMENT must be a power of two.
  assert(((alignment - 1) & alignment) == 0);
  size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1);
  contents_.append(new_size - contents_.size(), pad_byte);
  assert((contents_.size() & (alignment - 1)) == 0);
  return *this;
}

bool Section::GetContents(string* contents) {
  // For each label reference, find the label's value, and patch it into
  // the section's contents.
  for (size_t i = 0; i < references_.size(); i++) {
    Reference& r = references_[i];
    uint64_t value;
    if (!r.label.IsKnownConstant(&value)) {
      fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset);
      return false;
    }
    assert(r.offset < contents_.size());
    assert(contents_.size() - r.offset >= r.size);
    InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset);
  }
  contents->clear();
  std::swap(contents_, *contents);
  references_.clear();
  return true;
}

}  // namespace test_assembler

Minimal test - lines (57, 60)

path: .spaces[0].spaces[0].spaces[4].metrics.nom.closures
old: 3.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.nom.total
old: 4.0
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.cognitive.average
old: 2.75
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.cognitive.sum
old: 11.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.blank
old: 7.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.ploc
old: 87.0
new: 4.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.sloc
old: 108.0
new: 4.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.lloc
old: 36.0
new: 2.0

path: .spaces[0].spaces[0].spaces[4].metrics.loc.cloc
old: 14.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.nargs.average
old: 0.25
new: 0.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.bugs
old: 0.5604059795606705
new: 0.018752049849923146

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.effort
old: 68934.40366336062
new: 421.94418432572

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.n1
old: 21.0
new: 10.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 1.5439115273055908
new: 2.4904956346283575

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.level
old: 0.04616132167152576
new: 0.16666666666666666

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.difficulty
old: 21.66315789473684
new: 6.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.volume
old: 3182.103181739193
new: 70.32403072095333

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 716.3749486697941
new: 44.82892142331043

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.time
old: 3829.689092408923
new: 23.44134357365111

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.N2
old: 196.0
new: 6.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.length
old: 464.0
new: 18.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.n2
old: 95.0
new: 5.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.vocabulary
old: 116.0
new: 15.0

path: .spaces[0].spaces[0].spaces[4].metrics.halstead.N1
old: 268.0
new: 12.0

path: .spaces[0].spaces[0].spaces[4].metrics.cyclomatic.average
old: 11.0
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.cyclomatic.sum
old: 11.0
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 29.637383870319457
new: 73.79873729732505

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_original
old: 50.67992641824627
new: 126.19584077842585

path: .spaces[0].spaces[0].spaces[4].metrics.mi.mi_sei
old: 24.99976212527903
new: 106.46308153923984

path: .spaces[0].spaces[0].spaces[4].metrics.nexits.average
old: 0.75
new: 1.0

path: .spaces[0].spaces[0].spaces[4].metrics.nexits.sum
old: 3.0
new: 1.0

Code

Label& Label::operator=(uint64_t value) {
  value_->Set(NULL, value);
  return *this;
}

Minimal test - lines (73, 77)

path: .spaces[0].spaces[0].spaces[7].metrics.nargs.sum
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.nargs.average
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.cyclomatic.average
old: 5.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.cyclomatic.sum
old: 5.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.length
old: 85.0
new: 24.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.N2
old: 31.0
new: 10.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.n2
old: 23.0
new: 5.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.difficulty
old: 11.456521739130435
new: 10.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.effort
old: 5182.516717619118
new: 937.6537429460444

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.n1
old: 17.0
new: 10.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.purity_ratio
old: 2.041515215183142
new: 1.867871725971268

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.vocabulary
old: 40.0
new: 15.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.volume
old: 452.36388806542584
new: 93.76537429460444

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.time
old: 287.91759542328435
new: 52.09187460811358

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.bugs
old: 0.09982497721736826
new: 0.03193305039268938

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.estimated_program_length
old: 173.52879329056708
new: 44.82892142331043

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.N1
old: 54.0
new: 14.0

path: .spaces[0].spaces[0].spaces[7].metrics.halstead.level
old: 0.0872865275142315
new: 0.1

path: .spaces[0].spaces[0].spaces[7].metrics.mi.mi_sei
old: 79.2589955870867
new: 99.0896514058146

path: .spaces[0].spaces[0].spaces[7].metrics.mi.mi_visual_studio
old: 50.62584559916968
new: 70.8099230820973

path: .spaces[0].spaces[0].spaces[7].metrics.mi.mi_original
old: 86.57019597458014
new: 121.08496847038636

path: .spaces[0].spaces[0].spaces[7].metrics.loc.sloc
old: 24.0
new: 5.0

path: .spaces[0].spaces[0].spaces[7].metrics.loc.blank
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[7].metrics.loc.lloc
old: 10.0
new: 2.0

path: .spaces[0].spaces[0].spaces[7].metrics.loc.cloc
old: 4.0
new: 0.0

path: .spaces[0].spaces[0].spaces[7].metrics.loc.ploc
old: 18.0
new: 5.0

path: .spaces[0].spaces[0].spaces[7].metrics.nexits.average
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.nexits.sum
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[7].metrics.cognitive.sum
old: 4.0
new: 0.0

path: .spaces[0].spaces[0].spaces[7].metrics.cognitive.average
old: 4.0
new: 0.0

Code

Label Label::operator-(uint64_t subtrahend) const {
  Label l;
  l.value_->Set(this->value_, -subtrahend);
  return l;
}

Minimal test - lines (53, 55)

path: .spaces[0].spaces[0].spaces[3].metrics.cyclomatic.average
old: 5.0
new: 2.0

path: .spaces[0].spaces[0].spaces[3].metrics.cyclomatic.sum
old: 5.0
new: 2.0

path: .spaces[0].spaces[0].spaces[3].metrics.nexits.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.nexits.average
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.nargs.average
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.cognitive.average
old: 6.0
new: 1.0

path: .spaces[0].spaces[0].spaces[3].metrics.cognitive.sum
old: 6.0
new: 1.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.vocabulary
old: 53.0
new: 11.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.difficulty
old: 13.628571428571428
new: 5.333333333333333

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.level
old: 0.07337526205450734
new: 0.1875

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.N2
old: 53.0
new: 4.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.n1
old: 18.0
new: 8.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.bugs
old: 0.15704513393982142
new: 0.013519680280728329

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.n2
old: 35.0
new: 3.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.effort
old: 10226.301869836872
new: 258.3042275249182

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.N1
old: 78.0
new: 10.0

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 1.9433859207559956
new: 2.0539205358688193

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 254.58355561903545
new: 28.75488750216347

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.volume
old: 750.357579547779
new: 48.43204266092216

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.time
old: 568.127881657604
new: 14.350234862495457

path: .spaces[0].spaces[0].spaces[3].metrics.halstead.length
old: 131.0
new: 14.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.ploc
old: 28.0
new: 3.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.blank
old: 6.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.cloc
old: 3.0
new: 0.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.lloc
old: 14.0
new: 2.0

path: .spaces[0].spaces[0].spaces[3].metrics.loc.sloc
old: 37.0
new: 3.0

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_sei
old: 57.13741893836033
new: 115.75457976937346

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 44.98612310750397
new: 77.52376633412248

path: .spaces[0].spaces[0].spaces[3].metrics.mi.mi_original
old: 76.92627051383178
new: 132.56564043134944

Code

Label::~Label() {
  if (value_->Release()) delete value_;
}

Minimal test - lines (62, 65)

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.n1
old: 9.0
new: 10.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.N1
old: 19.0
new: 13.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.N2
old: 14.0
new: 8.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 1.8711698776319527
new: 2.1347105439671634

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.bugs
old: 0.03068314009949471
new: 0.02517517122460569

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.time
old: 49.06356278027341
new: 36.46431222567951

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.volume
old: 140.1816079436383
new: 82.0447025077789

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.effort
old: 883.1441300449213
new: 656.3576200622311

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.length
old: 33.0
new: 21.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 61.74860596185444
new: 44.82892142331043

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.vocabulary
old: 19.0
new: 15.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.difficulty
old: 6.3
new: 8.0

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.level
old: 0.15873015873015872
new: 0.125

path: .spaces[0].spaces[0].spaces[5].metrics.halstead.n2
old: 10.0
new: 5.0

path: .spaces[0].spaces[0].spaces[5].metrics.cyclomatic.average
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[5].metrics.cyclomatic.sum
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[5].metrics.cognitive.average
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[5].metrics.cognitive.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.sloc
old: 13.0
new: 4.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.lloc
old: 6.0
new: 2.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.cloc
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.blank
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[5].metrics.loc.ploc
old: 9.0
new: 4.0

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_original
old: 103.2845387449579
new: 125.39425724332408

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_sei
old: 102.0576030479892
new: 105.30664094829032

path: .spaces[0].spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 60.40031505553093
new: 73.32997499609597

path: .spaces[0].spaces[0].spaces[5].metrics.nexits.sum
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[5].metrics.nexits.average
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[5].metrics.nargs.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[5].metrics.nargs.average
old: 1.0
new: 0.0

Code

Label& Label::operator=(const Label& label) {
  value_->Set(label.value_, 0);
  return *this;
}

Minimal test - lines (47, 47)

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 61.34227922068799
new: 4.166666666666667

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 1104.161025972384
new: 75.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.03560959390880295
new: 0.005928155507483437

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.17105263157894737
new: 0.4

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 188.86964917948671
new: 30.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 24.0
new: 7.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 72.10571633583419
new: 16.36452797660028

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 8.0
new: 5.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.6768771240891671
new: 1.6364527976600278

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 13.0
new: 3.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 5.846153846153846
new: 2.5

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 19.0
new: 3.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 43.0
new: 10.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 21.0
new: 8.0

path: .spaces[0].spaces[0].spaces[0].metrics.cyclomatic.sum
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.lloc
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.ploc
old: 8.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.sloc
old: 8.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.sum
old: 6.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: 6.0
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 109.59955015556356
new: 153.0837736153568

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 82.62151521988892
new: 145.25416890283572

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 64.09330418454009
new: 89.52267462886361

Code

Label::Label() : value_(new Binding()) {}

Minimal test - lines (48, 48)

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.vocabulary
old: 9.0
new: 10.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.time
old: 5.811529169310906
new: 8.996888590319939

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.level
old: 0.3333333333333333
new: 0.26666666666666666

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.volume
old: 34.86917501586544
new: 43.18506523353571

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.length
old: 11.0
new: 13.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.N2
old: 3.0
new: 5.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.n2
old: 3.0
new: 4.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 1.842242046044582
new: 1.808444231102072

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.bugs
old: 0.007400380157174523
new: 0.009903498582139372

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.difficulty
old: 3.0
new: 3.75

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 20.264662506490403
new: 23.509775004326936

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.effort
old: 104.60752504759633
new: 161.9439946257589

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.lloc
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.sloc
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.ploc
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 78.65739431314731
new: 88.41486984730174

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_original
old: 134.50414427548188
new: 151.189427438886

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_sei
old: 118.44942979264312
new: 142.52120506831432

Code

Label::Label(uint64_t value) : value_(new Binding(value)) {}

Minimal test - lines (67, 71)

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_sei
old: 93.95328610212584
new: 99.60253955663347

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 68.68662876803354
new: 71.017821898286

path: .spaces[0].spaces[0].spaces[6].metrics.mi.mi_original
old: 117.45413519333736
new: 121.44047544606906

path: .spaces[0].spaces[0].spaces[6].metrics.nargs.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.nargs.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.cyclomatic.average
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.cyclomatic.sum
old: 2.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.nexits.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.nexits.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.effort
old: 749.3681875625622
new: 788.122468865924

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.N2
old: 8.0
new: 10.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.estimated_program_length
old: 53.5635228093372
new: 40.13896548741762

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.N1
old: 17.0
new: 13.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.level
old: 0.13636363636363638
new: 0.1111111111111111

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.difficulty
old: 7.333333333333333
new: 9.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.n2
old: 6.0
new: 5.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.time
old: 41.631565975697896
new: 43.784581603662446

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.volume
old: 102.18657103125848
new: 87.56916320732489

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 2.142540912373488
new: 1.7451724124964183

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.vocabulary
old: 17.0
new: 14.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.n1
old: 11.0
new: 9.0

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.bugs
old: 0.027500604913224463
new: 0.028440761343675472

path: .spaces[0].spaces[0].spaces[6].metrics.halstead.length
old: 25.0
new: 23.0

path: .spaces[0].spaces[0].spaces[6].metrics.cognitive.sum
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[6].metrics.cognitive.average
old: 1.0
new: 0.0

path: .spaces[0].spaces[0].spaces[6].metrics.loc.sloc
old: 6.0
new: 5.0

path: .spaces[0].spaces[0].spaces[6].metrics.loc.ploc
old: 6.0
new: 5.0

Code

Label Label::operator+(uint64_t addend) const {
  Label l;
  l.value_->Set(this->value_, addend);
  return l;
}

Minimal test - lines (49, 52)

path: .spaces[0].spaces[0].spaces[2].metrics.nargs.average
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.nargs.sum
old: 3.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.nexits.average
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.nexits.sum
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_original
old: 66.52758643388843
new: 126.64300853627338

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_sei
old: 35.983618726500616
new: 107.10820824593196

path: .spaces[0].spaces[0].spaces[2].metrics.mi.mi_visual_studio
old: 38.9050213063675
new: 74.0602389101014

path: .spaces[0].spaces[0].spaces[2].metrics.cyclomatic.average
old: 10.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.cyclomatic.sum
old: 10.0
new: 1.0

path: .spaces[0].spaces[0].spaces[2].metrics.cognitive.average
old: 7.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.cognitive.sum
old: 7.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.blank
old: 6.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.ploc
old: 46.0
new: 4.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.cloc
old: 2.0
new: 0.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.lloc
old: 20.0
new: 2.0

path: .spaces[0].spaces[0].spaces[2].metrics.loc.sloc
old: 54.0
new: 4.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.estimated_program_length
old: 418.41343573651113
new: 32.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.level
old: 0.08241758241758242
new: 0.125

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.length
old: 219.0
new: 18.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.bugs
old: 0.21692964024575936
new: 0.02145079956307671

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.difficulty
old: 12.133333333333333
new: 8.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.N1
old: 128.0
new: 10.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.time
old: 922.3329438179052
new: 28.67970000576925

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.volume
old: 1368.2961254441452
new: 64.5293250129808

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.n1
old: 16.0
new: 8.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.effort
old: 16601.992988722293
new: 516.2346001038464

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.n2
old: 60.0
new: 4.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.purity_ratio
old: 1.9105636335000509
new: 1.7777777777777777

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.N2
old: 91.0
new: 8.0

path: .spaces[0].spaces[0].spaces[2].metrics.halstead.vocabulary
old: 76.0
new: 12.0

Code

Label::Label(const Label& label) {
  value_ = label.value_;
  value_->Acquire();
}

Minimal test - lines (42, 335)

path: .spaces[0].metrics.nom.closures
old: 3.0
new: 0.0

path: .spaces[0].metrics.nom.functions
old: 8.0
new: 23.0

path: .spaces[0].metrics.nom.total
old: 11.0
new: 23.0

path: .spaces[0].metrics.mi.mi_visual_studio
old: 14.01615285832464
new: 11.56225135636454

path: .spaces[0].metrics.mi.mi_original
old: 23.967621387735136
new: 19.771449819383363

path: .spaces[0].metrics.mi.mi_sei
old: -13.06303553225542
new: -12.650508267330338

path: .spaces[0].metrics.halstead.effort
old: 245869.3306372341
new: 678855.1601589287

path: .spaces[0].metrics.halstead.N1
old: 606.0
new: 675.0

path: .spaces[0].metrics.halstead.N2
old: 424.0
new: 454.0

path: .spaces[0].metrics.halstead.length
old: 1030.0
new: 1129.0

path: .spaces[0].metrics.halstead.vocabulary
old: 203.0
new: 136.0

path: .spaces[0].metrics.halstead.bugs
old: 1.3082226113214566
new: 2.574720915466769

path: .spaces[0].metrics.halstead.n2
old: 177.0
new: 99.0

path: .spaces[0].metrics.halstead.n1
old: 26.0
new: 37.0

path: .spaces[0].metrics.halstead.volume
old: 7895.295994700732
new: 8001.745547771633

path: .spaces[0].metrics.halstead.purity_ratio
old: 1.401920014598407
new: 0.7520425862853433

path: .spaces[0].metrics.halstead.time
old: 13659.407257624116
new: 37714.17556438493

path: .spaces[0].metrics.halstead.difficulty
old: 31.141242937853107
new: 84.83838383838383

path: .spaces[0].metrics.halstead.level
old: 0.03211175616835994
new: 0.011787117513989762

path: .spaces[0].metrics.halstead.estimated_program_length
old: 1443.977615036359
new: 849.0560799161525

path: .spaces[0].metrics.nargs.average
old: 1.3636363636363635
new: 0.782608695652174

path: .spaces[0].metrics.nargs.sum
old: 15.0
new: 18.0

path: .spaces[0].metrics.loc.lloc
old: 91.0
new: 111.0

path: .spaces[0].metrics.loc.blank
old: 34.0
new: 48.0

path: .spaces[0].metrics.loc.ploc
old: 215.0
new: 199.0

path: .spaces[0].metrics.loc.sloc
old: 278.0
new: 294.0

path: .spaces[0].metrics.loc.cloc
old: 29.0
new: 47.0

path: .spaces[0].metrics.nexits.average
old: 1.0
new: 0.7391304347826086

path: .spaces[0].metrics.nexits.sum
old: 11.0
new: 17.0

path: .spaces[0].metrics.cyclomatic.sum
old: 40.0
new: 54.0

path: .spaces[0].metrics.cyclomatic.average
old: 3.636363636363636
new: 2.16

path: .spaces[0].metrics.cognitive.sum
old: 30.0
new: 42.0

path: .spaces[0].metrics.cognitive.average
old: 2.727272727272727
new: 1.826086956521739

Code

namespace lul_test {
namespace test_assembler {

using std::back_insert_iterator;

Label::Label() : value_(new Binding()) {}
Label::Label(uint64_t value) : value_(new Binding(value)) {}
Label::Label(const Label& label) {
  value_ = label.value_;
  value_->Acquire();
}
Label::~Label() {
  if (value_->Release()) delete value_;
}

Label& Label::operator=(uint64_t value) {
  value_->Set(NULL, value);
  return *this;
}

Label& Label::operator=(const Label& label) {
  value_->Set(label.value_, 0);
  return *this;
}

Label Label::operator+(uint64_t addend) const {
  Label l;
  l.value_->Set(this->value_, addend);
  return l;
}

Label Label::operator-(uint64_t subtrahend) const {
  Label l;
  l.value_->Set(this->value_, -subtrahend);
  return l;
}

// When NDEBUG is #defined, assert doesn't evaluate its argument. This
// means you can't simply use assert to check the return value of a
// function with necessary side effects.
//
// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether
// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts
// that x is true.
#ifdef NDEBUG
#  define ALWAYS_EVALUATE_AND_ASSERT(x) x
#else
#  define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x)
#endif

uint64_t Label::operator-(const Label& label) const {
  uint64_t offset;
  ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset));
  return offset;
}

bool Label::IsKnownConstant(uint64_t* value_p) const {
  Binding* base;
  uint64_t addend;
  value_->Get(&base, &addend);
  if (base != NULL) return false;
  if (value_p) *value_p = addend;
  return true;
}

bool Label::IsKnownOffsetFrom(const Label& label, uint64_t* offset_p) const {
  Binding *label_base, *this_base;
  uint64_t label_addend, this_addend;
  label.value_->Get(&label_base, &label_addend);
  value_->Get(&this_base, &this_addend);
  // If this and label are related, Get will find their final
  // common ancestor, regardless of how indirect the relation is. This
  // comparison also handles the constant vs. constant case.
  if (this_base != label_base) return false;
  if (offset_p) *offset_p = this_addend - label_addend;
  return true;
}

Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) {}

Label::Binding::Binding(uint64_t addend)
    : base_(NULL), addend_(addend), reference_count_(1) {}

Label::Binding::~Binding() {
  assert(reference_count_ == 0);
  if (base_ && base_ != this && base_->Release()) delete base_;
}

void Label::Binding::Set(Binding* binding, uint64_t addend) {
  if (!base_ && !binding) {
    // We're equating two constants. This could be okay.
    assert(addend_ == addend);
  } else if (!base_) {
    // We are a known constant, but BINDING may not be, so turn the
    // tables and try to set BINDING's value instead.
    binding->Set(NULL, addend_ - addend);
  } else {
    if (binding) {
      // Find binding's final value. Since the final value is always either
      // completely unconstrained or a constant, never a reference to
      // another variable (otherwise, it wouldn't be final), this
      // guarantees we won't create cycles here, even for code like this:
      //   l = m, m = n, n = l;
      uint64_t binding_addend;
      binding->Get(&binding, &binding_addend);
      addend += binding_addend;
    }

    // It seems likely that setting a binding to itself is a bug
    // (although I can imagine this might turn out to be helpful to
    // permit).
    assert(binding != this);

    if (base_ != this) {
      // Set the other bindings on our chain as well. Note that this
      // is sufficient even though binding relationships form trees:
      // All binding operations traverse their chains to the end, and
      // all bindings related to us share some tail of our chain, so
      // they will see the changes we make here.
      base_->Set(binding, addend - addend_);
      // We're not going to use base_ any more.
      if (base_->Release()) delete base_;
    }

    // Adopt BINDING as our base. Note that it should be correct to
    // acquire here, after the release above, even though the usual
    // reference-counting rules call for acquiring first, and then
    // releasing: the self-reference assertion above should have
    // complained if BINDING were 'this' or anywhere along our chain,
    // so we didn't release BINDING.
    if (binding) binding->Acquire();
    base_ = binding;
    addend_ = addend;
  }
}

void Label::Binding::Get(Binding** base, uint64_t* addend) {
  if (base_ && base_ != this) {
    // Recurse to find the end of our reference chain (the root of our
    // tree), and then rewrite every binding along the chain to refer
    // to it directly, adjusting addends appropriately. (This is why
    // this member function isn't this-const.)
    Binding* final_base;
    uint64_t final_addend;
    base_->Get(&final_base, &final_addend);
    if (final_base) final_base->Acquire();
    if (base_->Release()) delete base_;
    base_ = final_base;
    addend_ += final_addend;
  }
  *base = base_;
  *addend = addend_;
}

template 
static inline void InsertEndian(test_assembler::Endianness endianness,
                                size_t size, uint64_t number, Inserter dest) {
  assert(size > 0);
  if (endianness == kLittleEndian) {
    for (size_t i = 0; i < size; i++) {
      *dest++ = (char)(number & 0xff);
      number >>= 8;
    }
  } else {
    assert(endianness == kBigEndian);
    // The loop condition is odd, but it's correct for size_t.
    for (size_t i = size - 1; i < size; i--)
      *dest++ = (char)((number >> (i * 8)) & 0xff);
  }
}

Section& Section::Append(Endianness endianness, size_t size, uint64_t number) {
  InsertEndian(endianness, size, number,
               back_insert_iterator(contents_));
  return *this;
}

Section& Section::Append(Endianness endianness, size_t size,
                         const Label& label) {
  // If this label's value is known, there's no reason to waste an
  // entry in references_ on it.
  uint64_t value;
  if (label.IsKnownConstant(&value)) return Append(endianness, size, value);

  // This will get caught when the references are resolved, but it's
  // nicer to find out earlier.
  assert(endianness != kUnsetEndian);

  references_.push_back(Reference(contents_.size(), endianness, size, label));
  contents_.append(size, 0);
  return *this;
}

#define ENDIANNESS_L kLittleEndian
#define ENDIANNESS_B kBigEndian
#define ENDIANNESS(e) ENDIANNESS_##e

#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits)         \
  Section& Section::e##bits(uint##bits##_t v) {            \
    InsertEndian(ENDIANNESS(e), bits / 8, v,               \
                 back_insert_iterator(contents_)); \
    return *this;                                          \
  }

#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \
  Section& Section::e##bits(const Label& v) {     \
    return Append(ENDIANNESS(e), bits / 8, v);    \
  }

// Define L16, B32, and friends.
#define DEFINE_SHORT_APPEND_ENDIAN(e, bits)  \
  DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
  DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits)

DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8);
DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8);
DEFINE_SHORT_APPEND_ENDIAN(L, 16);
DEFINE_SHORT_APPEND_ENDIAN(L, 32);
DEFINE_SHORT_APPEND_ENDIAN(L, 64);
DEFINE_SHORT_APPEND_ENDIAN(B, 16);
DEFINE_SHORT_APPEND_ENDIAN(B, 32);
DEFINE_SHORT_APPEND_ENDIAN(B, 64);

#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits)           \
  Section& Section::D##bits(uint##bits##_t v) {            \
    InsertEndian(endianness_, bits / 8, v,                 \
                 back_insert_iterator(contents_)); \
    return *this;                                          \
  }
#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \
  Section& Section::D##bits(const Label& v) {   \
    return Append(endianness_, bits / 8, v);    \
  }
#define DEFINE_SHORT_APPEND_DEFAULT(bits)  \
  DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
  DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits)

DEFINE_SHORT_APPEND_LABEL_DEFAULT(8)
DEFINE_SHORT_APPEND_DEFAULT(16);
DEFINE_SHORT_APPEND_DEFAULT(32);
DEFINE_SHORT_APPEND_DEFAULT(64);

Section& Section::LEB128(long long value) {
  while (value < -0x40 || 0x3f < value) {
    contents_ += (value & 0x7f) | 0x80;
    if (value < 0)
      value = (value >> 7) | ~(((unsigned long long)-1) >> 7);
    else
      value = (value >> 7);
  }
  contents_ += value & 0x7f;
  return *this;
}

Section& Section::ULEB128(uint64_t value) {
  while (value > 0x7f) {
    contents_ += (value & 0x7f) | 0x80;
    value = (value >> 7);
  }
  contents_ += value;
  return *this;
}

Section& Section::Align(size_t alignment, uint8_t pad_byte) {
  // ALIGNMENT must be a power of two.
  assert(((alignment - 1) & alignment) == 0);
  size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1);
  contents_.append(new_size - contents_.size(), pad_byte);
  assert((contents_.size() & (alignment - 1)) == 0);
  return *this;
}

bool Section::GetContents(string* contents) {
  // For each label reference, find the label's value, and patch it into
  // the section's contents.
  for (size_t i = 0; i < references_.size(); i++) {
    Reference& r = references_[i];
    uint64_t value;
    if (!r.label.IsKnownConstant(&value)) {
      fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset);
      return false;
    }
    assert(r.offset < contents_.size());
    assert(contents_.size() - r.offset >= r.size);
    InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset);
  }
  contents->clear();
  std::swap(contents_, *contents);
  references_.clear();
  return true;
}

}  // namespace test_assembler
}  // namespace lul_test