//===--- LayoutOverrideSource.cpp --Override Record Layouts ---------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/LayoutOverrideSource.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/CharInfo.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
#include <string>

using namespace clang;

/// Parse a simple identifier.
static std::string parseName(StringRef S) {
  if (S.empty() || !isIdentifierHead(S[0]))
    return "";

  unsigned Offset = 1;
  while (Offset < S.size() && isIdentifierBody(S[Offset]))
    ++Offset;

  return S.substr(0, Offset).str();
}

LayoutOverrideSource::LayoutOverrideSource(StringRef Filename) {
  std::ifstream Input(Filename.str().c_str());
  if (!Input.is_open())
    return;

  // Parse the output of -fdump-record-layouts.
  std::string CurrentType;
  Layout CurrentLayout;
  bool ExpectingType = false;

  while (Input.good()) {
    std::string Line;
    getline(Input, Line);

    StringRef LineStr(Line);

    // Determine whether the following line will start a
    if (LineStr.find("*** Dumping AST Record Layout") != StringRef::npos)  {
      // Flush the last type/layout, if there is one.
      if (!CurrentType.empty())
        Layouts[CurrentType] = CurrentLayout;
      CurrentLayout = Layout();

      ExpectingType = true;
      continue;
    }

    // If we're expecting a type, grab it.
    if (ExpectingType) {
      ExpectingType = false;

      StringRef::size_type Pos;
      if ((Pos = LineStr.find("struct ")) != StringRef::npos)
        LineStr = LineStr.substr(Pos + strlen("struct "));
      else if ((Pos = LineStr.find("class ")) != StringRef::npos)
        LineStr = LineStr.substr(Pos + strlen("class "));
      else if ((Pos = LineStr.find("union ")) != StringRef::npos)
        LineStr = LineStr.substr(Pos + strlen("union "));
      else
        continue;

      // Find the name of the type.
      CurrentType = parseName(LineStr);
      CurrentLayout = Layout();
      continue;
    }

    // Check for the size of the type.
    StringRef::size_type Pos = LineStr.find(" Size:");
    if (Pos != StringRef::npos) {
      // Skip past the " Size:" prefix.
      LineStr = LineStr.substr(Pos + strlen(" Size:"));

      unsigned long long Size = 0;
      (void)LineStr.getAsInteger(10, Size);
      CurrentLayout.Size = Size;
      continue;
    }

    // Check for the alignment of the type.
    Pos = LineStr.find("Alignment:");
    if (Pos != StringRef::npos) {
      // Skip past the "Alignment:" prefix.
      LineStr = LineStr.substr(Pos + strlen("Alignment:"));

      unsigned long long Alignment = 0;
      (void)LineStr.getAsInteger(10, Alignment);
      CurrentLayout.Align = Alignment;
      continue;
    }

    // Check for the size/alignment of the type.
    Pos = LineStr.find("sizeof=");
    if (Pos != StringRef::npos) {
      /* Skip past the sizeof= prefix. */
      LineStr = LineStr.substr(Pos + strlen("sizeof="));

      // Parse size.
      unsigned long long Size = 0;
      (void)LineStr.getAsInteger(10, Size);
      CurrentLayout.Size = Size;

      Pos = LineStr.find("align=");
      if (Pos != StringRef::npos) {
        /* Skip past the align= prefix. */
        LineStr = LineStr.substr(Pos + strlen("align="));

        // Parse alignment.
        unsigned long long Alignment = 0;
        (void)LineStr.getAsInteger(10, Alignment);
        CurrentLayout.Align = Alignment;
      }

      continue;
    }

    // Check for the field offsets of the type.
    Pos = LineStr.find("FieldOffsets: [");
    if (Pos == StringRef::npos)
      continue;

    LineStr = LineStr.substr(Pos + strlen("FieldOffsets: ["));
    while (!LineStr.empty() && isDigit(LineStr[0])) {
      // Parse this offset.
      unsigned Idx = 1;
      while (Idx < LineStr.size() && isDigit(LineStr[Idx]))
        ++Idx;

      unsigned long long Offset = 0;
      (void)LineStr.substr(0, Idx).getAsInteger(10, Offset);

      CurrentLayout.FieldOffsets.push_back(Offset);

      // Skip over this offset, the following comma, and any spaces.
      LineStr = LineStr.substr(Idx + 1);
      while (!LineStr.empty() && isWhitespace(LineStr[0]))
        LineStr = LineStr.substr(1);
    }
  }

  // Flush the last type/layout, if there is one.
  if (!CurrentType.empty())
    Layouts[CurrentType] = CurrentLayout;
}

bool
LayoutOverrideSource::layoutRecordType(const RecordDecl *Record,
  uint64_t &Size, uint64_t &Alignment,
  llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
  llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
  llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets)
{
  // We can't override unnamed declarations.
  if (!Record->getIdentifier())
    return false;

  // Check whether we have a layout for this record.
  llvm::StringMap<Layout>::iterator Known = Layouts.find(Record->getName());
  if (Known == Layouts.end())
    return false;

  // Provide field layouts.
  unsigned NumFields = 0;
  for (RecordDecl::field_iterator F = Record->field_begin(),
                               FEnd = Record->field_end();
       F != FEnd; ++F, ++NumFields) {
    if (NumFields >= Known->second.FieldOffsets.size())
      continue;

    FieldOffsets[*F] = Known->second.FieldOffsets[NumFields];
  }

  // Wrong number of fields.
  if (NumFields != Known->second.FieldOffsets.size())
    return false;

  Size = Known->second.Size;
  Alignment = Known->second.Align;
  return true;
}

LLVM_DUMP_METHOD void LayoutOverrideSource::dump() {
  raw_ostream &OS = llvm::errs();
  for (llvm::StringMap<Layout>::iterator L = Layouts.begin(),
                                      LEnd = Layouts.end();
       L != LEnd; ++L) {
    OS << "Type: blah " << L->first() << '\n';
    OS << "  Size:" << L->second.Size << '\n';
    OS << "  Alignment:" << L->second.Align << '\n';
    OS << "  FieldOffsets: [";
    for (unsigned I = 0, N = L->second.FieldOffsets.size(); I != N; ++I) {
      if (I)
        OS << ", ";
      OS << L->second.FieldOffsets[I];
    }
    OS << "]\n";
  }
}

