//===- subzero/src/IceTranslator.cpp - ICE to machine code ------*- C++ -*-===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the general driver class for translating ICE to
// machine code.
//
//===----------------------------------------------------------------------===//

#include "IceCfg.h"
#include "IceClFlags.h"
#include "IceDefs.h"
#include "IceTargetLowering.h"
#include "IceTranslator.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"

#include <iostream>

using namespace Ice;

Translator::~Translator() {}

namespace {
void setValueName(llvm::Value *V, const char *Kind, const IceString &Prefix,
                  uint32_t &NameIndex, Ostream &errs) {
  if (V->hasName()) {
    const std::string &Name(V->getName());
    if (Name.find(Prefix) == 0) {
      errs << "Warning: Default " << Kind << " prefix '" << Prefix
           << "' conflicts with name '" << Name << "'.\n";
    }
    return;
  }
  if (NameIndex == 0) {
    V->setName(Prefix);
    ++NameIndex;
    return;
  }
  std::string Buffer;
  llvm::raw_string_ostream StrBuf(Buffer);
  StrBuf << Prefix << NameIndex;
  V->setName(StrBuf.str());
  ++NameIndex;
}
} // end of anonymous namespace

void Translator::nameUnnamedGlobalAddresses(llvm::Module *Mod) {
  const IceString &GlobalPrefix = Flags.DefaultGlobalPrefix;
  Ostream &errs = Ctx->getStrDump();
  if (!GlobalPrefix.empty()) {
    uint32_t NameIndex = 0;
    for (llvm::Module::global_iterator I = Mod->global_begin(),
                                       E = Mod->global_end();
         I != E; ++I) {
      setValueName(I, "global", GlobalPrefix, NameIndex, errs);
    }
  }
  const IceString &FunctionPrefix = Flags.DefaultFunctionPrefix;
  if (FunctionPrefix.empty())
    return;
  uint32_t NameIndex = 0;
  for (llvm::Module::iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
    setValueName(I, "function", FunctionPrefix, NameIndex, errs);
  }
}

void Translator::translateFcn(Cfg *Fcn) {
  Ctx->resetStats();
  Func.reset(Fcn);
  if (Ctx->getFlags().DisableInternal)
    Func->setInternal(false);
  if (Ctx->getFlags().DisableTranslation) {
    Func->dump();
  } else {
    Func->translate();
    if (Func->hasError()) {
      std::cerr << "ICE translation error: " << Func->getError() << "\n";
      ErrorStatus = true;
    }

    Func->emit();
    Ctx->dumpStats(Func->getFunctionName());
  }
}

void Translator::emitConstants() {
  if (!Ctx->getFlags().DisableTranslation && Func)
    Func->getTarget()->emitConstants();
}

void Translator::convertGlobals(llvm::Module *Mod) {
  llvm::OwningPtr<TargetGlobalInitLowering> GlobalLowering(
      TargetGlobalInitLowering::createLowering(Ctx->getTargetArch(), Ctx));
  for (llvm::Module::const_global_iterator I = Mod->global_begin(),
                                           E = Mod->global_end();
       I != E; ++I) {
    if (!I->hasInitializer())
      continue;
    const llvm::Constant *Initializer = I->getInitializer();
    IceString Name = I->getName();
    unsigned Align = I->getAlignment();
    uint64_t NumElements = 0;
    const char *Data = NULL;
    bool IsInternal = I->hasInternalLinkage();
    bool IsConst = I->isConstant();
    bool IsZeroInitializer = false;

    if (const llvm::ConstantDataArray *CDA =
            llvm::dyn_cast<llvm::ConstantDataArray>(Initializer)) {
      NumElements = CDA->getNumElements();
      assert(llvm::isa<llvm::IntegerType>(CDA->getElementType()) &&
             (llvm::cast<llvm::IntegerType>(CDA->getElementType())
                  ->getBitWidth() == 8));
      Data = CDA->getRawDataValues().data();
    } else if (llvm::isa<llvm::ConstantAggregateZero>(Initializer)) {
      if (const llvm::ArrayType *AT =
              llvm::dyn_cast<llvm::ArrayType>(Initializer->getType())) {
        assert(llvm::isa<llvm::IntegerType>(AT->getElementType()) &&
               (llvm::cast<llvm::IntegerType>(AT->getElementType())
                    ->getBitWidth() == 8));
        NumElements = AT->getNumElements();
        IsZeroInitializer = true;
      } else {
        llvm_unreachable("Unhandled constant aggregate zero type");
      }
    } else {
      llvm_unreachable("Unhandled global initializer");
    }

    GlobalLowering->lower(Name, Align, IsInternal, IsConst, IsZeroInitializer,
                          NumElements, Data,
                          Ctx->getFlags().DisableTranslation);
  }
  GlobalLowering.reset();
}
