//===--- GenConstant.cpp - Swift IR Generation For Constants --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for constant values.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Constants.h"

#include "GenConstant.h"
#include "GenStruct.h"
#include "GenTuple.h"
#include "TypeInfo.h"
#include "StructLayout.h"
#include "swift/Basic/Range.h"
#include "swift/SIL/SILModule.h"

using namespace swift;
using namespace irgen;

llvm::Constant *irgen::emitConstantInt(IRGenModule &IGM,
                                       IntegerLiteralInst *ILI) {
  APInt value = ILI->getValue();
  BuiltinIntegerWidth width
    = ILI->getType().castTo<BuiltinIntegerType>()->getWidth();

  // The value may need truncation if its type had an abstract size.
  if (!width.isFixedWidth()) {
    assert(width.isPointerWidth() && "impossible width value");

    unsigned pointerWidth = IGM.getPointerSize().getValueInBits();
    assert(pointerWidth <= value.getBitWidth()
           && "lost precision at AST/SIL level?!");
    if (pointerWidth < value.getBitWidth())
      value = value.trunc(pointerWidth);
  }

  return llvm::ConstantInt::get(IGM.LLVMContext, value);
}

llvm::Constant *irgen::emitConstantFP(IRGenModule &IGM, FloatLiteralInst *FLI) {
  return llvm::ConstantFP::get(IGM.LLVMContext, FLI->getValue());
}

llvm::Constant *irgen::emitAddrOfConstantString(IRGenModule &IGM,
                                                StringLiteralInst *SLI) {
  switch (SLI->getEncoding()) {
  case StringLiteralInst::Encoding::UTF8:
    return IGM.getAddrOfGlobalString(SLI->getValue());

  case StringLiteralInst::Encoding::UTF16: {
    // This is always a GEP of a GlobalVariable with a nul terminator.
    auto addr = IGM.getAddrOfGlobalUTF16String(SLI->getValue());

    // Cast to Builtin.RawPointer.
    return llvm::ConstantExpr::getBitCast(addr, IGM.Int8PtrTy);
  }

  case StringLiteralInst::Encoding::ObjCSelector:
    llvm_unreachable("cannot get the address of an Objective-C selector");
  }
  llvm_unreachable("bad string encoding");
}

static llvm::Constant *emitConstantValue(IRGenModule &IGM, SILValue operand) {
  if (auto *SI = dyn_cast<StructInst>(operand)) {
    return emitConstantStruct(IGM, SI);
  } else if (auto *TI = dyn_cast<TupleInst>(operand)) {
    return emitConstantTuple(IGM, TI);
  } else if (auto *ILI = dyn_cast<IntegerLiteralInst>(operand)) {
    return emitConstantInt(IGM, ILI);
  } else if (auto *FLI = dyn_cast<FloatLiteralInst>(operand)) {
    return emitConstantFP(IGM, FLI);
  } else if (auto *SLI = dyn_cast<StringLiteralInst>(operand)) {
    return emitAddrOfConstantString(IGM, SLI);
  } else if (auto *BI = dyn_cast<BuiltinInst>(operand)) {
    assert(IGM.getSILModule().getBuiltinInfo(BI->getName()).ID ==
           BuiltinValueKind::PtrToInt);
    llvm::Constant *ptr = emitConstantValue(IGM, BI->getArguments()[0]);
    return llvm::ConstantExpr::getPtrToInt(ptr, IGM.IntPtrTy);
  } else {
    llvm_unreachable("Unsupported SILInstruction in static initializer!");
  }
}

namespace {

/// Fill in the missing values for padding.
void insertPadding(SmallVectorImpl<llvm::Constant *> &Elements,
                   llvm::StructType *sTy) {
  // fill in any gaps, which are the explicit padding that swiftc inserts.
  for (unsigned i = 0, e = Elements.size(); i != e; i++) {
    auto &elt = Elements[i];
    if (elt == nullptr) {
      auto *eltTy = sTy->getElementType(i);
      assert(eltTy->isArrayTy() &&
             eltTy->getArrayElementType()->isIntegerTy(8) &&
             "Unexpected non-byte-array type for constant struct padding");
      elt = llvm::UndefValue::get(eltTy);
    }
  }
}

template <typename InstTy, typename NextIndexFunc>
llvm::Constant *emitConstantStructOrTuple(IRGenModule &IGM, InstTy inst,
                                          NextIndexFunc nextIndex) {
  auto type = inst->getType();
  auto *sTy = cast<llvm::StructType>(IGM.getTypeInfo(type).getStorageType());

  SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr);

  // run over the Swift initializers, putting them into the struct as
  // appropriate.
  for (unsigned i = 0, e = inst->getElements().size(); i != e; i++) {
    auto operand = inst->getOperand(i);
    Optional<unsigned> index = nextIndex(IGM, type, i);
    if (index.hasValue()) {
      assert(elts[index.getValue()] == nullptr &&
             "Unexpected constant struct field overlap");

      elts[index.getValue()] = emitConstantValue(IGM, operand);
    }
  }
  insertPadding(elts, sTy);
  return llvm::ConstantStruct::get(sTy, elts);
}
} // end anonymous namespace

llvm::Constant *irgen::emitConstantStruct(IRGenModule &IGM, StructInst *SI) {
  // The only way to get a struct's stored properties (which we need to map to
  // their physical/LLVM index) is to iterate over the properties
  // progressively. Fortunately the iteration order matches the order of
  // operands in a StructInst.
  auto StoredProperties = SI->getStructDecl()->getStoredProperties();
  auto Iter = StoredProperties.begin();

  return emitConstantStructOrTuple(
      IGM, SI, [&Iter](IRGenModule &IGM, SILType Type, unsigned _i) mutable {
        (void)_i;
        auto *FD = *Iter++;
        return irgen::getPhysicalStructFieldIndex(IGM, Type, FD);
      });
}

llvm::Constant *irgen::emitConstantTuple(IRGenModule &IGM, TupleInst *TI) {
  return emitConstantStructOrTuple(IGM, TI,
                                   irgen::getPhysicalTupleElementStructIndex);
}

llvm::Constant *irgen::emitConstantObject(IRGenModule &IGM, ObjectInst *OI,
                                         StructLayout *ClassLayout) {
  auto *sTy = cast<llvm::StructType>(ClassLayout->getType());
  SmallVector<llvm::Constant *, 32> elts(sTy->getNumElements(), nullptr);

  unsigned NumElems = OI->getAllElements().size();
  assert(NumElems == ClassLayout->getElements().size());

  // Construct the object init value including tail allocated elements.
  for (unsigned i = 0; i != NumElems; i++) {
    SILValue Val = OI->getAllElements()[i];
    const ElementLayout &EL = ClassLayout->getElements()[i];
    if (!EL.isEmpty()) {
      unsigned EltIdx = EL.getStructIndex();
      assert(EltIdx != 0 && "the first element is the object header");
      elts[EltIdx] = emitConstantValue(IGM, Val);
    }
  }
  // Construct the object header.
  llvm::Type *ObjectHeaderTy = sTy->getElementType(0);
  assert(ObjectHeaderTy->isStructTy());
  elts[0] = llvm::Constant::getNullValue(ObjectHeaderTy);
  insertPadding(elts, sTy);
  return llvm::ConstantStruct::get(sTy, elts);
}
