//===- AMDGPUEmitPrintf.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Utility function to lower a printf call into a series of device
// library calls on the AMDGPU target.
//
// WARNING: This file knows about certain library functions. It recognizes them
// by name, and hardwires knowledge of their semantics.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Utils/AMDGPUEmitPrintf.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"

using namespace llvm;

#define DEBUG_TYPE "amdgpu-emit-printf"

static Value *fitArgInto64Bits(IRBuilder<> &Builder, Value *Arg) {
  auto Int64Ty = Builder.getInt64Ty();
  auto Ty = Arg->getType();

  if (auto IntTy = dyn_cast<IntegerType>(Ty)) {
    switch (IntTy->getBitWidth()) {
    case 32:
      return Builder.CreateZExt(Arg, Int64Ty);
    case 64:
      return Arg;
    }
  }

  if (Ty->getTypeID() == Type::DoubleTyID) {
    return Builder.CreateBitCast(Arg, Int64Ty);
  }

  if (isa<PointerType>(Ty)) {
    return Builder.CreatePtrToInt(Arg, Int64Ty);
  }

  llvm_unreachable("unexpected type");
}

static Value *callPrintfBegin(IRBuilder<> &Builder, Value *Version) {
  auto Int64Ty = Builder.getInt64Ty();
  auto M = Builder.GetInsertBlock()->getModule();
  auto Fn = M->getOrInsertFunction("__ockl_printf_begin", Int64Ty, Int64Ty);
  return Builder.CreateCall(Fn, Version);
}

static Value *callAppendArgs(IRBuilder<> &Builder, Value *Desc, int NumArgs,
                             Value *Arg0, Value *Arg1, Value *Arg2, Value *Arg3,
                             Value *Arg4, Value *Arg5, Value *Arg6,
                             bool IsLast) {
  auto Int64Ty = Builder.getInt64Ty();
  auto Int32Ty = Builder.getInt32Ty();
  auto M = Builder.GetInsertBlock()->getModule();
  auto Fn = M->getOrInsertFunction("__ockl_printf_append_args", Int64Ty,
                                   Int64Ty, Int32Ty, Int64Ty, Int64Ty, Int64Ty,
                                   Int64Ty, Int64Ty, Int64Ty, Int64Ty, Int32Ty);
  auto IsLastValue = Builder.getInt32(IsLast);
  auto NumArgsValue = Builder.getInt32(NumArgs);
  return Builder.CreateCall(Fn, {Desc, NumArgsValue, Arg0, Arg1, Arg2, Arg3,
                                 Arg4, Arg5, Arg6, IsLastValue});
}

static Value *appendArg(IRBuilder<> &Builder, Value *Desc, Value *Arg,
                        bool IsLast) {
  auto Arg0 = fitArgInto64Bits(Builder, Arg);
  auto Zero = Builder.getInt64(0);
  return callAppendArgs(Builder, Desc, 1, Arg0, Zero, Zero, Zero, Zero, Zero,
                        Zero, IsLast);
}

// The device library does not provide strlen, so we build our own loop
// here. While we are at it, we also include the terminating null in the length.
static Value *getStrlenWithNull(IRBuilder<> &Builder, Value *Str) {
  auto *Prev = Builder.GetInsertBlock();
  Module *M = Prev->getModule();

  auto CharZero = Builder.getInt8(0);
  auto One = Builder.getInt64(1);
  auto Zero = Builder.getInt64(0);
  auto Int64Ty = Builder.getInt64Ty();

  // The length is either zero for a null pointer, or the computed value for an
  // actual string. We need a join block for a phi that represents the final
  // value.
  //
  //  Strictly speaking, the zero does not matter since
  // __ockl_printf_append_string_n ignores the length if the pointer is null.
  BasicBlock *Join = nullptr;
  if (Prev->hasTerminator()) {
    Join = Prev->splitBasicBlock(Builder.GetInsertPoint(),
                                 "strlen.join");
    Prev->getTerminator()->eraseFromParent();
  } else {
    Join = BasicBlock::Create(M->getContext(), "strlen.join",
                              Prev->getParent());
  }
  BasicBlock *While =
      BasicBlock::Create(M->getContext(), "strlen.while",
                         Prev->getParent(), Join);
  BasicBlock *WhileDone = BasicBlock::Create(
      M->getContext(), "strlen.while.done",
      Prev->getParent(), Join);

  // Emit an early return for when the pointer is null.
  Builder.SetInsertPoint(Prev);
  auto CmpNull =
      Builder.CreateICmpEQ(Str, Constant::getNullValue(Str->getType()));
  Builder.CreateCondBr(CmpNull, Join, While);

  // Entry to the while loop.
  Builder.SetInsertPoint(While);

  auto PtrPhi = Builder.CreatePHI(Str->getType(), 2);
  PtrPhi->addIncoming(Str, Prev);
  auto PtrNext = Builder.CreateGEP(Builder.getInt8Ty(), PtrPhi, One);
  PtrPhi->addIncoming(PtrNext, While);

  // Condition for the while loop.
  auto Data = Builder.CreateLoad(Builder.getInt8Ty(), PtrPhi);
  auto Cmp = Builder.CreateICmpEQ(Data, CharZero);
  Builder.CreateCondBr(Cmp, WhileDone, While);

  // Add one to the computed length.
  Builder.SetInsertPoint(WhileDone, WhileDone->begin());
  auto Len = Builder.CreatePtrDiff(PtrPhi, Str);
  Len = Builder.CreateZExt(Len, Int64Ty);
  Len = Builder.CreateAdd(Len, One);

  // Final join.
  UncondBrInst::Create(Join, WhileDone);
  Builder.SetInsertPoint(Join, Join->begin());
  auto LenPhi = Builder.CreatePHI(Len->getType(), 2);
  LenPhi->addIncoming(Len, WhileDone);
  LenPhi->addIncoming(Zero, Prev);

  return LenPhi;
}

static Value *callAppendStringN(IRBuilder<> &Builder, Value *Desc, Value *Str,
                                Value *Length, bool isLast) {
  auto Int64Ty = Builder.getInt64Ty();
  auto IsLastInt32 = Builder.getInt32(isLast);
  auto M = Builder.GetInsertBlock()->getModule();
  auto Fn = M->getOrInsertFunction("__ockl_printf_append_string_n", Int64Ty,
                                   Desc->getType(), Str->getType(),
                                   Length->getType(), IsLastInt32->getType());
  return Builder.CreateCall(Fn, {Desc, Str, Length, IsLastInt32});
}

static Value *appendString(IRBuilder<> &Builder, Value *Desc, Value *Arg,
                           bool IsLast) {
  auto Length = getStrlenWithNull(Builder, Arg);
  return callAppendStringN(Builder, Desc, Arg, Length, IsLast);
}

static Value *processArg(IRBuilder<> &Builder, Value *Desc, Value *Arg,
                         bool SpecIsCString, bool IsLast) {
  if (SpecIsCString && isa<PointerType>(Arg->getType())) {
    return appendString(Builder, Desc, Arg, IsLast);
  }
  // If the format specifies a string but the argument is not, the frontend will
  // have printed a warning. We just rely on undefined behaviour and send the
  // argument anyway.
  return appendArg(Builder, Desc, Arg, IsLast);
}

// Scan the format string to locate all specifiers, and mark the ones that
// specify a string, i.e, the "%s" specifier with optional '*' characters.
static void locateCStrings(SparseBitVector<8> &BV, StringRef Str) {
  static const char ConvSpecifiers[] = "diouxXfFeEgGaAcspn";
  size_t SpecPos = 0;
  // Skip the first argument, the format string.
  unsigned ArgIdx = 1;

  while ((SpecPos = Str.find_first_of('%', SpecPos)) != StringRef::npos) {
    if (Str[SpecPos + 1] == '%') {
      SpecPos += 2;
      continue;
    }
    auto SpecEnd = Str.find_first_of(ConvSpecifiers, SpecPos);
    if (SpecEnd == StringRef::npos)
      return;
    auto Spec = Str.slice(SpecPos, SpecEnd + 1);
    ArgIdx += Spec.count('*');
    if (Str[SpecEnd] == 's') {
      BV.set(ArgIdx);
    }
    SpecPos = SpecEnd + 1;
    ++ArgIdx;
  }
}

// helper struct to package the string related data
struct StringData {
  StringRef Str;
  Value *RealSize = nullptr;
  Value *AlignedSize = nullptr;
  bool IsConst = true;

  StringData(StringRef ST, Value *RS, Value *AS, bool IC)
      : Str(ST), RealSize(RS), AlignedSize(AS), IsConst(IC) {}
};

// Calculates frame size required for current printf expansion and allocates
// space on printf buffer. Printf frame includes following contents
// [ ControlDWord , format string/Hash , Arguments (each aligned to 8 byte) ]
static Value *callBufferedPrintfStart(
    IRBuilder<> &Builder, ArrayRef<Value *> Args, Value *Fmt,
    bool isConstFmtStr, SparseBitVector<8> &SpecIsCString,
    SmallVectorImpl<StringData> &StringContents, Value *&ArgSize) {
  Module *M = Builder.GetInsertBlock()->getModule();
  Value *NonConstStrLen = nullptr;
  Value *LenWithNull = nullptr;
  Value *LenWithNullAligned = nullptr;
  Value *TempAdd = nullptr;

  // First 4 bytes to be reserved for control dword
  size_t BufSize = 4;
  if (isConstFmtStr)
    // First 8 bytes of MD5 hash
    BufSize += 8;
  else {
    LenWithNull = getStrlenWithNull(Builder, Fmt);

    // Align the computed length to next 8 byte boundary
    TempAdd = Builder.CreateAdd(LenWithNull,
                                ConstantInt::get(LenWithNull->getType(), 7U));
    NonConstStrLen = Builder.CreateAnd(
        TempAdd, ConstantInt::get(LenWithNull->getType(), ~7U));

    StringContents.push_back(
        StringData(StringRef(), LenWithNull, NonConstStrLen, false));
  }

  for (size_t i = 1; i < Args.size(); i++) {
    if (SpecIsCString.test(i)) {
      StringRef ArgStr;
      if (getConstantStringInfo(Args[i], ArgStr)) {
        auto alignedLen = alignTo(ArgStr.size() + 1, 8);
        StringContents.push_back(StringData(
            ArgStr,
            /*RealSize*/ nullptr, /*AlignedSize*/ nullptr, /*IsConst*/ true));
        BufSize += alignedLen;
      } else {
        LenWithNull = getStrlenWithNull(Builder, Args[i]);

        // Align the computed length to next 8 byte boundary
        TempAdd = Builder.CreateAdd(
            LenWithNull, ConstantInt::get(LenWithNull->getType(), 7U));
        LenWithNullAligned = Builder.CreateAnd(
            TempAdd, ConstantInt::get(LenWithNull->getType(), ~7U));

        if (NonConstStrLen) {
          auto Val = Builder.CreateAdd(LenWithNullAligned, NonConstStrLen,
                                       "cumulativeAdd");
          NonConstStrLen = Val;
        } else
          NonConstStrLen = LenWithNullAligned;

        StringContents.push_back(
            StringData(StringRef(), LenWithNull, LenWithNullAligned, false));
      }
    } else {
      int AllocSize = M->getDataLayout().getTypeAllocSize(Args[i]->getType());
      // We end up expanding non string arguments to 8 bytes
      // (args smaller than 8 bytes)
      BufSize += std::max(AllocSize, 8);
    }
  }

  // calculate final size value to be passed to printf_alloc
  Value *SizeToReserve = ConstantInt::get(Builder.getInt64Ty(), BufSize, false);
  SmallVector<Value *, 1> Alloc_args;
  if (NonConstStrLen)
    SizeToReserve = Builder.CreateAdd(NonConstStrLen, SizeToReserve);

  ArgSize = Builder.CreateTrunc(SizeToReserve, Builder.getInt32Ty());
  Alloc_args.push_back(ArgSize);

  // call the printf_alloc function
  AttributeList Attr = AttributeList::get(
      Builder.getContext(), AttributeList::FunctionIndex, Attribute::NoUnwind);

  Type *Tys_alloc[1] = {Builder.getInt32Ty()};
  Type *PtrTy =
      Builder.getPtrTy(M->getDataLayout().getDefaultGlobalsAddressSpace());
  FunctionType *FTy_alloc = FunctionType::get(PtrTy, Tys_alloc, false);
  auto PrintfAllocFn =
      M->getOrInsertFunction(StringRef("__printf_alloc"), FTy_alloc, Attr);

  return Builder.CreateCall(PrintfAllocFn, Alloc_args, "printf_alloc_fn");
}

// Prepare constant string argument to push onto the buffer
static void processConstantStringArg(StringData *SD, IRBuilder<> &Builder,
                                     SmallVectorImpl<Value *> &WhatToStore) {
  std::string Str(SD->Str.str() + '\0');

  DataExtractor Extractor(Str, /*IsLittleEndian=*/true);
  DataExtractor::Cursor Offset(0);
  while (Offset && Offset.tell() < Str.size()) {
    const uint64_t ReadSize = 4;
    uint64_t ReadNow = std::min(ReadSize, Str.size() - Offset.tell());
    uint64_t ReadBytes = 0;
    switch (ReadNow) {
    default:
      llvm_unreachable("min(4, X) > 4?");
    case 1:
      ReadBytes = Extractor.getU8(Offset);
      break;
    case 2:
      ReadBytes = Extractor.getU16(Offset);
      break;
    case 3:
      ReadBytes = Extractor.getU24(Offset);
      break;
    case 4:
      ReadBytes = Extractor.getU32(Offset);
      break;
    }
    cantFail(Offset.takeError(), "failed to read bytes from constant array");

    APInt IntVal(8 * ReadSize, ReadBytes);

    // TODO: Should not bother aligning up.
    if (ReadNow < ReadSize)
      IntVal = IntVal.zext(8 * ReadSize);

    Type *IntTy = Type::getIntNTy(Builder.getContext(), IntVal.getBitWidth());
    WhatToStore.push_back(ConstantInt::get(IntTy, IntVal));
  }
  // Additional padding for 8 byte alignment
  int Rem = (Str.size() % 8);
  if (Rem > 0 && Rem <= 4)
    WhatToStore.push_back(ConstantInt::get(Builder.getInt32Ty(), 0));
}

static Value *processNonStringArg(Value *Arg, IRBuilder<> &Builder) {
  const DataLayout &DL = Builder.GetInsertBlock()->getDataLayout();
  auto Ty = Arg->getType();

  if (auto IntTy = dyn_cast<IntegerType>(Ty)) {
    if (IntTy->getBitWidth() < 64) {
      return Builder.CreateZExt(Arg, Builder.getInt64Ty());
    }
  }

  if (Ty->isFloatingPointTy()) {
    if (DL.getTypeAllocSize(Ty) < 8) {
      return Builder.CreateFPExt(Arg, Builder.getDoubleTy());
    }
  }

  return Arg;
}

static void
callBufferedPrintfArgPush(IRBuilder<> &Builder, ArrayRef<Value *> Args,
                          Value *PtrToStore, SparseBitVector<8> &SpecIsCString,
                          SmallVectorImpl<StringData> &StringContents,
                          bool IsConstFmtStr) {
  Module *M = Builder.GetInsertBlock()->getModule();
  const DataLayout &DL = M->getDataLayout();
  auto StrIt = StringContents.begin();
  size_t i = IsConstFmtStr ? 1 : 0;
  for (; i < Args.size(); i++) {
    SmallVector<Value *, 32> WhatToStore;
    if ((i == 0) || SpecIsCString.test(i)) {
      if (StrIt->IsConst) {
        processConstantStringArg(StrIt, Builder, WhatToStore);
        StrIt++;
      } else {
        // This copies the contents of the string, however the next offset
        // is at aligned length, the extra space that might be created due
        // to alignment padding is not populated with any specific value
        // here. This would be safe as long as runtime is sync with
        // the offsets.
        Builder.CreateMemCpy(PtrToStore, /*DstAlign*/ Align(1), Args[i],
                             /*SrcAlign*/ Args[i]->getPointerAlignment(DL),
                             StrIt->RealSize);

        PtrToStore =
            Builder.CreateInBoundsGEP(Builder.getInt8Ty(), PtrToStore,
                                      {StrIt->AlignedSize}, "PrintBuffNextPtr");
        LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:"
                          << *PtrToStore << '\n');

        // done with current argument, move to next
        StrIt++;
        continue;
      }
    } else {
      WhatToStore.push_back(processNonStringArg(Args[i], Builder));
    }

    for (Value *toStore : WhatToStore) {
      StoreInst *StBuff = Builder.CreateStore(toStore, PtrToStore);
      LLVM_DEBUG(dbgs() << "inserting store to printf buffer:" << *StBuff
                        << '\n');
      (void)StBuff;
      PtrToStore = Builder.CreateConstInBoundsGEP1_32(
          Builder.getInt8Ty(), PtrToStore,
          M->getDataLayout().getTypeAllocSize(toStore->getType()),
          "PrintBuffNextPtr");
      LLVM_DEBUG(dbgs() << "inserting gep to the printf buffer:" << *PtrToStore
                        << '\n');
    }
  }
}

Value *llvm::emitAMDGPUPrintfCall(IRBuilder<> &Builder, ArrayRef<Value *> Args,
                                  bool IsBuffered) {
  auto NumOps = Args.size();
  assert(NumOps >= 1);

  auto Fmt = Args[0];
  SparseBitVector<8> SpecIsCString;
  StringRef FmtStr;

  if (getConstantStringInfo(Fmt, FmtStr))
    locateCStrings(SpecIsCString, FmtStr);

  if (IsBuffered) {
    SmallVector<StringData, 8> StringContents;
    Module *M = Builder.GetInsertBlock()->getModule();
    LLVMContext &Ctx = Builder.getContext();
    auto Int8Ty = Builder.getInt8Ty();
    auto Int32Ty = Builder.getInt32Ty();
    bool IsConstFmtStr = !FmtStr.empty();

    Value *ArgSize = nullptr;
    Value *Ptr =
        callBufferedPrintfStart(Builder, Args, Fmt, IsConstFmtStr,
                                SpecIsCString, StringContents, ArgSize);

    // The buffered version still follows OpenCL printf standards for
    // printf return value, i.e 0 on success, -1 on failure.
    ConstantPointerNull *zeroIntPtr =
        ConstantPointerNull::get(cast<PointerType>(Ptr->getType()));

    auto *Cmp = cast<ICmpInst>(Builder.CreateICmpNE(Ptr, zeroIntPtr, ""));

    BasicBlock *End = BasicBlock::Create(Ctx, "end.block",
                                         Builder.GetInsertBlock()->getParent());
    BasicBlock *ArgPush = BasicBlock::Create(
        Ctx, "argpush.block", Builder.GetInsertBlock()->getParent());

    CondBrInst::Create(Cmp, ArgPush, End, Builder.GetInsertBlock());
    Builder.SetInsertPoint(ArgPush);

    // Create controlDWord and store as the first entry, format as follows
    // Bit 0 (LSB) -> stream (1 if stderr, 0 if stdout, printf always outputs to
    // stdout) Bit 1 -> constant format string (1 if constant) Bits 2-31 -> size
    // of printf data frame
    auto ConstantTwo = Builder.getInt32(2);
    auto ControlDWord = Builder.CreateShl(ArgSize, ConstantTwo);
    if (IsConstFmtStr)
      ControlDWord = Builder.CreateOr(ControlDWord, ConstantTwo);

    Builder.CreateStore(ControlDWord, Ptr);

    Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 4);

    // Create MD5 hash for constant format string, push low 64 bits of the
    // same onto buffer and metadata.
    NamedMDNode *metaD = M->getOrInsertNamedMetadata("llvm.printf.fmts");
    if (IsConstFmtStr) {
      MD5 Hasher;
      MD5::MD5Result Hash;
      Hasher.update(FmtStr);
      Hasher.final(Hash);

      // Try sticking to llvm.printf.fmts format, although we are not going to
      // use the ID and argument size fields while printing,
      std::string MetadataStr =
          "0:0:" + llvm::utohexstr(Hash.low(), /*LowerCase=*/true) + "," +
          FmtStr.str();
      MDString *fmtStrArray = MDString::get(Ctx, MetadataStr);
      MDNode *myMD = MDNode::get(Ctx, fmtStrArray);
      metaD->addOperand(myMD);

      Builder.CreateStore(Builder.getInt64(Hash.low()), Ptr);
      Ptr = Builder.CreateConstInBoundsGEP1_32(Int8Ty, Ptr, 8);
    } else {
      // Include a dummy metadata instance in case of only non constant
      // format string usage, This might be an absurd usecase but needs to
      // be done for completeness
      if (metaD->getNumOperands() == 0) {
        MDString *fmtStrArray =
            MDString::get(Ctx, "0:0:ffffffff,\"Non const format string\"");
        MDNode *myMD = MDNode::get(Ctx, fmtStrArray);
        metaD->addOperand(myMD);
      }
    }

    // Push The printf arguments onto buffer
    callBufferedPrintfArgPush(Builder, Args, Ptr, SpecIsCString, StringContents,
                              IsConstFmtStr);

    // End block, returns -1 on failure
    UncondBrInst::Create(End, ArgPush);
    Builder.SetInsertPoint(End);
    return Builder.CreateSExt(Builder.CreateNot(Cmp), Int32Ty, "printf_result");
  }

  auto Desc = callPrintfBegin(Builder, Builder.getIntN(64, 0));
  Desc = appendString(Builder, Desc, Fmt, NumOps == 1);

  // FIXME: This invokes hostcall once for each argument. We can pack up to
  // seven scalar printf arguments in a single hostcall. See the signature of
  // callAppendArgs().
  for (unsigned int i = 1; i != NumOps; ++i) {
    bool IsLast = i == NumOps - 1;
    bool IsCString = SpecIsCString.test(i);
    Desc = processArg(Builder, Desc, Args[i], IsCString, IsLast);
  }

  return Builder.CreateTrunc(Desc, Builder.getInt32Ty());
}
