//===--- GenIntegerLiteral.cpp - IRGen for Builtin.IntegerLiteral ---------===//
//
// 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 Builtin.IntegerLiteral.
//
//===----------------------------------------------------------------------===//

#include "GenIntegerLiteral.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "swift/ABI/MetadataValues.h"
#include "Explosion.h"
#include "ExtraInhabitants.h"
#include "GenType.h"
#include "IRGenFunction.h"
#include "IRGenModule.h"
#include "LoadableTypeInfo.h"
#include "ScalarPairTypeInfo.h"

using namespace swift;
using namespace irgen;

namespace {

/// A TypeInfo implementation for Builtin.IntegerLiteral.
class IntegerLiteralTypeInfo :
  public ScalarPairTypeInfo<IntegerLiteralTypeInfo, LoadableTypeInfo> {

public:
  IntegerLiteralTypeInfo(llvm::StructType *storageType,
                         Size size, Alignment align, SpareBitVector &&spareBits)
      : ScalarPairTypeInfo(storageType, size, std::move(spareBits), align,
                           IsPOD, IsFixedSize) {}

  static Size getFirstElementSize(IRGenModule &IGM) {
    return IGM.getPointerSize();
  }
  static StringRef getFirstElementLabel() {
    return ".data";
  }
  static bool isFirstElementTrivial() {
    return true;
  }
  void emitRetainFirstElement(IRGenFunction &IGF, llvm::Value *fn,
                              Optional<Atomicity> atomicity = None) const {}
  void emitReleaseFirstElement(IRGenFunction &IGF, llvm::Value *fn,
                               Optional<Atomicity> atomicity = None) const {}
  void emitAssignFirstElement(IRGenFunction &IGF, llvm::Value *fn,
                              Address fnAddr) const {
    IGF.Builder.CreateStore(fn, fnAddr);
  }

  static Size getSecondElementOffset(IRGenModule &IGM) {
    return IGM.getPointerSize();
  }
  static Size getSecondElementSize(IRGenModule &IGM) {
    return IGM.getPointerSize();
  }
  static StringRef getSecondElementLabel() {
    return ".flags";
  }
  bool isSecondElementTrivial() const {
    return true;
  }
  void emitRetainSecondElement(IRGenFunction &IGF, llvm::Value *data,
                               Optional<Atomicity> atomicity = None) const {}
  void emitReleaseSecondElement(IRGenFunction &IGF, llvm::Value *data,
                                Optional<Atomicity> atomicity = None) const {}
  void emitAssignSecondElement(IRGenFunction &IGF, llvm::Value *context,
                               Address dataAddr) const {
    IGF.Builder.CreateStore(context, dataAddr);
  }

  // The data pointer isn't a heap object, but it is an aligned pointer.
  bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
    return true;
  }
  unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
    return getHeapObjectExtraInhabitantCount(IGM);
  }
  APInt getFixedExtraInhabitantValue(IRGenModule &IGM,
                                     unsigned bits,
                                     unsigned index) const override {
    return getHeapObjectFixedExtraInhabitantValue(IGM, bits, index, 0);
  }
  llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF, Address src,
                                       SILType T,
                                       bool isOutlined) const override {
    src = projectFirstElement(IGF, src);
    return getHeapObjectExtraInhabitantIndex(IGF, src);
  }
  APInt getFixedExtraInhabitantMask(IRGenModule &IGM) const override {
    auto pointerSize = IGM.getPointerSize().getValueInBits();
    APInt bits = APInt::getAllOnesValue(pointerSize);
    bits = bits.zext(pointerSize * 2);
    return bits;
  }
  void storeExtraInhabitant(IRGenFunction &IGF, llvm::Value *index,
                            Address dest, SILType T,
                            bool isOutlined) const override {
    dest = projectFirstElement(IGF, dest);
    storeHeapObjectExtraInhabitant(IGF, index, dest);
  }
};

}

llvm::StructType *IRGenModule::getIntegerLiteralTy() {
  if (!IntegerLiteralTy) {
    IntegerLiteralTy =
      llvm::StructType::create(LLVMContext, {
                                 SizeTy->getPointerTo(),
                                 SizeTy
                               }, "swift.int_literal");
  }
  return IntegerLiteralTy;
}

const LoadableTypeInfo &
TypeConverter::getIntegerLiteralTypeInfo() {
  if (!IntegerLiteralTI) {
    auto ty = IGM.getIntegerLiteralTy();

    SpareBitVector spareBits;
    spareBits.append(IGM.getHeapObjectSpareBits());
    spareBits.appendClearBits(IGM.getPointerSize().getValueInBits());

    IntegerLiteralTI =
      new IntegerLiteralTypeInfo(ty, IGM.getPointerSize() * 2,
                                 IGM.getPointerAlignment(),
                                 std::move(spareBits));
  }
  return *IntegerLiteralTI;
}

ConstantIntegerLiteral
irgen::emitConstantIntegerLiteral(IRGenModule &IGM, IntegerLiteralInst *ILI) {
  return IGM.getConstantIntegerLiteral(ILI->getValue());
}

ConstantIntegerLiteral
IRGenModule::getConstantIntegerLiteral(APInt value) {
  if (!ConstantIntegerLiterals)
    ConstantIntegerLiterals.reset(new ConstantIntegerLiteralMap());

  return ConstantIntegerLiterals->get(*this, std::move(value));
}

ConstantIntegerLiteral
ConstantIntegerLiteralMap::get(IRGenModule &IGM, APInt &&value) {
  auto &entry = map[value];
  if (entry.Data) return entry;

  assert(value.getMinSignedBits() == value.getBitWidth() &&
         "expected IntegerLiteral value to be maximally compact");

  // We're going to break the value down into pointer-sized chunks.
  uint64_t chunkSizeInBits = IGM.getPointerSize().getValueInBits();

  // Count how many bits are needed to store the value, including the sign bit.
  uint64_t minWidthInBits = value.getBitWidth();

  // Round up to the nearest multiple of the chunk size.
  uint64_t storageWidthInBits = (minWidthInBits + chunkSizeInBits - 1)
                                & ~(chunkSizeInBits - 1);

  // Extend the value to that width.  We guarantee that extra bits in the
  // chunks will be appropriately sign-extended.
  value = value.sextOrTrunc(storageWidthInBits);

  // Extract the individual chunks from the extended value.
  uint64_t numChunks = storageWidthInBits / chunkSizeInBits;
  SmallVector<llvm::Constant *, 4> chunks;
  chunks.reserve(numChunks);
  for (uint64_t i = 0; i != numChunks; ++i) {
    auto chunk = value.extractBits(chunkSizeInBits, i * chunkSizeInBits);
    chunks.push_back(llvm::ConstantInt::get(IGM.SizeTy, std::move(chunk)));
  }

  // Build a global to hold the chunks.
  // TODO: make this shared within the image
  auto arrayTy = llvm::ArrayType::get(IGM.SizeTy, numChunks);
  auto initV = llvm::ConstantArray::get(arrayTy, chunks);
  auto globalArray =
    new llvm::GlobalVariable(*IGM.getModule(), arrayTy, /*constant*/ true,
                             llvm::GlobalVariable::PrivateLinkage, initV,
                             IGM.EnableValueNames
                               ? Twine("intliteral.") + value.toString(10, true)
                               : "");
  globalArray->setUnnamedAddr(llvm::GlobalVariable::UnnamedAddr::Global);

  // Various clients expect this to be a i64*, not an [N x i64]*, so cast down.
  auto zero = llvm::ConstantInt::get(IGM.Int32Ty, 0);
  llvm::Constant *indices[] = { zero, zero };
  auto data = llvm::ConstantExpr::getInBoundsGetElementPtr(arrayTy, globalArray,
                                                           indices);

  // Build the flags word.
  auto flags = IntegerLiteralFlags(minWidthInBits, value.isNegative());
  auto flagsV = llvm::ConstantInt::get(IGM.SizeTy, flags.getOpaqueValue());

  // Cache the global.
  entry.Data = data;
  entry.Flags = flagsV;
  return entry;
}

void irgen::emitIntegerLiteralCheckedTrunc(IRGenFunction &IGF,
                                           Explosion &in,
                                           llvm::IntegerType *resultTy,
                                           bool resultIsSigned,
                                           Explosion &out) {
  Address data(in.claimNext(), IGF.IGM.getPointerAlignment());
  auto flags = in.claimNext();

  size_t chunkWidth = IGF.IGM.getPointerSize().getValueInBits();
  size_t resultWidth = resultTy->getBitWidth();

  // The number of bits required to express the value, including the sign bit.
  auto valueWidth = IGF.Builder.CreateLShr(flags,
                    IGF.IGM.getSize(Size(IntegerLiteralFlags::BitWidthShift)));

  // The maximum number of chunks that we need to read in order to fill the
  // result type: ceil(resultWidth / chunkWidth).
  // Note that we won't actually end up reading the final chunk if we're
  // building an unsigned value that requires e.g. 65 bits to express:
  // there's only one meaningful bit there, and we know it's zero from the
  // isNegative check.
  size_t maxNumChunks = (resultWidth + chunkWidth - 1) / chunkWidth;

  // One branch from invalidBB, one branch at each intermediate point in the
  // do-we-have-more-chunks chain, and one branch at the end.
  auto numPHIEntries = maxNumChunks + /*overflow*/ 1;

  auto boolTy = IGF.IGM.Int1Ty;
  auto doneBB = IGF.createBasicBlock("intliteral.trunc.done");
  auto resultPHI = llvm::PHINode::Create(resultTy, numPHIEntries, "", doneBB);
  auto overflowPHI = llvm::PHINode::Create(boolTy, numPHIEntries, "", doneBB);
  out.add(resultPHI);
  out.add(overflowPHI);

  auto validBB = IGF.createBasicBlock("intliteral.trunc.valid");
  auto invalidBB = IGF.createBasicBlock("intliteral.trunc.invalid");

  // Check whether the value fits in the result type.
  // If the result is signed, then we need valueWidth <= resultWidth.
  // Otherwise we need valueWidth <= resultWidth + 1 && !isNegative.
  {
    llvm::Value *hasOverflow;
    if (resultIsSigned) {
      hasOverflow = IGF.Builder.CreateICmpUGT(valueWidth,
                                        IGF.IGM.getSize(Size(resultWidth)));
    } else {
      static_assert(IntegerLiteralFlags::IsNegativeFlag == 1,
                    "hardcoded in this truncation");
      auto isNegative = IGF.Builder.CreateTrunc(flags, boolTy);
      auto tooBig = IGF.Builder.CreateICmpUGT(valueWidth,
                                        IGF.IGM.getSize(Size(resultWidth + 1)));
      hasOverflow = IGF.Builder.CreateOr(isNegative, tooBig);
    }
    IGF.Builder.CreateCondBr(hasOverflow, invalidBB, validBB);
  }

  // In the invalid block, we just need to construct the result.  This block
  // only exists to split the otherwise-critical edge.
  IGF.Builder.emitBlock(invalidBB);
  {
    resultPHI->addIncoming(llvm::ConstantInt::get(resultTy, 0), invalidBB);
    overflowPHI->addIncoming(llvm::ConstantInt::get(boolTy, 1), invalidBB);
    IGF.Builder.CreateBr(doneBB);
  }

  // Okay, the value fits in the result type, so overflow is off the table
  // and we just need to assemble a value of resultTy.  But we might not have
  // the full complement of chunks.
  IGF.Builder.emitBlock(validBB);
  {
    auto firstChunk = IGF.Builder.CreateLoad(data);

    // The easy case is if resultWidth <= chunkWidth, in which case knowing
    // that we haven't overflowed is sufficient to say that we can just
    // use the first chunk.
    if (resultWidth <= chunkWidth) {
      auto result = IGF.Builder.CreateTrunc(firstChunk, resultTy);
      resultPHI->addIncoming(result, validBB);
      overflowPHI->addIncoming(llvm::ConstantInt::get(boolTy, 0), validBB);
      IGF.Builder.CreateBr(doneBB);

    // Otherwise, we're going to have to test dynamically how many chunks
    // we need to read.
    } else {
      assert(maxNumChunks >= 2);
      llvm::Value *cur = firstChunk;
      for (size_t i = 1; i != maxNumChunks; ++i) {
        auto extendBB = IGF.createBasicBlock("intliteral.trunc.finish");
        auto nextBB = IGF.createBasicBlock("intliteral.trunc.next");

        // If the result is signed, then we're done if:
        //   valueWidth <= bitsInChunksReadSoFar
        // If the result is unsigned, then we're done if:
        //   valueWidth <= bitsInChunksReadSoFar + 1
        // (because we know the next bit will be zero)
        auto limit = i * chunkWidth + size_t(!resultIsSigned);
        auto isComplete =
          IGF.Builder.CreateICmpULE(valueWidth, IGF.IGM.getSize(Size(limit)));
        IGF.Builder.CreateCondBr(isComplete, extendBB, nextBB);

        // If we're done, extend the current value to the result type and
        // then branch out.
        IGF.Builder.emitBlock(extendBB);
        {
          auto extendedResult =
            resultIsSigned ? IGF.Builder.CreateSExt(cur, resultTy)
                           : IGF.Builder.CreateZExt(cur, resultTy);
          resultPHI->addIncoming(extendedResult, extendBB);
          overflowPHI->addIncoming(llvm::ConstantInt::get(boolTy, 0), extendBB);
          IGF.Builder.CreateBr(doneBB);
        }

        // Otherwise, load the next chunk.
        IGF.Builder.emitBlock(nextBB);
        auto nextChunkAddr =
          IGF.Builder.CreateConstArrayGEP(data, i, IGF.IGM.getPointerSize());
        auto nextChunk = IGF.Builder.CreateLoad(nextChunkAddr);

        // Zero-extend the current value and the chunk and then shift the
        // chunk into place.  If this is the last iteration, we should use
        // the final result type; the shift might then drop bits, but they
        // should just be sign-extension bits.
        auto nextTy = (i + 1 == maxNumChunks
                         ? resultTy
                         : llvm::IntegerType::get(IGF.IGM.getLLVMContext(),
                                                  (i + 1) * chunkWidth));
        cur = IGF.Builder.CreateZExt(cur, nextTy);
        auto shiftedNextChunk =
          IGF.Builder.CreateShl(IGF.Builder.CreateZExt(nextChunk, nextTy),
                                i * chunkWidth);
        cur = IGF.Builder.CreateAdd(cur, shiftedNextChunk);
      }

      // Given the overflow check before, we know we don't need to look at
      // any more chunks.
      assert(cur->getType() == resultTy);
      auto curBB = IGF.Builder.GetInsertBlock();
      resultPHI->addIncoming(cur, curBB);
      overflowPHI->addIncoming(llvm::ConstantInt::get(boolTy, 0), curBB);
      IGF.Builder.CreateBr(doneBB);
    }
  }

  // Emit the continuation block.  We've already set up the PHIs here and
  // add them to `out`, so there's nothing else to do.
  IGF.Builder.emitBlock(doneBB);
}

static llvm::Value *emitIntegerLiteralToFloatCall(IRGenFunction &IGF,
                                                  llvm::Value *data,
                                                  llvm::Value *flags,
                                                  unsigned bitWidth) {
  assert(bitWidth == 32 || bitWidth == 64);
  auto fn = bitWidth == 32 ? IGF.IGM.getIntToFloat32Fn()
                           : IGF.IGM.getIntToFloat64Fn();
  auto call = IGF.Builder.CreateCall(fn, {data, flags});
  call->setCallingConv(IGF.IGM.SwiftCC);
  call->setDoesNotThrow();
  call->setOnlyReadsMemory();
  call->setOnlyAccessesArgMemory();

  return call;
}

llvm::Value *irgen::emitIntegerLiteralToFP(IRGenFunction &IGF,
                                           Explosion &in,
                                           llvm::Type *toType) {
  auto data = in.claimNext();
  auto flags = in.claimNext();

  assert(toType->isFloatingPointTy());
  switch (toType->getTypeID()) {
  case llvm::Type::HalfTyID: {
    auto flt = emitIntegerLiteralToFloatCall(IGF, data, flags, 32);
    return IGF.Builder.CreateFPTrunc(flt, toType);
  }

  case llvm::Type::FloatTyID:
    return emitIntegerLiteralToFloatCall(IGF, data, flags, 32);

  case llvm::Type::DoubleTyID:
    return emitIntegerLiteralToFloatCall(IGF, data, flags, 64);

  // TODO: add runtime functions for some of these?
  case llvm::Type::X86_FP80TyID:
  case llvm::Type::FP128TyID:
  case llvm::Type::PPC_FP128TyID: {
    auto dbl = emitIntegerLiteralToFloatCall(IGF, data, flags, 64);
    return IGF.Builder.CreateFPExt(dbl, toType);
  }

  default:
    llvm_unreachable("not a floating-point type");
  }
}
