//===--- GenCoverage.cpp - IR Generation for coverage ---------------------===//
//
// 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 the initialization of
//  coverage related variables.
//
//===----------------------------------------------------------------------===//

#include "IRGenModule.h"
#include "SwiftTargetInfo.h"

#include "swift/SIL/SILModule.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
#include "llvm/Support/FileSystem.h"

using namespace swift;
using namespace irgen;

using llvm::coverage::CovMapVersion;
using llvm::coverage::CounterMappingRegion;

static std::string getCoverageSection(IRGenModule &IGM) {
  return llvm::getInstrProfSectionName(llvm::IPSK_covmap,
                                       IGM.Triple.getObjectFormat());
}

void IRGenModule::emitCoverageMapping() {
  std::vector<const SILCoverageMap *> Mappings;
  for (const auto &M : getSILModule().getCoverageMaps())
    if (M.second->hasSymtabEntry())
      Mappings.push_back(M.second);

  // If there aren't any coverage maps, there's nothing to emit.
  if (Mappings.empty())
    return;

  std::vector<StringRef> Files;
  for (const auto &M : Mappings)
    if (std::find(Files.begin(), Files.end(), M->getFile()) == Files.end())
      Files.push_back(M->getFile());

  // Awkwardly munge absolute filenames into a vector of StringRefs.
  // TODO: This is heinous - the same thing is happening in clang, but the API
  // really needs to be cleaned up for both.
  llvm::SmallVector<std::string, 8> FilenameStrs;
  llvm::SmallVector<StringRef, 8> FilenameRefs;
  for (StringRef Name : Files) {
    llvm::SmallString<256> Path(Name);
    llvm::sys::fs::make_absolute(Path);
    FilenameStrs.push_back(std::string(Path.begin(), Path.end()));
    FilenameRefs.push_back(FilenameStrs.back());
  }

  // Encode the filenames first.
  std::string FilenamesAndCoverageMappings;
  llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
  llvm::coverage::CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
  size_t FilenamesSize = OS.str().size();
  size_t CurrentSize, PrevSize = FilenamesSize;

  // Now we need to build up the list of function records.
  llvm::LLVMContext &Ctx = LLVMContext;
  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);

  llvm::Type *FunctionRecordTypes[] = {
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
#include "llvm/ProfileData/InstrProfData.inc"
#undef COVMAP_FUNC_RECORD
  };

  auto FunctionRecordTy =
      llvm::StructType::get(Ctx, llvm::makeArrayRef(FunctionRecordTypes),
                            /*isPacked=*/true);

  std::vector<llvm::Constant *> FunctionRecords;
  std::vector<CounterMappingRegion> Regions;
  for (const auto &M : Mappings) {
    unsigned FileID =
        std::find(Files.begin(), Files.end(), M->getFile()) - Files.begin();
    Regions.clear();
    for (const auto &MR : M->getMappedRegions())
      Regions.emplace_back(CounterMappingRegion::makeRegion(
          MR.Counter, /*FileID=*/0, MR.StartLine, MR.StartCol, MR.EndLine,
          MR.EndCol));
    // Append each function's regions into the encoded buffer.
    ArrayRef<unsigned> VirtualFileMapping(FileID);
    llvm::coverage::CoverageMappingWriter W(VirtualFileMapping,
                                            M->getExpressions(), Regions);
    W.write(OS);

    CurrentSize = OS.str().size();
    unsigned MappingLen = CurrentSize - PrevSize;
    StringRef CoverageMapping(OS.str().c_str() + PrevSize, MappingLen);

    StringRef NameValue = M->getPGOFuncName();
    uint64_t FuncHash = M->getHash();

    // Create a record for this function.
    llvm::Constant *FunctionRecordVals[] = {
#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
#include "llvm/ProfileData/InstrProfData.inc"
#undef COVMAP_FUNC_RECORD
    };

    FunctionRecords.push_back(llvm::ConstantStruct::get(
        FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
    PrevSize = CurrentSize;
  }
  size_t CoverageMappingSize = PrevSize - FilenamesSize;

  // Append extra zeroes if necessary to ensure that the size of the filenames
  // and coverage mappings is a multiple of 8.
  if (size_t Rem = OS.str().size() % 8) {
    CoverageMappingSize += 8 - Rem;
    for (size_t I = 0, S = 8 - Rem; I < S; ++I)
      OS << '\0';
  }
  auto *FilenamesAndMappingsVal =
      llvm::ConstantDataArray::getString(Ctx, OS.str(), false);

  auto *RecordsTy =
      llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
  auto *RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);

  // Create the coverage data header.
  llvm::Type *CovDataHeaderTypes[] = {
#define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
#include "llvm/ProfileData/InstrProfData.inc"
#undef COVMAP_HEADER
  };
  auto *CovDataHeaderTy =
      llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
  llvm::Constant *CovDataHeaderVals[] = {
#define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
#include "llvm/ProfileData/InstrProfData.inc"
#undef COVMAP_HEADER
  };
  auto *CovDataHeaderVal = llvm::ConstantStruct::get(
      CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));

  // Combine the header, function records, and mappings together.
  llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
                                FilenamesAndMappingsVal->getType()};
  auto *CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
  llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
                                  FilenamesAndMappingsVal};
  auto *CovDataVal =
      llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));

  auto CovData = new llvm::GlobalVariable(
      *getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
      CovDataVal, llvm::getCoverageMappingVarName());
  std::string CovSection = getCoverageSection(*this);
  CovData->setSection(CovSection);
  CovData->setAlignment(8);
  addUsedGlobal(CovData);
}
