/*
 * 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());
  return 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
