/*
 * Copyright 2017, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <algorithm>
#include <iostream>
#include <string>

#include "clang/AST/APValue.h"

#include "slang_assert.h"
#include "slang_rs_export_foreach.h"
#include "slang_rs_export_func.h"
#include "slang_rs_export_reduce.h"
#include "slang_rs_export_type.h"
#include "slang_rs_export_var.h"
#include "slang_rs_reflection.h"
#include "slang_rs_reflection_state.h"

#include "bcinfo/MetadataExtractor.h"

namespace slang {

static bool equal(const clang::APValue &a, const clang::APValue &b) {
  if (a.getKind() != b.getKind())
    return false;
  switch (a.getKind()) {
    case clang::APValue::Float:
      return a.getFloat().bitwiseIsEqual(b.getFloat());
    case clang::APValue::Int:
      return a.getInt() == b.getInt();
    case clang::APValue::Vector: {
      unsigned NumElements = a.getVectorLength();
      if (NumElements != b.getVectorLength())
        return false;
      for (unsigned i = 0; i < NumElements; ++i) {
        if (!equal(a.getVectorElt(i), b.getVectorElt(i)))
          return false;
      }
      return true;
    }
    default:
      slangAssert(false && "unexpected APValue kind");
      return false;
  }
}

ReflectionState::~ReflectionState() {
  slangAssert(mState==S_Initial || mState==S_ClosedJava64 || mState==S_Bad);
  delete mStringSet;
}

void ReflectionState::openJava32(size_t NumFiles) {
  if (kDisabled)
    return;
  slangAssert(mState==S_Initial);
  mState = S_OpenJava32;
  mStringSet = new llvm::StringSet<>;
  mFiles.BeginCollecting(NumFiles);
}

void ReflectionState::closeJava32() {
  if (kDisabled)
    return;
  slangAssert(mState==S_OpenJava32 && (mForEachOpen < 0) && !mOutputClassOpen && (mRecordsState != RS_Open));
  mState = S_ClosedJava32;
  mRSC = nullptr;
}

void ReflectionState::openJava64() {
  if (kDisabled)
    return;
  slangAssert(mState==S_ClosedJava32);
  mState = S_OpenJava64;
  mFiles.BeginUsing();
}

void ReflectionState::closeJava64() {
  if (kDisabled)
    return;
  slangAssert(mState==S_OpenJava64 && (mForEachOpen < 0) && !mOutputClassOpen && (mRecordsState != RS_Open));
  mState = S_ClosedJava64;
  mRSC = nullptr;
}

llvm::StringRef ReflectionState::canon(const std::string &String) {
  slangAssert(isCollecting());
  // NOTE: llvm::StringSet does not permit the empty string as a member
  return String.empty() ? llvm::StringRef() : mStringSet->insert(String).first->getKey();
}

std::string ReflectionState::getUniqueTypeName(const RSExportType *T) {
  return RSReflectionJava::GetTypeName(T, RSReflectionJava::TypeNamePseudoC);
}

void ReflectionState::nextFile(const RSContext *RSC,
                               const std::string &PackageName,
                               const std::string &RSSourceFileName) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  mRSC = RSC;

  slangAssert(mRecordsState != RS_Open);
  mRecordsState = RS_Initial;

  if (isCollecting()) {
    File &file = mFiles.CollectNext();
    file.mPackageName = PackageName;
    file.mRSSourceFileName = RSSourceFileName;
  }
  if (isUsing()) {
    File &file = mFiles.UseNext();
    slangAssert(file.mRSSourceFileName == RSSourceFileName);
    if (file.mPackageName != PackageName)
      mRSC->ReportError("in file '%0' Java package name is '%1' for 32-bit targets "
                        "but '%2' for 64-bit targets")
          << RSSourceFileName << file.mPackageName << PackageName;
  }
}

void ReflectionState::dump() {
  const size_t NumFiles = mFiles.Size();
  for (int i = 0; i < NumFiles; ++i) {
    const File &file = mFiles[i];
    std::cout << "file = \"" << file.mRSSourceFileName << "\", "
              << "package = \"" << file.mPackageName << "\"" << std::endl;

    // NOTE: "StringMap iteration order, however, is not guaranteed to
    // be deterministic".  So sort before dumping.
    typedef const llvm::StringMap<File::Record>::MapEntryTy *RecordsEntryTy;
    std::vector<RecordsEntryTy> Records;
    Records.reserve(file.mRecords.size());
    for (auto I = file.mRecords.begin(), E = file.mRecords.end(); I != E; I++)
      Records.push_back(&(*I));
    std::sort(Records.begin(), Records.end(),
              [](RecordsEntryTy a, RecordsEntryTy b) { return a->getKey().compare(b->getKey())==-1; });
    for (auto Record : Records) {
      const auto &Val = Record->getValue();
      std::cout << "  (Record) name=\"" << Record->getKey().str() << "\""
                << " allocSize=" << Val.mAllocSize
                << " postPadding=" << Val.mPostPadding
                << " ordinary=" << Val.mOrdinary
                << " matchedByName=" << Val.mMatchedByName
                << std::endl;
      const size_t NumFields = Val.mFieldCount;
      for (int fieldIdx = 0; fieldIdx < NumFields; ++fieldIdx) {
        const auto &field = Val.mFields[fieldIdx];
        std::cout << "    (Field) name=\"" << field.mName << "\" ("
                  << field.mPrePadding << ", \"" << field.mType.str()
                  << "\"(" << field.mStoreSize << ")@" << field.mOffset
                  << ", " << field.mPostPadding << ")" << std::endl;
      }
    }

    const size_t NumVars = file.mVariables.Size();
    for (int varIdx = 0; varIdx < NumVars; ++varIdx) {
      const auto &var = file.mVariables[varIdx];
      std::cout << "  (Var) name=\"" << var.mName << "\" type=\"" << var.mType.str()
                << "\" const=" << var.mIsConst << " initialized=" << (var.mInitializerCount != 0)
                << " allocSize=" << var.mAllocSize << std::endl;
    }

    for (int feIdx = 0; feIdx < file.mForEachCount; ++feIdx) {
      const auto &fe = file.mForEaches[feIdx];
      std::cout << "  (ForEach) ordinal=" << feIdx << " state=";
      switch (fe.mState) {
        case File::ForEach::S_Initial:
          std::cout << "initial" << std::endl;
          continue;
        case File::ForEach::S_Collected:
          std::cout << "collected";
          break;
        case File::ForEach::S_UseMatched:
          std::cout << "usematched";
          break;
        default:
          std::cout << fe.mState;
          break;
      }
      std::cout << " name=\"" << fe.mName << "\" kernel=" << fe.mIsKernel
                << " hasOut=" << fe.mHasOut << " out=\"" << fe.mOut.str()
                << "\" metadata=0x" << std::hex << fe.mSignatureMetadata << std::dec
                << std::endl;
      const size_t NumIns = fe.mIns.Size();
      for (int insIdx = 0; insIdx < NumIns; ++insIdx)
        std::cout << "    (In) " << fe.mIns[insIdx].str() << std::endl;
      const size_t NumParams = fe.mParams.Size();
      for (int paramsIdx = 0; paramsIdx < NumParams; ++paramsIdx)
        std::cout << "    (Param) " << fe.mParams[paramsIdx].str() << std::endl;
    }

    for (auto feBad : mForEachesBad) {
      std::cout << "  (ForEachBad) ordinal=" << feBad->getOrdinal()
                << " name=\"" << feBad->getName() << "\""
                << std::endl;
    }

    const size_t NumInvokables = file.mInvokables.Size();
    for (int invIdx = 0; invIdx < NumInvokables; ++invIdx) {
      const auto &inv = file.mInvokables[invIdx];
      std::cout << "  (Invokable) name=\"" << inv.mName << "\"" << std::endl;
      const size_t NumParams = inv.mParamCount;
      for (int paramsIdx = 0; paramsIdx < NumParams; ++paramsIdx)
        std::cout << "    (Param) " << inv.mParams[paramsIdx].str() << std::endl;
    }

    const size_t NumReduces = file.mReduces.Size();
    for (int redIdx = 0; redIdx < NumReduces; ++redIdx) {
      const auto &red = file.mReduces[redIdx];
      std::cout << "  (Reduce) name=\"" << red.mName
                << "\" result=\"" << red.mResult.str()
                << "\" exportable=" << red.mIsExportable
                << std::endl;
      const size_t NumIns = red.mAccumInCount;
      for (int insIdx = 0; insIdx < NumIns; ++insIdx)
        std::cout << "    (In) " << red.mAccumIns[insIdx].str() << std::endl;
    }
  }
}

// ForEach /////////////////////////////////////////////////////////////////////////////////////

void ReflectionState::beginForEaches(size_t Count) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  if (isCollecting()) {
    auto &file = mFiles.Current();
    file.mForEaches = new File::ForEach[Count];
    file.mForEachCount = Count;
  }
  if (isUsing()) {
    slangAssert(mForEachesBad.empty());
    mNumForEachesMatchedByOrdinal = 0;
  }
}

// Keep this in sync with RSReflectionJava::genExportForEach().
void ReflectionState::beginForEach(const RSExportForEach *EF) {
  slangAssert(!isClosed() && (mForEachOpen < 0));
  if (!isActive())
    return;

  const bool IsKernel = EF->isKernelStyle();
  const std::string Name = EF->getName();
  const unsigned Ordinal = EF->getOrdinal();
  const size_t InCount = EF->getInTypes().size();
  const size_t ParamCount = EF->params_count();

  const RSExportType *OET = EF->getOutType();
  if (OET && !IsKernel) {
    slangAssert(OET->getClass() == RSExportType::ExportClassPointer);
    OET = static_cast<const RSExportPointerType *>(OET)->getPointeeType();
  }
  const std::string OutType = (OET ? getUniqueTypeName(OET) : "");
  const bool HasOut = (EF->hasOut() || EF->hasReturn());

  mForEachOpen = Ordinal;
  mForEachFatal = true;  // we'll set this to false if everything looks ok

  auto &file = mFiles.Current();
  auto &foreaches = file.mForEaches;
  if (isCollecting()) {
    slangAssert(Ordinal < file.mForEachCount);
    auto &foreach = foreaches[Ordinal];
    slangAssert(foreach.mState == File::ForEach::S_Initial);
    foreach.mState = File::ForEach::S_Collected;
    foreach.mName = Name;
    foreach.mIns.BeginCollecting(InCount);
    foreach.mParams.BeginCollecting(ParamCount);
    foreach.mOut = canon(OutType);
    foreach.mHasOut = HasOut;
    foreach.mSignatureMetadata = 0;
    foreach.mIsKernel = IsKernel;
  }
  if (isUsing()) {
    if (Ordinal >= file.mForEachCount) {
      mForEachesBad.push_back(EF);
      return;
    }

    auto &foreach = foreaches[Ordinal];
    slangAssert(foreach.mState == File::ForEach::S_Collected);
    foreach.mState = File::ForEach::S_UseMatched;
    ++mNumForEachesMatchedByOrdinal;

    if (foreach.mName != Name) {
      // Order matters because it determines slot number
      mForEachesBad.push_back(EF);
      return;
    }

    // At this point, we have matching ordinal and matching name.

    if (foreach.mIsKernel != IsKernel) {
      mRSC->ReportError(EF->getLocation(),
                        "foreach kernel '%0' has __attribute__((kernel)) for %select{32|64}1-bit targets "
                        "but not for %select{64|32}1-bit targets")
          << Name << IsKernel;
      return;
    }

    if ((foreach.mHasOut != HasOut) || !foreach.mOut.equals(OutType)) {
      // There are several different patterns we need to handle:
      // (1) Two different non-void* output types
      // (2) One non-void* output type, one void* output type
      // (3) One non-void* output type, one no-output
      // (4) One void* output type, one no-output
      if (foreach.mHasOut && HasOut) {
        if (foreach.mOut.size() && OutType.size()) {
          // (1) Two different non-void* output types
          mRSC->ReportError(EF->getLocation(),
                            "foreach kernel '%0' has output type '%1' for 32-bit targets "
                            "but output type '%2' for 64-bit targets")
              << Name << foreach.mOut.str() << OutType;
        } else {
          // (2) One non-void* return type, one void* output type
          const bool hasTyped64 = OutType.size();
          mRSC->ReportError(EF->getLocation(),
                            "foreach kernel '%0' has output type '%1' for %select{32|64}2-bit targets "
                            "but has untyped output for %select{64|32}2-bit targets")
              << Name << (foreach.mOut.str() + OutType) << hasTyped64;
        }
      } else {
        const std::string CombinedOutType = (foreach.mOut.str() + OutType);
        if (CombinedOutType.size()) {
          // (3) One non-void* output type, one no-output
          mRSC->ReportError(EF->getLocation(),
                            "foreach kernel '%0' has output type '%1' for %select{32|64}2-bit targets "
                            "but no output for %select{64|32}2-bit targets")
              << Name << CombinedOutType << HasOut;
        } else {
          // (4) One void* output type, one no-output
          mRSC->ReportError(EF->getLocation(),
                            "foreach kernel '%0' has untyped output for %select{32|64}1-bit targets "
                            "but no output for %select{64|32}1-bit targets")
              << Name << HasOut;
        }
      }
    }

    bool BadCount = false;
    if (foreach.mIns.Size() != InCount) {
      mRSC->ReportError(EF->getLocation(),
                        "foreach kernel '%0' has %1 input%s1 for 32-bit targets "
                        "but %2 input%s2 for 64-bit targets")
          << Name << unsigned(foreach.mIns.Size()) << unsigned(InCount);
      BadCount = true;
    }
    if (foreach.mParams.Size() != ParamCount) {
      mRSC->ReportError(EF->getLocation(),
                        "foreach kernel '%0' has %1 usrData parameter%s1 for 32-bit targets "
                        "but %2 usrData parameter%s2 for 64-bit targets")
          << Name << unsigned(foreach.mParams.Size()) << unsigned(ParamCount);
      BadCount = true;
    }

    if (BadCount)
      return;

    foreach.mIns.BeginUsing();
    foreach.mParams.BeginUsing();
  }

  mForEachFatal = false;
}

void ReflectionState::addForEachIn(const RSExportForEach *EF, const RSExportType *Type) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mForEachOpen == EF->getOrdinal());

  // Type may be nullptr in the case of void*.  See RSExportForEach::Create().
  if (Type && !EF->isKernelStyle()) {
    slangAssert(Type->getClass() == RSExportType::ExportClassPointer);
    Type = static_cast<const RSExportPointerType *>(Type)->getPointeeType();
  }
  const std::string TypeName = (Type ? getUniqueTypeName(Type) : std::string());

  auto &ins = mFiles.Current().mForEaches[EF->getOrdinal()].mIns;
  if (isCollecting()) {
    ins.CollectNext() = canon(TypeName);
  }
  if (isUsing()) {
    if (mForEachFatal)
      return;

    if (!ins.UseNext().equals(TypeName)) {
      if (ins.Current().size() && TypeName.size()) {
        mRSC->ReportError(EF->getLocation(),
                          "%ordinal0 input of foreach kernel '%1' "
                          "has type '%2' for 32-bit targets "
                          "but type '%3' for 64-bit targets")
            << unsigned(ins.CurrentIdx() + 1)
            << EF->getName()
            << ins.Current().str()
            << TypeName;
      } else {
        const bool hasType64 = TypeName.size();
        mRSC->ReportError(EF->getLocation(),
                          "%ordinal0 input of foreach kernel '%1' "
                          "has type '%2' for %select{32|64}3-bit targets "
                          "but is untyped for %select{64|32}3-bit targets")
            << unsigned(ins.CurrentIdx() + 1)
            << EF->getName()
            << (ins.Current().str() + TypeName)
            << hasType64;
      }
    }
  }
}

void ReflectionState::addForEachParam(const RSExportForEach *EF, const RSExportType *Type) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mForEachOpen == EF->getOrdinal());

  const std::string TypeName = getUniqueTypeName(Type);

  auto &params = mFiles.Current().mForEaches[EF->getOrdinal()].mParams;
  if (isCollecting()) {
    params.CollectNext() = canon(TypeName);
  }
  if (isUsing()) {
    if (mForEachFatal)
      return;

    if (!params.UseNext().equals(TypeName)) {
      mRSC->ReportError(EF->getLocation(),
                        "%ordinal0 usrData parameter of foreach kernel '%1' "
                        "has type '%2' for 32-bit targets "
                        "but type '%3' for 64-bit targets")
          << unsigned(params.CurrentIdx() + 1)
          << EF->getName()
          << params.Current().str()
          << TypeName;
    }
  }
}

void ReflectionState::addForEachSignatureMetadata(const RSExportForEach *EF, unsigned Metadata) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mForEachOpen == EF->getOrdinal());

  // These are properties in the metadata that we need to check.
  const unsigned SpecialParameterBits = bcinfo::MD_SIG_X|bcinfo::MD_SIG_Y|bcinfo::MD_SIG_Z|bcinfo::MD_SIG_Ctxt;

#ifndef __DISABLE_ASSERTS
  {
    // These are properties in the metadata that we already check in
    // some other way.
    const unsigned BoringBits = bcinfo::MD_SIG_In|bcinfo::MD_SIG_Out|bcinfo::MD_SIG_Usr|bcinfo::MD_SIG_Kernel;

    slangAssert((Metadata & ~(SpecialParameterBits | BoringBits)) == 0);
  }
#endif

  auto &mSignatureMetadata = mFiles.Current().mForEaches[EF->getOrdinal()].mSignatureMetadata;
  if (isCollecting()) {
    mSignatureMetadata = Metadata;
  }
  if (isUsing()) {
    if (mForEachFatal)
      return;

    if ((mSignatureMetadata & SpecialParameterBits) != (Metadata & SpecialParameterBits)) {
      mRSC->ReportError(EF->getLocation(),
                        "foreach kernel '%0' has different special parameters "
                        "for 32-bit targets than for 64-bit targets")
          << EF->getName();
    }
  }
}

void ReflectionState::endForEach() {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mForEachOpen >= 0);
  if (isUsing() && !mForEachFatal) {
    slangAssert(mFiles.Current().mForEaches[mForEachOpen].mIns.isFinished());
    slangAssert(mFiles.Current().mForEaches[mForEachOpen].mParams.isFinished());
  }

  mForEachOpen = -1;
}

void ReflectionState::endForEaches() {
  slangAssert(mForEachOpen < 0);
  if (!isUsing())
    return;

  const auto &file = mFiles.Current();

  if (!mForEachesBad.empty()) {
    std::sort(mForEachesBad.begin(), mForEachesBad.end(),
         [](const RSExportForEach *a, const RSExportForEach *b) { return a->getOrdinal() < b->getOrdinal(); });
    // Note that after the sort, all kernels that are bad because of
    // name mismatch precede all kernels that are bad because of
    // too-high ordinal.

    // 32-bit and 64-bit compiles need to see foreach kernels in the
    // same order, because of slot number assignment.  Once we see the
    // first name mismatch in the sequence of foreach kernels, it
    // doesn't make sense to issue further diagnostics regarding
    // foreach kernels except those that still happen to match by name
    // and ordinal (we already handled those diagnostics between
    // beginForEach() and endForEach()).
    bool ForEachesOrderFatal = false;

    for (const RSExportForEach *EF : mForEachesBad) {
      if (EF->getOrdinal() >= file.mForEachCount) {
        mRSC->ReportError(EF->getLocation(),
                          "foreach kernel '%0' is only present for 64-bit targets")
            << EF->getName();
      } else {
        mRSC->ReportError(EF->getLocation(),
                          "%ordinal0 foreach kernel is '%1' for 32-bit targets "
                          "but '%2' for 64-bit targets")
            << (EF->getOrdinal() + 1)
            << mFiles.Current().mForEaches[EF->getOrdinal()].mName
            << EF->getName();
        ForEachesOrderFatal = true;
        break;
      }
    }

    mForEachesBad.clear();

    if (ForEachesOrderFatal)
      return;
  }

  if (mNumForEachesMatchedByOrdinal == file.mForEachCount)
    return;
  for (unsigned ord = 0; ord < file.mForEachCount; ord++) {
    const auto &fe = file.mForEaches[ord];
    if (fe.mState == File::ForEach::S_Collected) {
      mRSC->ReportError("in file '%0' foreach kernel '%1' is only present for 32-bit targets")
          << file.mRSSourceFileName << fe.mName;
    }
  }
}

// Invokable ///////////////////////////////////////////////////////////////////////////////////

// Keep this in sync with RSReflectionJava::genExportFunction().
void ReflectionState::declareInvokable(const RSExportFunc *EF) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  const std::string Name = EF->getName(/*Mangle=*/false);
  const size_t ParamCount = EF->getNumParameters();

  auto &invokables = mFiles.Current().mInvokables;
  if (isCollecting()) {
    auto &invokable = invokables.CollectNext();
    invokable.mName = Name;
    invokable.mParamCount = ParamCount;
    if (EF->hasParam()) {
      unsigned FieldIdx = 0;
      invokable.mParams = new llvm::StringRef[ParamCount];
      for (RSExportFunc::const_param_iterator I = EF->params_begin(),
                                              E = EF->params_end();
           I != E; I++, FieldIdx++) {
        invokable.mParams[FieldIdx] = canon(getUniqueTypeName((*I)->getType()));
      }
    }
  }
  if (isUsing()) {
    if (mInvokablesOrderFatal)
      return;

    if (invokables.isFinished()) {
      // This doesn't actually break reflection, but that's a
      // coincidence of the fact that we reflect during the 64-bit
      // compilation pass rather than the 32-bit compilation pass, and
      // of the fact that the "extra" invokable(s) are at the end.
      mRSC->ReportError(EF->getLocation(),
                        "invokable function '%0' is only present for 64-bit targets")
          << Name;
      return;
    }

    auto &invokable = invokables.UseNext();

    if (invokable.mName != Name) {
      // Order matters because it determines slot number
      mRSC->ReportError(EF->getLocation(),
                        "%ordinal0 invokable function is '%1' for 32-bit targets "
                        "but '%2' for 64-bit targets")
          << unsigned(invokables.CurrentIdx() + 1)
          << invokable.mName
          << Name;
      mInvokablesOrderFatal = true;
      return;
    }

    if (invokable.mParamCount != ParamCount) {
      mRSC->ReportError(EF->getLocation(),
                        "invokable function '%0' has %1 parameter%s1 for 32-bit targets "
                        "but %2 parameter%s2 for 64-bit targets")
          << Name << unsigned(invokable.mParamCount) << unsigned(ParamCount);
      return;
    }
    if (EF->hasParam()) {
      unsigned FieldIdx = 0;
      for (RSExportFunc::const_param_iterator I = EF->params_begin(),
                                              E = EF->params_end();
           I != E; I++, FieldIdx++) {
        const std::string Type = getUniqueTypeName((*I)->getType());
        if (!invokable.mParams[FieldIdx].equals(Type)) {
          mRSC->ReportError(EF->getLocation(),
                            "%ordinal0 parameter of invokable function '%1' "
                            "has type '%2' for 32-bit targets "
                            "but type '%3' for 64-bit targets")
              << (FieldIdx + 1)
              << Name
              << invokable.mParams[FieldIdx].str()
              << Type;
        }
      }
    }
  }
}

void ReflectionState::endInvokables() {
  if (!isUsing() || mInvokablesOrderFatal)
    return;

  auto &invokables = mFiles.Current().mInvokables;
  while (!invokables.isFinished()) {
    const auto &invokable = invokables.UseNext();
    mRSC->ReportError("in file '%0' invokable function '%1' is only present for 32-bit targets")
        << mFiles.Current().mRSSourceFileName << invokable.mName;
  }
}

// Record //////////////////////////////////////////////////////////////////////////////////////

void ReflectionState::beginRecords() {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mRecordsState != RS_Open);
  mRecordsState = RS_Open;
  mNumRecordsMatchedByName = 0;
}

void ReflectionState::endRecords() {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mRecordsState == RS_Open);
  mRecordsState = RS_Closed;

  if (isUsing()) {
    const File &file = mFiles.Current();
    if (mNumRecordsMatchedByName == file.mRecords.size())
      return;
    // NOTE: "StringMap iteration order, however, is not guaranteed to
    // be deterministic".  So sort by name before reporting.
    // Alternatively, if we record additional information, we could
    // sort by source location or by order in which we discovered the
    // need to export.
    std::vector<llvm::StringRef> Non64RecordNames;
    for (auto I = file.mRecords.begin(), E = file.mRecords.end(); I != E; I++)
      if (!I->getValue().mMatchedByName && I->getValue().mOrdinary)
        Non64RecordNames.push_back(I->getKey());
    std::sort(Non64RecordNames.begin(), Non64RecordNames.end(),
              [](llvm::StringRef a, llvm::StringRef b) { return a.compare(b)==-1; });
    for (auto N : Non64RecordNames)
      mRSC->ReportError("in file '%0' structure '%1' is exported only for 32-bit targets")
          << file.mRSSourceFileName << N.str();
  }
}

void ReflectionState::declareRecord(const RSExportRecordType *ERT, bool Ordinary) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  slangAssert(mRecordsState == RS_Open);

  auto &records = mFiles.Current().mRecords;
  if (isCollecting()) {
    // Keep struct/field layout in sync with
    // RSReflectionJava::genPackVarOfType() and
    // RSReflectionJavaElementBuilder::genAddElement()

    // Save properties of record

    const size_t FieldCount = ERT->fields_size();
    File::Record::Field *Fields = new File::Record::Field[FieldCount];

    size_t Pos = 0;  // Relative position of field within record
    unsigned FieldIdx = 0;
    for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), E = ERT->fields_end();
         I != E; I++, FieldIdx++) {
      const RSExportRecordType::Field *FieldExport = *I;
      size_t FieldOffset = FieldExport->getOffsetInParent();
      const RSExportType *T = FieldExport->getType();
      size_t FieldStoreSize = T->getStoreSize();
      size_t FieldAllocSize = T->getAllocSize();

      slangAssert(FieldOffset >= Pos);
      slangAssert(FieldAllocSize >= FieldStoreSize);

      auto &FieldState = Fields[FieldIdx];
      FieldState.mName = FieldExport->getName();
      FieldState.mType = canon(getUniqueTypeName(T));
      FieldState.mPrePadding = FieldOffset - Pos;
      FieldState.mPostPadding = FieldAllocSize - FieldStoreSize;
      FieldState.mOffset = FieldOffset;
      FieldState.mStoreSize = FieldStoreSize;

      Pos = FieldOffset + FieldAllocSize;
    }

    slangAssert(ERT->getAllocSize() >= Pos);

    // Insert record into map

    slangAssert(records.find(ERT->getName()) == records.end());
    File::Record &record = records[ERT->getName()];
    record.mFields = Fields;
    record.mFieldCount = FieldCount;
    record.mPostPadding = ERT->getAllocSize() - Pos;
    record.mAllocSize = ERT->getAllocSize();
    record.mOrdinary = Ordinary;
    record.mMatchedByName = false;
  }
  if (isUsing()) {
    if (!Ordinary)
      return;

    const auto RIT = records.find(ERT->getName());
    if (RIT == records.end()) {
      // This doesn't actually break reflection, but that's a
      // coincidence of the fact that we reflect during the 64-bit
      // compilation pass rather than the 32-bit compilation pass, so
      // a record that's only classified as exported during the 64-bit
      // compilation pass doesn't cause any problems.
      mRSC->ReportError(ERT->getLocation(), "structure '%0' is exported only for 64-bit targets")
          << ERT->getName();
      return;
    }
    File::Record &record = RIT->getValue();
    record.mMatchedByName = true;
    ++mNumRecordsMatchedByName;
    slangAssert(record.mOrdinary);

    if (ERT->fields_size() != record.mFieldCount) {
      mRSC->ReportError(ERT->getLocation(),
                        "exported structure '%0' has %1 field%s1 for 32-bit targets "
                        "but %2 field%s2 for 64-bit targets")
          << ERT->getName() << unsigned(record.mFieldCount) << unsigned(ERT->fields_size());
      return;
    }

    // Note that we are deliberately NOT comparing layout properties
    // (such as Field offsets and sizes, or Record allocation size);
    // we need to tolerate layout differences between 32-bit
    // compilation and 64-bit compilation.

    unsigned FieldIdx = 0;
    for (RSExportRecordType::const_field_iterator I = ERT->fields_begin(), E = ERT->fields_end();
         I != E; I++, FieldIdx++) {
      const RSExportRecordType::Field &FieldExport = **I;
      const File::Record::Field &FieldState = record.mFields[FieldIdx];
      if (FieldState.mName != FieldExport.getName()) {
        mRSC->ReportError(ERT->getLocation(),
                          "%ordinal0 field of exported structure '%1' "
                          "is '%2' for 32-bit targets "
                          "but '%3' for 64-bit targets")
            << (FieldIdx + 1) << ERT->getName() << FieldState.mName << FieldExport.getName();
        return;
      }
      const std::string FieldExportType = getUniqueTypeName(FieldExport.getType());
      if (!FieldState.mType.equals(FieldExportType)) {
        mRSC->ReportError(ERT->getLocation(),
                          "field '%0' of exported structure '%1' "
                          "has type '%2' for 32-bit targets "
                          "but type '%3' for 64-bit targets")
            << FieldState.mName << ERT->getName() << FieldState.mType.str() << FieldExportType;
      }
    }
  }
}

ReflectionState::Record32
ReflectionState::getRecord32(const RSExportRecordType *ERT) {
  if (isUsing()) {
    const auto &Records = mFiles.Current().mRecords;
    const auto RIT = Records.find(ERT->getName());
    if (RIT != Records.end())
      return Record32(&RIT->getValue());
  }
  return Record32();
}

// Reduce //////////////////////////////////////////////////////////////////////////////////////

void ReflectionState::declareReduce(const RSExportReduce *ER, bool IsExportable) {
  slangAssert(!isClosed());
  if (!isActive())
    return;

  auto &reduces = mFiles.Current().mReduces;
  if (isCollecting()) {
    auto &reduce = reduces.CollectNext();
    reduce.mName = ER->getNameReduce();

    const auto &InTypes = ER->getAccumulatorInTypes();
    const size_t InTypesSize = InTypes.size();
    reduce.mAccumInCount = InTypesSize;
    reduce.mAccumIns = new llvm::StringRef[InTypesSize];
    unsigned InTypesIdx = 0;
    for (const auto &InType : InTypes)
      reduce.mAccumIns[InTypesIdx++] = canon(getUniqueTypeName(InType));

    reduce.mResult = canon(getUniqueTypeName(ER->getResultType()));
    reduce.mIsExportable = IsExportable;
  }
  if (isUsing()) {
    if (mReducesOrderFatal)
      return;

    const std::string Name = ER->getNameReduce();

    if (reduces.isFinished()) {
      // This doesn't actually break reflection, but that's a
      // coincidence of the fact that we reflect during the 64-bit
      // compilation pass rather than the 32-bit compilation pass, and
      // of the fact that the "extra" reduction kernel(s) are at the
      // end.
      mRSC->ReportError(ER->getLocation(),
                        "reduction kernel '%0' is only present for 64-bit targets")
          << Name;
      return;
    }

    auto &reduce = reduces.UseNext();

    if (reduce.mName != Name) {
      // Order matters because it determines slot number.  We might be
      // able to tolerate certain cases if we ignore non-exportable
      // kernels in the two sequences (32-bit and 64-bit) -- non-exportable
      // kernels do not take up slot numbers.
      mRSC->ReportError(ER->getLocation(),
                        "%ordinal0 reduction kernel is '%1' for 32-bit targets "
                        "but '%2' for 64-bit targets")
          << unsigned(reduces.CurrentIdx() + 1)
          << reduce.mName
          << Name;
      mReducesOrderFatal = true;
      return;
    }

    // If at least one of the two kernels (32-bit or 64-bit) is not
    // exporable, then there will be no reflection for that kernel,
    // and so any mismatch in result type or in inputs is irrelevant.
    // However, we may make more kernels exportable in the future.
    // Therefore, we'll forbid mismatches anyway.

    if (reduce.mIsExportable != IsExportable) {
      mRSC->ReportError(ER->getLocation(),
                        "reduction kernel '%0' is reflected in Java only for %select{32|64}1-bit targets")
          << reduce.mName
          << IsExportable;
    }

    const std::string ResultType = getUniqueTypeName(ER->getResultType());
    if (!reduce.mResult.equals(ResultType)) {
      mRSC->ReportError(ER->getLocation(),
                        "reduction kernel '%0' has result type '%1' for 32-bit targets "
                        "but result type '%2' for 64-bit targets")
          << reduce.mName << reduce.mResult.str() << ResultType;
    }

    const auto &InTypes = ER->getAccumulatorInTypes();
    if (reduce.mAccumInCount != InTypes.size()) {
      mRSC->ReportError(ER->getLocation(),
                        "reduction kernel '%0' has %1 input%s1 for 32-bit targets "
                        "but %2 input%s2 for 64-bit targets")
          << Name << unsigned(reduce.mAccumInCount) << unsigned(InTypes.size());
      return;
    }
    unsigned FieldIdx = 0;
    for (const auto &InType : InTypes) {
      const std::string InTypeName = getUniqueTypeName(InType);
      const llvm::StringRef StateInTypeName = reduce.mAccumIns[FieldIdx++];
      if (!StateInTypeName.equals(InTypeName)) {
        mRSC->ReportError(ER->getLocation(),
                          "%ordinal0 input of reduction kernel '%1' "
                          "has type '%2' for 32-bit targets "
                          "but type '%3' for 64-bit targets")
            << FieldIdx
            << Name
            << StateInTypeName.str()
            << InTypeName;
      }
    }
  }
}

void ReflectionState::endReduces() {
  if (!isUsing() || mReducesOrderFatal)
    return;

  auto &reduces = mFiles.Current().mReduces;
  while (!reduces.isFinished()) {
    const auto &reduce = reduces.UseNext();
    mRSC->ReportError("in file '%0' reduction kernel '%1' is only present for 32-bit targets")
        << mFiles.Current().mRSSourceFileName << reduce.mName;
  }
}

// Variable ////////////////////////////////////////////////////////////////////////////////////

// Keep this in sync with initialization handling in
// RSReflectionJava::genScriptClassConstructor().
ReflectionState::Val32 ReflectionState::declareVariable(const RSExportVar *EV) {
  slangAssert(!isClosed());
  if (!isActive())
    return NoVal32();

  auto &variables = mFiles.Current().mVariables;
  if (isCollecting()) {
    auto &variable = variables.CollectNext();
    variable.mName = EV->getName();
    variable.mType = canon(getUniqueTypeName(EV->getType()));
    variable.mAllocSize = EV->getType()->getAllocSize();
    variable.mIsConst = EV->isConst();
    if (!EV->getInit().isUninit()) {
      variable.mInitializerCount = 1;
      variable.mInitializers = new clang::APValue[1];
      variable.mInitializers[0] = EV->getInit();
    } else if (EV->getArraySize()) {
      variable.mInitializerCount = EV->getNumInits();
      variable.mInitializers = new clang::APValue[variable.mInitializerCount];
      for (size_t i = 0; i < variable.mInitializerCount; ++i)
        variable.mInitializers[i] = EV->getInitArray(i);
    } else {
      variable.mInitializerCount = 0;
    }
    return NoVal32();
  }

  /*-- isUsing() -----------------------------------------------------------*/

  slangAssert(isUsing());

  if (mVariablesOrderFatal)
    return NoVal32();

  if (variables.isFinished()) {
    // This doesn't actually break reflection, but that's a
    // coincidence of the fact that we reflect during the 64-bit
    // compilation pass rather than the 32-bit compilation pass, and
    // of the fact that the "extra" variable(s) are at the end.
    mRSC->ReportError(EV->getLocation(), "global variable '%0' is only present for 64-bit targets")
        << EV->getName();
    return NoVal32();
  }

  const auto &variable = variables.UseNext();

  if (variable.mName != EV->getName()) {
    // Order matters because it determines slot number
    mRSC->ReportError(EV->getLocation(),
                      "%ordinal0 global variable is '%1' for 32-bit targets "
                      "but '%2' for 64-bit targets")
        << unsigned(variables.CurrentIdx() + 1)
        << variable.mName
        << EV->getName();
    mVariablesOrderFatal = true;
    return NoVal32();
  }

  const std::string TypeName = getUniqueTypeName(EV->getType());

  if (!variable.mType.equals(TypeName)) {
    mRSC->ReportError(EV->getLocation(),
                      "global variable '%0' has type '%1' for 32-bit targets "
                      "but type '%2' for 64-bit targets")
        << EV->getName()
        << variable.mType.str()
        << TypeName;
    return NoVal32();
  }

  if (variable.mIsConst != EV->isConst()) {
    mRSC->ReportError(EV->getLocation(),
                      "global variable '%0' has inconsistent 'const' qualification "
                      "between 32-bit targets and 64-bit targets")
        << EV->getName();
    return NoVal32();
  }

  // NOTE: Certain syntactically different but semantically
  // equivalent initialization patterns are unnecessarily rejected
  // as errors.
  //
  // Background:
  //
  // . A vector initialized with a scalar value is treated
  //   by reflection as if all elements of the vector are
  //   initialized with the scalar value.
  // . A vector may be initialized with a vector of greater
  //   length; reflection ignores the extra initializers.
  // . If only the beginning of a vector is explicitly
  //   initialized, reflection treats it as if trailing elements are
  //   initialized to zero (by issuing explicit assignments to those
  //   trailing elements).
  // . If only the beginning of an array is explicitly initialized,
  //   reflection treats it as if trailing elements are initialized
  //   to zero (by Java rules for newly-created arrays).
  //
  // Unnecessarily rejected as errors:
  //
  // . One compile initializes a vector with a scalar, and
  //   another initializes it with a vector whose elements
  //   are the scalar, as in
  //
  //     int2 x =
  //     #ifdef __LP64__
  //       1
  //     #else
  //       { 1, 1 }
  //     #endif
  //
  // . Compiles initialize a vector with vectors of different
  //   lengths, but the initializers agree up to the length
  //   of the variable being initialized, as in
  //
  //     int2 x = { 1, 2
  //     #ifdef __LP64__
  //       3
  //     #else
  //       4
  //     #endif
  //     };
  //
  // . Two compiles agree with the initializer for a vector or
  //   array, except that one has some number of explicit trailing
  //   zeroes, as in
  //
  //     int x[4] = { 3, 2, 1
  //     #ifdef __LP64__
  //       , 0
  //     #endif
  //     };

  bool MismatchedInitializers = false;
  if (!EV->getInit().isUninit()) {
    // Use phase has a scalar initializer.
    // Make sure that Collect phase had a matching scalar initializer.
    if ((variable.mInitializerCount != 1) ||
        !equal(variable.mInitializers[0], EV->getInit()))
      MismatchedInitializers = true;
  } else if (EV->getArraySize()) {
    const size_t UseSize = EV->getNumInits();
    if (variable.mInitializerCount != UseSize)
      MismatchedInitializers = true;
    else {
      for (int i = 0; i < UseSize; ++i)
        if (!equal(variable.mInitializers[i], EV->getInitArray(i))) {
          MismatchedInitializers = true;
          break;
        }
    }
  } else if (variable.mInitializerCount != 0) {
    // Use phase does not have a scalar initializer, variable is not
    // an array, and Collect phase has an initializer.  This is an error.
    MismatchedInitializers = true;
  }

  if (MismatchedInitializers) {
    mRSC->ReportError(EV->getLocation(),
                      "global variable '%0' is initialized differently for 32-bit targets "
                      "than for 64-bit targets")
        << EV->getName();
    return NoVal32();
  }

  return Val32(true, variable.mAllocSize);
}

void ReflectionState::endVariables() {
  if (!isUsing() || mVariablesOrderFatal)
    return;

  auto &variables = mFiles.Current().mVariables;
  while (!variables.isFinished()) {
    const auto &variable = variables.UseNext();
    mRSC->ReportError("in file '%0' global variable '%1' is only present for 32-bit targets")
        << mFiles.Current().mRSSourceFileName << variable.mName;
  }
}

}  // namespace slang
