// Copyright (c) 2010, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>

// test_assembler.cc: Implementation of google_breakpad::TestAssembler.
// See test_assembler.h for details.

#include "common/test_assembler.h"

#include <assert.h>
#include <stdio.h>

#include <iterator>

namespace google_breakpad {
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;
}

uint64_t Label::Value() const {
  uint64_t v = 0;
  ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v));
  return v;
};

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<typename Inserter>
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<string>(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<string>(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<string>(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::Append(const Section& section) {
  size_t base = contents_.size();
  contents_.append(section.contents_);
  for (vector<Reference>::const_iterator it = section.references_.begin();
       it != section.references_.end(); it++)
    references_.push_back(Reference(base + it->offset, it->endianness,
                                    it->size, it->label));
  return *this;
}

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;
}

void Section::Clear() {
  contents_.clear();
  references_.clear();
}

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 google_breakpad
