/*
 * Copyright 2010-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.
 */

#ifndef BCC_COMPILER_H
#define BCC_COMPILER_H

#include <bcc/bcc.h>

#include <Config.h>

#include "librsloader.h"

#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Target/TargetMachine.h"

#include <stddef.h>

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


namespace llvm {
  class Module;
  class NamedMDNode;
  class TargetData;
}


namespace bcc {
  class ScriptCompiled;
  struct CompilerOption;

  class Compiler {
  private:
    //////////////////////////////////////////////////////////////////////////
    // The variable section below (e.g., Triple, CodeGenOptLevel)
    // is initialized in GlobalInitialization()
    //
    static bool GlobalInitialized;

    // If given, this will be the name of the target triple to compile for.
    // If not given, the initial values defined in this file will be used.
    static std::string Triple;
    static llvm::Triple::ArchType ArchType;

    static llvm::CodeGenOpt::Level CodeGenOptLevel;

    // End of section of GlobalInitializing variables
    /////////////////////////////////////////////////////////////////////////
    // If given, the name of the target CPU to generate code for.
    static std::string CPU;

    // The list of target specific features to enable or disable -- this should
    // be a list of strings starting with '+' (enable) or '-' (disable).
    static std::vector<std::string> Features;

    static void LLVMErrorHandler(void *UserData, const std::string &Message);

    friend class CodeEmitter;
    friend class CodeMemoryManager;

  private:
    ScriptCompiled *mpResult;

    std::string mError;

    // Compilation buffer for MC
    llvm::SmallVector<char, 1024> mEmittedELFExecutable;

    // Loaded and relocated executable
    RSExecRef mRSExecutable;

    BCCSymbolLookupFn mpSymbolLookupFn;
    void *mpSymbolLookupContext;

    llvm::Module *mModule;

  public:
    Compiler(ScriptCompiled *result);

    static void GlobalInitialization();

    static std::string const &getTargetTriple() {
      return Triple;
    }

    static llvm::Triple::ArchType getTargetArchType() {
      return ArchType;
    }

    void registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
      mpSymbolLookupFn = pFn;
      mpSymbolLookupContext = pContext;
    }

    void *getSymbolAddress(char const *name);

    const llvm::SmallVector<char, 1024> &getELF() const {
      return mEmittedELFExecutable;
    }

    int readModule(llvm::Module &pModule);

    int compile(const CompilerOption &option);

    char const *getErrorMessage() {
      return mError.c_str();
    }

    const llvm::Module *getModule() const {
      return mModule;
    }

    ~Compiler();

  private:

    int runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
                   llvm::NamedMDNode const *ExportVarMetadata,
                   llvm::NamedMDNode const *ExportFuncMetadata);

    int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);

    int runInternalPasses(std::vector<std::string>& Names,
                          std::vector<uint32_t>& Signatures);

    int runLTO(llvm::TargetData *TD,
               std::vector<const char*>& ExportSymbols,
               llvm::CodeGenOpt::Level OptimizationLevel);

    bool hasError() const {
      return !mError.empty();
    }

    void setError(const char *Error) {
      mError.assign(Error);  // Copying
    }

    void setError(const std::string &Error) {
      mError = Error;
    }

  };  // End of class Compiler

} // namespace bcc

#endif // BCC_COMPILER_H
