//===--- Explosion.h - Exploded R-Value Representation ----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// A storage structure for holding an exploded r-value.  An exploded
// r-value has been separated into individual components.  Only types
// with non-resilient structure may be exploded.
//
// The standard use for explosions is for argument-passing.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_IRGEN_EXPLOSION_H
#define SWIFT_IRGEN_EXPLOSION_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "IRGen.h"
#include "IRGenFunction.h"

namespace swift {
namespace irgen {

/// The representation for an explosion is just a list of raw LLVM
/// values.  The meaning of these values is imposed externally by the
/// type infos, except that it is expected that they will be passed
/// as arguments in exactly this way.
class Explosion {
  unsigned NextValue;
  SmallVector<llvm::Value*, 8> Values;

public:
  Explosion() : NextValue(0) {}

  // We want to be a move-only type.
  Explosion(const Explosion &) = delete;
  Explosion &operator=(const Explosion &) = delete;
  Explosion(Explosion &&other) : NextValue(0) {
    // Do an uninitialized copy of the non-consumed elements.
    Values.reserve(other.size());
    Values.set_size(other.size());
    std::uninitialized_copy(other.begin(), other.end(), Values.begin());

    // Remove everything from the other explosion.
    other.reset();
  }

  Explosion &operator=(Explosion &&o) {
    assert(empty() && "explosion had values remaining when reassigned!");
    NextValue = o.NextValue;
    Values.swap(o.Values);
    o.reset();
    return *this;
  }

  ~Explosion() {
    assert(empty() && "explosion had values remaining when destroyed!");
  }

  bool empty() const {
    return NextValue == Values.size();
  }

  size_t size() const {
    return Values.size() - NextValue;
  }

  typedef SmallVector<llvm::Value*, 8>::iterator iterator;
  iterator begin() { return Values.begin() + NextValue; }
  iterator end() { return Values.end(); }

  typedef SmallVector<llvm::Value*, 8>::const_iterator const_iterator;
  const_iterator begin() const { return Values.begin() + NextValue; }
  const_iterator end() const { return Values.end(); }

  /// Add a value to the end of this exploded r-value.
  void add(llvm::Value *value) {
    assert(value && "adding null value to explosion");
    assert(NextValue == 0 && "adding to partially-claimed explosion?");
    Values.push_back(value);
  }

  void add(ArrayRef<llvm::Value*> values) {
#ifndef NDEBUG
    for (auto value : values)
      assert(value && "adding null value to explosion");
#endif
    assert(NextValue == 0 && "adding to partially-claimed explosion?");
    Values.append(values.begin(), values.end());
  }

  /// Return an array containing the given range of values.  The values
  /// are not claimed.
  ArrayRef<llvm::Value*> getRange(unsigned from, unsigned to) const {
    assert(from <= to);
    assert(to <= Values.size());
    return llvm::makeArrayRef(begin() + from, to - from);
  }

  /// Return an array containing all of the remaining values.  The values
  /// are not claimed.
  ArrayRef<llvm::Value *> getAll() {
    return llvm::makeArrayRef(begin(), Values.size() - NextValue);
  }

  /// Transfer ownership of the next N values to the given explosion.
  void transferInto(Explosion &other, unsigned n) {
    other.add(claim(n));
  }


  /// The next N values have been claimed in some indirect way (e.g.
  /// using getRange() and the like); just give up on them.
  void markClaimed(unsigned n) {
    assert(NextValue + n <= Values.size());
    NextValue += n;
  }

  /// Claim and return the next value in this explosion.
  llvm::Value *claimNext() {
    assert(NextValue < Values.size());
    return Values[NextValue++];
  }

  /// Claim and return the next N values in this explosion.
  ArrayRef<llvm::Value*> claim(unsigned n) {
    assert(NextValue + n <= Values.size());
    auto array = llvm::makeArrayRef(begin(), n);
    NextValue += n;
    return array;
  }

  /// Claim and return all the values in this explosion.
  ArrayRef<llvm::Value*> claimAll() {
    return claim(size());
  }

  // These are all kindof questionable.

  /// Without changing any state, take the last claimed value,
  /// if there is one.
  llvm::Value *getLastClaimed() {
    assert(NextValue > 0);
    return Values[NextValue-1];
  }

  /// Claim and remove the last item in the array.
  /// Unlike the normal 'claim' methods, the item is gone forever.
  llvm::Value *takeLast() {
    assert(!empty());
    auto result = Values.back();
    Values.pop_back();
    return result;
  }

  /// Reset this explosion.
  void reset() {
    NextValue = 0;
    Values.clear();
  }

  void print(llvm::raw_ostream &OS);
  void dump();
};

/// An explosion schema is essentially the type of an Explosion.
class ExplosionSchema {
public:

  /// The schema for one atom of the explosion.
  class Element {
    llvm::Type *Type;
    Alignment::int_type Align;
    Element() = default;
  public:
    static Element forScalar(llvm::Type *type) {
      Element e;
      e.Type = type;
      e.Align = 0;
      return e;
    }

    static Element forAggregate(llvm::Type *type, Alignment align) {
      assert(align.getValue() != 0 && "alignment with zero value!");
      Element e;
      e.Type = type;
      e.Align = align.getValue();
      return e;
    }

    bool isScalar() const { return Align == 0; }
    llvm::Type *getScalarType() const { assert(isScalar()); return Type; }

    bool isAggregate() const { return !isScalar(); }
    llvm::Type *getAggregateType() const {
      assert(isAggregate());
      return Type;
    }
    Alignment getAggregateAlignment() const {
      assert(isAggregate());
      return Alignment(Align);
    }
  };
  
private:
  SmallVector<Element, 8> Elements;
  bool ContainsAggregate;

public:
  ExplosionSchema() : ContainsAggregate(false) {}

  /// Return the number of elements in this schema.
  unsigned size() const { return Elements.size(); }
  bool empty() const { return Elements.empty(); }

  /// Does this schema contain an aggregate element?
  bool containsAggregate() const { return ContainsAggregate; }

  /// Does this schema consist solely of one aggregate element?
  bool isSingleAggregate() const {
    return size() == 1 && containsAggregate();
  }

  const Element &operator[](size_t index) const {
    return Elements[index];
  }

  typedef SmallVectorImpl<Element>::iterator iterator;
  typedef SmallVectorImpl<Element>::const_iterator const_iterator;
  
  iterator begin() { return Elements.begin(); }
  iterator end() { return Elements.end(); }
  const_iterator begin() const { return Elements.begin(); }
  const_iterator end() const { return Elements.end(); }

  void add(Element e) {
    Elements.push_back(e);
    ContainsAggregate |= e.isAggregate();
  }

  /// Produce the correct type for a direct return of this schema,
  /// which is assumed to contain only scalars.  This is defined as:
  ///   - void, if the schema is empty;
  ///   - the element type, if the schema contains exactly one element;
  ///   - an anonymous struct type concatenating those types, otherwise.
  llvm::Type *getScalarResultType(IRGenModule &IGM) const;
};

} // end namespace irgen
} // end namespace swift

#endif
