/*
 * Copyright 2012, 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 "bcc/Renderscript/RSExecutable.h"

#include "bcc/Config/Config.h"
#include "bcc/Support/Disassembler.h"
#include "bcc/Support/FileBase.h"
#include "bcc/Support/Log.h"
#include "bcc/Support/OutputFile.h"
#include "bcc/ExecutionEngine/SymbolResolverProxy.h"

#include <utils/String8.h>

using namespace bcc;

const char *RSExecutable::SpecialFunctionNames[] = {
  "root",      // Graphics drawing function or compute kernel.
  "init",      // Initialization routine called implicitly on startup.
  ".rs.dtor",  // Static global destructor for a script instance.
  ".rs.info",  // Variable containing string of RS metadata info.
  NULL         // Must be NULL-terminated.
};

RSExecutable *RSExecutable::Create(RSInfo &pInfo,
                                   FileBase &pObjFile,
                                   SymbolResolverProxy &pResolver) {
  // Load the object file. Enable the GDB's JIT debugging if the script contains
  // debug information.
  ObjectLoader *loader = ObjectLoader::Load(pObjFile,
                                            pResolver,
                                            pInfo.hasDebugInformation());
  if (loader == NULL) {
    return NULL;
  }

  // Now, all things required to build a RSExecutable object are ready.
  RSExecutable *result = new (std::nothrow) RSExecutable(pInfo,
                                                         pObjFile,
                                                         *loader);
  if (result == NULL) {
    ALOGE("Out of memory when create object to hold RS result file for %s!",
          pObjFile.getName().c_str());
    return NULL;
  }

  unsigned idx;
  // Resolve addresses of RS export vars.
  idx = 0;
  const RSInfo::ExportVarNameListTy &export_var_names =
      pInfo.getExportVarNames();
  for (RSInfo::ExportVarNameListTy::const_iterator
           var_iter = export_var_names.begin(),
           var_end = export_var_names.end(); var_iter != var_end;
       var_iter++, idx++) {
    const char *name = *var_iter;
    void *addr = result->getSymbolAddress(name);
    if (addr == NULL) {
      ALOGW("RS export var at entry #%u named %s cannot be found in the result "
            "object!", idx, name);
    }
    result->mExportVarAddrs.push_back(addr);
  }

  // Resolve addresses of RS export functions.
  idx = 0;
  const RSInfo::ExportFuncNameListTy &export_func_names =
      pInfo.getExportFuncNames();
  for (RSInfo::ExportFuncNameListTy::const_iterator
           func_iter = export_func_names.begin(),
           func_end = export_func_names.end(); func_iter != func_end;
       func_iter++, idx++) {
    const char *name = *func_iter;
    void *addr = result->getSymbolAddress(name);
    if (addr == NULL) {
      ALOGW("RS export func at entry #%u named %s cannot be found in the result"
            " object!", idx, name);
    }
    result->mExportFuncAddrs.push_back(addr);
  }

  // Resolve addresses of expanded RS foreach function.
  idx = 0;
  const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
      pInfo.getExportForeachFuncs();
  for (RSInfo::ExportForeachFuncListTy::const_iterator
           foreach_iter = export_foreach_funcs.begin(),
           foreach_end = export_foreach_funcs.end();
       foreach_iter != foreach_end; foreach_iter++, idx++) {
    const char *func_name = foreach_iter->first;
    android::String8 expanded_func_name(func_name);
    expanded_func_name.append(".expand");
    void *addr = result->getSymbolAddress(expanded_func_name.string());
    if (addr == NULL) {
      ALOGW("Expanded RS foreach at entry #%u named %s cannot be found in the "
            "result object!", idx, expanded_func_name.string());
    }
    result->mExportForeachFuncAddrs.push_back(addr);
  }

  // Copy pragma key/value pairs from RSInfo::getPragmas() into mPragmaKeys and
  // mPragmaValues, respectively.
  const RSInfo::PragmaListTy &pragmas = pInfo.getPragmas();
  for (RSInfo::PragmaListTy::const_iterator pragma_iter = pragmas.begin(),
          pragma_end = pragmas.end(); pragma_iter != pragma_end;
       pragma_iter++){
    result->mPragmaKeys.push_back(pragma_iter->first);
    result->mPragmaValues.push_back(pragma_iter->second);
  }

  return result;
}

bool RSExecutable::syncInfo(bool pForce) {
  if (!pForce && !mIsInfoDirty) {
    return true;
  }

  android::String8 info_path = RSInfo::GetPath(*mObjFile);
  OutputFile info_file(info_path.string(), FileBase::kTruncate);

  if (info_file.hasError()) {
    ALOGE("Failed to open the info file %s for write! (%s)", info_path.string(),
          info_file.getErrorMessage().c_str());
    return false;
  }

  // Operation to the RS info file need to acquire the lock on the output file
  // first.
  if (!mObjFile->lock(FileBase::kWriteLock)) {
    ALOGE("Write to RS info file %s required the acquisition of the write lock "
          "on %s but got failure! (%s)", info_path.string(),
          mObjFile->getName().c_str(), info_file.getErrorMessage().c_str());
    return false;
  }

  // Perform the write.
  if (!mInfo->write(info_file)) {
    ALOGE("Failed to sync the RS info file %s!", info_path.string());
    mObjFile->unlock();
    return false;
  }

  mObjFile->unlock();
  mIsInfoDirty = false;
  return true;
}

void RSExecutable::dumpDisassembly(OutputFile &pOutput) const {
#if DEBUG_MC_DISASSEMBLER
  if (pOutput.hasError()) {
    return;
  }

  // Get MC codegen emitted function name list.
  android::Vector<const char *> func_list;

  if (!mLoader->getSymbolNameList(func_list, ObjectLoader::kFunctionType)) {
    ALOGW("Failed to get the list of function name in %s for disassembly!",
          mObjFile->getName().c_str());
  } else {
    // Disassemble each function
    for (size_t i = 0, e = func_list.size(); i != e; i++) {
      const char* func_name = func_list[i];
      void *func = mLoader->getSymbolAddress(func_name);
      size_t func_size = mLoader->getSymbolSize(func_name);

      if (func == NULL) {
        continue;
      }
      DisassembleResult result =
          Disassemble(pOutput, DEFAULT_TARGET_TRIPLE_STRING, func_name,
                      reinterpret_cast<const uint8_t *>(func), func_size);

      if (result != kDisassembleSuccess) {
        ALOGW("Failed to disassemble the function %s in %s (error code=%zu)!",
              func_name, mObjFile->getName().c_str(), static_cast<size_t>(result));

        if (result != kDisassembleInvalidInstruction) {
          ALOGW("And the error occured in disassembler is fatal. Abort "
                "disassembler on remaining functions!");
          break;
        }
      }
    }
  }
#endif
  return;
}

RSExecutable::~RSExecutable() {
  syncInfo();
  delete mInfo;
  delete mObjFile;
  delete mLoader;
}
