/*
 * Copyright 2010, 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 "slang.h"

#include <stdlib.h>

#include <cstring>
#include <list>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"

#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"

#include "clang/Frontend/DependencyOutputOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/PCHContainerOperations.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"

#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"

#include "clang/Parse/ParseAST.h"

#include "clang/Sema/SemaDiagnostic.h"

#include "llvm/ADT/IntrusiveRefCntPtr.h"

#include "llvm/Bitcode/ReaderWriter.h"

// More force linking
#include "llvm/Linker/Linker.h"

// Force linking all passes/vmcore stuffs to libslang.so
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"

#include "os_sep.h"
#include "rs_cc_options.h"
#include "slang_assert.h"
#include "slang_backend.h"

#include "slang_rs_context.h"
#include "slang_rs_export_type.h"

#include "slang_rs_reflection.h"
#include "slang_rs_reflection_cpp.h"


namespace {

static const char *kRSTriple32 = "renderscript32-none-linux-gnueabi";
static const char *kRSTriple64 = "renderscript64-none-linux-gnueabi";

}  // namespace

namespace slang {


#define FS_SUFFIX  "fs"

#define RS_HEADER_SUFFIX  "rsh"

/* RS_HEADER_ENTRY(name) */
#define ENUM_RS_HEADER()  \
  RS_HEADER_ENTRY(rs_allocation_create) \
  RS_HEADER_ENTRY(rs_allocation_data) \
  RS_HEADER_ENTRY(rs_atomic) \
  RS_HEADER_ENTRY(rs_convert) \
  RS_HEADER_ENTRY(rs_core) \
  RS_HEADER_ENTRY(rs_debug) \
  RS_HEADER_ENTRY(rs_for_each) \
  RS_HEADER_ENTRY(rs_graphics) \
  RS_HEADER_ENTRY(rs_graphics_types) \
  RS_HEADER_ENTRY(rs_io) \
  RS_HEADER_ENTRY(rs_math) \
  RS_HEADER_ENTRY(rs_matrix) \
  RS_HEADER_ENTRY(rs_object_info) \
  RS_HEADER_ENTRY(rs_object_types) \
  RS_HEADER_ENTRY(rs_quaternion) \
  RS_HEADER_ENTRY(rs_time) \
  RS_HEADER_ENTRY(rs_value_types) \
  RS_HEADER_ENTRY(rs_vector_math) \


// The named of metadata node that pragma resides (should be synced with
// bcc.cpp)
const llvm::StringRef Slang::PragmaMetadataName = "#pragma";

static llvm::LLVMContext globalContext;

llvm::LLVMContext &getGlobalLLVMContext() { return globalContext; }

static inline llvm::tool_output_file *
OpenOutputFile(const char *OutputFile,
               llvm::sys::fs::OpenFlags Flags,
               std::error_code &EC,
               clang::DiagnosticsEngine *DiagEngine) {
  slangAssert((OutputFile != nullptr) &&
              (DiagEngine != nullptr) && "Invalid parameter!");

  EC = llvm::sys::fs::create_directories(
      llvm::sys::path::parent_path(OutputFile));
  if (!EC) {
    llvm::tool_output_file *F =
          new llvm::tool_output_file(OutputFile, EC, Flags);
    if (F != nullptr)
      return F;
  }

  // Report error here.
  DiagEngine->Report(clang::diag::err_fe_error_opening)
    << OutputFile << EC.message();

  return nullptr;
}

void Slang::createTarget(uint32_t BitWidth) {
  if (BitWidth == 64) {
    mTargetOpts->Triple = kRSTriple64;
  } else {
    mTargetOpts->Triple = kRSTriple32;
  }

  mTarget.reset(clang::TargetInfo::CreateTargetInfo(*mDiagEngine,
                                                    mTargetOpts));
}

void Slang::createFileManager() {
  mFileSysOpt.reset(new clang::FileSystemOptions());
  mFileMgr.reset(new clang::FileManager(*mFileSysOpt));
}

void Slang::createSourceManager() {
  mSourceMgr.reset(new clang::SourceManager(*mDiagEngine, *mFileMgr));
}

void Slang::createPreprocessor() {
  // Default only search header file in current dir
  clang::HeaderSearch *HeaderInfo = new clang::HeaderSearch(&getHeaderSearchOpts(),
                                                            *mSourceMgr,
                                                            *mDiagEngine,
                                                            LangOpts,
                                                            mTarget.get());

  mPP.reset(new clang::Preprocessor(&getPreprocessorOpts(),
                                    *mDiagEngine,
                                    LangOpts,
                                    *mSourceMgr,
                                    *HeaderInfo,
                                    *this,
                                    nullptr,
                                    /* OwnsHeaderSearch = */true));
  // Initialize the preprocessor
  mPP->Initialize(getTargetInfo());
  clang::FrontendOptions FEOpts;

  auto *Reader = mPCHContainerOperations->getReaderOrNull(
      getHeaderSearchOpts().ModuleFormat);
  clang::InitializePreprocessor(*mPP, getPreprocessorOpts(), *Reader, FEOpts);

  clang::ApplyHeaderSearchOptions(*HeaderInfo, getHeaderSearchOpts(), LangOpts,
      mPP->getTargetInfo().getTriple());

  mPragmas.clear();

  std::vector<clang::DirectoryLookup> SearchList;
  for (unsigned i = 0, e = mIncludePaths.size(); i != e; i++) {
    if (const clang::DirectoryEntry *DE =
            mFileMgr->getDirectory(mIncludePaths[i])) {
      SearchList.push_back(clang::DirectoryLookup(DE,
                                                  clang::SrcMgr::C_System,
                                                  false));
    }
  }

  HeaderInfo->SetSearchPaths(SearchList,
                             /* angledDirIdx = */1,
                             /* systemDixIdx = */1,
                             /* noCurDirSearch = */false);

  initPreprocessor();
}

void Slang::createASTContext() {
  mASTContext.reset(
      new clang::ASTContext(LangOpts, *mSourceMgr, mPP->getIdentifierTable(),
                            mPP->getSelectorTable(), mPP->getBuiltinInfo()));
  mASTContext->InitBuiltinTypes(getTargetInfo());
  initASTContext();
}

clang::ASTConsumer *
Slang::createBackend(const RSCCOptions &Opts, const clang::CodeGenOptions &CodeGenOpts,
                     llvm::raw_ostream *OS, OutputType OT) {
  auto *B = new Backend(mRSContext, &getDiagnostics(), Opts,
                        getHeaderSearchOpts(), getPreprocessorOpts(),
                        CodeGenOpts, getTargetOptions(), &mPragmas, OS, OT,
                        getSourceManager(), mAllowRSPrefix, mIsFilterscript);
  B->Initialize(getASTContext());
  return B;
}

Slang::Slang(uint32_t BitWidth, clang::DiagnosticsEngine *DiagEngine,
             DiagnosticBuffer *DiagClient)
    : mDiagEngine(DiagEngine), mDiagClient(DiagClient),
      mTargetOpts(new clang::TargetOptions()),
      mHSOpts(new clang::HeaderSearchOptions()),
      mPPOpts(new clang::PreprocessorOptions()),
      mPCHContainerOperations(std::make_shared<clang::PCHContainerOperations>()),
      mOT(OT_Default), mRSContext(nullptr), mAllowRSPrefix(false), mTargetAPI(0),
      mVerbose(false), mIsFilterscript(false) {
  // Please refer to include/clang/Basic/LangOptions.h to setup
  // the options.
  LangOpts.RTTI = 0;  // Turn off the RTTI information support
  LangOpts.LineComment = 1;
  LangOpts.C99 = 1;
  LangOpts.RenderScript = 1;
  LangOpts.LaxVectorConversions = 0;  // Do not bitcast vectors!
  LangOpts.CharIsSigned = 1;  // Signed char is our default.

  CodeGenOpts.OptimizationLevel = 3;

  // We must set StackRealignment, because the default is for the actual
  // Clang driver to pass this option (-mstackrealign) directly to cc1.
  // Since we don't use Clang's driver, we need to similarly supply it.
  // If StackRealignment is zero (i.e. the option wasn't set), then the
  // backend assumes that it can't adjust the stack in any way, which breaks
  // alignment for vector loads/stores.
  CodeGenOpts.StackRealignment = 1;

  createTarget(BitWidth);
  createFileManager();
  createSourceManager();
}

Slang::~Slang() {
  delete mRSContext;
  for (ReflectedDefinitionListTy::iterator I = ReflectedDefinitions.begin(),
                                           E = ReflectedDefinitions.end();
       I != E; I++) {
    delete I->getValue().first;
  }
}

clang::ModuleLoadResult Slang::loadModule(
    clang::SourceLocation ImportLoc,
    clang::ModuleIdPath Path,
    clang::Module::NameVisibilityKind Visibility,
    bool IsInclusionDirective) {
  slangAssert(0 && "Not implemented");
  return clang::ModuleLoadResult();
}

bool Slang::setInputSource(llvm::StringRef InputFile) {
  mInputFileName = InputFile.str();

  mSourceMgr->clearIDTables();

  const clang::FileEntry *File = mFileMgr->getFile(InputFile);
  if (File) {
    mSourceMgr->setMainFileID(mSourceMgr->createFileID(File,
        clang::SourceLocation(), clang::SrcMgr::C_User));
  }

  if (mSourceMgr->getMainFileID().isInvalid()) {
    mDiagEngine->Report(clang::diag::err_fe_error_reading) << InputFile;
    return false;
  }

  return true;
}

bool Slang::setOutput(const char *OutputFile) {
  std::error_code EC;
  llvm::tool_output_file *OS = nullptr;

  switch (mOT) {
    case OT_Dependency:
    case OT_Assembly:
    case OT_LLVMAssembly: {
      OS = OpenOutputFile(OutputFile, llvm::sys::fs::F_Text, EC, mDiagEngine);
      break;
    }
    case OT_Nothing: {
      break;
    }
    case OT_Object:
    case OT_Bitcode: {
      OS = OpenOutputFile(OutputFile, llvm::sys::fs::F_None, EC, mDiagEngine);
      break;
    }
    default: {
      llvm_unreachable("Unknown compiler output type");
    }
  }

  if (EC)
    return false;

  mOS.reset(OS);

  mOutputFileName = OutputFile;

  return true;
}

bool Slang::setDepOutput(const char *OutputFile) {
  std::error_code EC;

  mDOS.reset(
      OpenOutputFile(OutputFile, llvm::sys::fs::F_Text, EC, mDiagEngine));
  if (EC || (mDOS.get() == nullptr))
    return false;

  mDepOutputFileName = OutputFile;

  return true;
}

int Slang::generateDepFile(bool PhonyTarget) {
  if (mDiagEngine->hasErrorOccurred())
    return 1;
  if (mDOS.get() == nullptr)
    return 1;

  // Initialize options for generating dependency file
  clang::DependencyOutputOptions DepOpts;
  DepOpts.IncludeSystemHeaders = 1;
  if (PhonyTarget)
    DepOpts.UsePhonyTargets = 1;
  DepOpts.OutputFile = mDepOutputFileName;
  DepOpts.Targets = mAdditionalDepTargets;
  DepOpts.Targets.push_back(mDepTargetBCFileName);
  for (std::vector<std::string>::const_iterator
           I = mGeneratedFileNames.begin(), E = mGeneratedFileNames.end();
       I != E;
       I++) {
    DepOpts.Targets.push_back(*I);
  }
  mGeneratedFileNames.clear();

  // Per-compilation needed initialization
  createPreprocessor();
  clang::DependencyFileGenerator::CreateAndAttachToPreprocessor(*mPP.get(), DepOpts);

  // Inform the diagnostic client we are processing a source file
  mDiagClient->BeginSourceFile(LangOpts, mPP.get());

  // Go through the source file (no operations necessary)
  clang::Token Tok;
  mPP->EnterMainSourceFile();
  do {
    mPP->Lex(Tok);
  } while (Tok.isNot(clang::tok::eof));

  mPP->EndSourceFile();

  // Declare success if no error
  if (!mDiagEngine->hasErrorOccurred())
    mDOS->keep();

  // Clean up after compilation
  mPP.reset();
  mDOS.reset();

  return mDiagEngine->hasErrorOccurred() ? 1 : 0;
}

int Slang::compile(const RSCCOptions &Opts) {
  if (mDiagEngine->hasErrorOccurred())
    return 1;
  if (mOS.get() == nullptr)
    return 1;

  // Here is per-compilation needed initialization
  createPreprocessor();
  createASTContext();

  mBackend.reset(createBackend(Opts, CodeGenOpts, &mOS->os(), mOT));

  // Inform the diagnostic client we are processing a source file
  mDiagClient->BeginSourceFile(LangOpts, mPP.get());

  // The core of the slang compiler
  ParseAST(*mPP, mBackend.get(), *mASTContext);

  // Inform the diagnostic client we are done with previous source file
  mDiagClient->EndSourceFile();

  // Declare success if no error
  if (!mDiagEngine->hasErrorOccurred())
    mOS->keep();

  // The compilation ended, clear
  mBackend.reset();
  mOS.reset();

  return mDiagEngine->hasErrorOccurred() ? 1 : 0;
}

void Slang::setDebugMetadataEmission(bool EmitDebug) {
  if (EmitDebug)
    CodeGenOpts.setDebugInfo(clang::codegenoptions::FullDebugInfo);
  else
    CodeGenOpts.setDebugInfo(clang::codegenoptions::NoDebugInfo);
}

void Slang::setOptimizationLevel(llvm::CodeGenOpt::Level OptimizationLevel) {
  CodeGenOpts.OptimizationLevel = OptimizationLevel;
}

bool Slang::isFilterscript(const char *Filename) {
  const char *c = strrchr(Filename, '.');
  if (c && !strncmp(FS_SUFFIX, c + 1, strlen(FS_SUFFIX) + 1)) {
    return true;
  } else {
    return false;
  }
}

bool Slang::generateJavaBitcodeAccessor(const std::string &OutputPathBase,
                                          const std::string &PackageName,
                                          const std::string *LicenseNote) {
  RSSlangReflectUtils::BitCodeAccessorContext BCAccessorContext;

  BCAccessorContext.rsFileName = getInputFileName().c_str();
  BCAccessorContext.bc32FileName = mOutput32FileName.c_str();
  BCAccessorContext.bc64FileName = mOutputFileName.c_str();
  BCAccessorContext.reflectPath = OutputPathBase.c_str();
  BCAccessorContext.packageName = PackageName.c_str();
  BCAccessorContext.licenseNote = LicenseNote;
  BCAccessorContext.bcStorage = BCST_JAVA_CODE;   // Must be BCST_JAVA_CODE
  BCAccessorContext.verbose = false;

  return RSSlangReflectUtils::GenerateJavaBitCodeAccessor(BCAccessorContext);
}

bool Slang::checkODR(const char *CurInputFile) {
  for (RSContext::ExportableList::iterator I = mRSContext->exportable_begin(),
          E = mRSContext->exportable_end();
       I != E;
       I++) {
    RSExportable *RSE = *I;
    if (RSE->getKind() != RSExportable::EX_TYPE)
      continue;

    RSExportType *ET = static_cast<RSExportType *>(RSE);
    if (ET->getClass() != RSExportType::ExportClassRecord)
      continue;

    RSExportRecordType *ERT = static_cast<RSExportRecordType *>(ET);

    // Artificial record types (create by us not by user in the source) always
    // conforms the ODR.
    if (ERT->isArtificial())
      continue;

    // Key to lookup ERT in ReflectedDefinitions
    llvm::StringRef RDKey(ERT->getName());
    ReflectedDefinitionListTy::const_iterator RD =
        ReflectedDefinitions.find(RDKey);

    if (RD != ReflectedDefinitions.end()) {
      const RSExportRecordType *Reflected = RD->getValue().first;

      // See RSExportRecordType::matchODR for the logic
      if (!Reflected->matchODR(ERT, true)) {
        unsigned DiagID = mDiagEngine->getCustomDiagID(
            clang::DiagnosticsEngine::Error,
            "type '%0' in different translation unit (%1 v.s. %2) "
            "has incompatible type definition");
        getDiagnostics().Report(DiagID) << Reflected->getName()
                                        << getInputFileName()
                                        << RD->getValue().second;
        return false;
      }
    } else {
      llvm::StringMapEntry<ReflectedDefinitionTy> *ME =
          llvm::StringMapEntry<ReflectedDefinitionTy>::Create(RDKey);
      ME->setValue(std::make_pair(ERT, CurInputFile));

      if (!ReflectedDefinitions.insert(ME)) {
        slangAssert(false && "Type shouldn't be in map yet!");
      }

      // Take the ownership of ERT such that it won't be freed in ~RSContext().
      ERT->keep();
    }
  }
  return true;
}

void Slang::initPreprocessor() {
  clang::Preprocessor &PP = getPreprocessor();

  std::stringstream RSH;
  RSH << PP.getPredefines();
  RSH << "#define RS_VERSION " << mTargetAPI << "\n";
  RSH << "#include \"rs_core." RS_HEADER_SUFFIX "\"\n";
  PP.setPredefines(RSH.str());
}

void Slang::initASTContext() {
  mRSContext = new RSContext(getPreprocessor(),
                             getASTContext(),
                             getTargetInfo(),
                             &mPragmas,
                             mTargetAPI,
                             mVerbose);
}

bool Slang::IsRSHeaderFile(const char *File) {
#define RS_HEADER_ENTRY(name)  \
  if (::strcmp(File, #name "." RS_HEADER_SUFFIX) == 0)  \
    return true;
ENUM_RS_HEADER()
#undef RS_HEADER_ENTRY
  return false;
}

bool Slang::IsLocInRSHeaderFile(const clang::SourceLocation &Loc,
                                  const clang::SourceManager &SourceMgr) {
  clang::FullSourceLoc FSL(Loc, SourceMgr);
  clang::PresumedLoc PLoc = SourceMgr.getPresumedLoc(FSL);

  const char *Filename = PLoc.getFilename();
  if (!Filename) {
    return false;
  } else {
    return IsRSHeaderFile(llvm::sys::path::filename(Filename).data());
  }
}

bool Slang::compile(
    const std::list<std::pair<const char*, const char*> > &IOFiles64,
    const std::list<std::pair<const char*, const char*> > &IOFiles32,
    const std::list<std::pair<const char*, const char*> > &DepFiles,
    const RSCCOptions &Opts,
    clang::DiagnosticOptions &DiagOpts) {
  if (IOFiles32.empty())
    return true;

  if (Opts.mEmitDependency && (DepFiles.size() != IOFiles32.size())) {
    unsigned DiagID = mDiagEngine->getCustomDiagID(
        clang::DiagnosticsEngine::Error,
        "invalid parameter for output dependencies files.");
    getDiagnostics().Report(DiagID);
    return false;
  }

  if (Opts.mEmit3264 && (IOFiles64.size() != IOFiles32.size())) {
    slangAssert(false && "Should have equal number of 32/64-bit files");
    return false;
  }

  std::string RealPackageName;

  const char *InputFile, *Output64File, *Output32File, *BCOutputFile,
             *DepOutputFile;

  setIncludePaths(Opts.mIncludePaths);
  setOutputType(Opts.mOutputType);
  if (Opts.mEmitDependency) {
    setAdditionalDepTargets(Opts.mAdditionalDepTargets);
  }

  setDebugMetadataEmission(Opts.mDebugEmission);

  setOptimizationLevel(Opts.mOptimizationLevel);

  mAllowRSPrefix = Opts.mAllowRSPrefix;

  mTargetAPI = Opts.mTargetAPI;
  if (mTargetAPI != SLANG_DEVELOPMENT_TARGET_API &&
      (mTargetAPI < SLANG_MINIMUM_TARGET_API ||
       mTargetAPI > SLANG_MAXIMUM_TARGET_API)) {
    unsigned DiagID = mDiagEngine->getCustomDiagID(
        clang::DiagnosticsEngine::Error,
        "target API level '%0' is out of range ('%1' - '%2')");
    getDiagnostics().Report(DiagID) << mTargetAPI << SLANG_MINIMUM_TARGET_API
                                    << SLANG_MAXIMUM_TARGET_API;
    return false;
  }

  if (mTargetAPI >= SLANG_M_TARGET_API) {
    LangOpts.NativeHalfArgsAndReturns = 1;
    LangOpts.NativeHalfType = 1;
    LangOpts.HalfArgsAndReturns = 1;
  }

  mVerbose = Opts.mVerbose;

  // Skip generation of warnings a second time if we are doing more than just
  // a single pass over the input file.
  bool SuppressAllWarnings = (Opts.mOutputType != Slang::OT_Dependency);

  std::list<std::pair<const char*, const char*> >::const_iterator
      IOFile64Iter = IOFiles64.begin(),
      IOFile32Iter = IOFiles32.begin(),
      DepFileIter = DepFiles.begin();

  for (unsigned i = 0, e = IOFiles32.size(); i != e; i++) {
    InputFile = IOFile64Iter->first;
    Output64File = IOFile64Iter->second;
    Output32File = IOFile32Iter->second;

    if (!setInputSource(InputFile))
      return false;

    if (!setOutput(Output64File))
      return false;

    // For use with 64-bit compilation/reflection. This only sets the filename of
    // the 32-bit bitcode file, and doesn't actually verify it already exists.
    mOutput32FileName = Output32File;

    mIsFilterscript = isFilterscript(InputFile);

    CodeGenOpts.MainFileName = mInputFileName;

    if (Slang::compile(Opts) > 0)
      return false;

    if (!Opts.mJavaReflectionPackageName.empty()) {
      mRSContext->setReflectJavaPackageName(Opts.mJavaReflectionPackageName);
    }
    const std::string &RealPackageName =
        mRSContext->getReflectJavaPackageName();

    bool doReflection = true;
    if (Opts.mEmit3264 && (Opts.mBitWidth == 32)) {
      // Skip reflection on the 32-bit path if we are going to emit it on the
      // 64-bit path.
      doReflection = false;
    }
    if (Opts.mOutputType != Slang::OT_Dependency && doReflection) {

      if (Opts.mBitcodeStorage == BCST_CPP_CODE) {
        const std::string &outputFileName = (Opts.mBitWidth == 64) ?
                                            mOutputFileName : mOutput32FileName;
        RSReflectionCpp R(mRSContext, Opts.mJavaReflectionPathBase,
                          getInputFileName(), outputFileName);
        if (!R.reflect()) {
            return false;
        }
      } else {
        if (!Opts.mRSPackageName.empty()) {
          mRSContext->setRSPackageName(Opts.mRSPackageName);
        }

        std::vector<std::string> generatedFileNames;
        RSReflectionJava R(mRSContext, &generatedFileNames,
                           Opts.mJavaReflectionPathBase, getInputFileName(),
                           mOutputFileName,
                           Opts.mBitcodeStorage == BCST_JAVA_CODE);
        if (!R.reflect()) {
          // TODO Is this needed or will the error message have been printed
          // already? and why not for the C++ case?
          fprintf(stderr, "RSContext::reflectToJava : failed to do reflection "
                          "(%s)\n",
                  R.getLastError());
          return false;
        }

        for (std::vector<std::string>::const_iterator
                 I = generatedFileNames.begin(), E = generatedFileNames.end();
             I != E;
             I++) {
          std::string ReflectedName = RSSlangReflectUtils::ComputePackagedPath(
              Opts.mJavaReflectionPathBase.c_str(),
              (RealPackageName + OS_PATH_SEPARATOR_STR + *I).c_str());
          appendGeneratedFileName(ReflectedName + ".java");
        }

        if ((Opts.mOutputType == Slang::OT_Bitcode) &&
            (Opts.mBitcodeStorage == BCST_JAVA_CODE) &&
            !generateJavaBitcodeAccessor(Opts.mJavaReflectionPathBase,
                                         RealPackageName.c_str(),
                                         mRSContext->getLicenseNote())) {
          return false;
        }
      }
    }

    if (Opts.mEmitDependency) {
      BCOutputFile = DepFileIter->first;
      DepOutputFile = DepFileIter->second;

      setDepTargetBC(BCOutputFile);

      if (!setDepOutput(DepOutputFile))
        return false;

      if (SuppressAllWarnings) {
        getDiagnostics().setSuppressAllDiagnostics(true);
      }
      if (generateDepFile(Opts.mEmitPhonyDependency) > 0)
        return false;
      if (SuppressAllWarnings) {
        getDiagnostics().setSuppressAllDiagnostics(false);
      }

      DepFileIter++;
    }

    if (!checkODR(InputFile))
      return false;

    IOFile64Iter++;
    IOFile32Iter++;
  }
  return true;
}

}  // namespace slang
