Пример #1
0
void SwiftAggLowering::addLegalTypedData(llvm::Type *type,
                                         CharUnits begin, CharUnits end) {
  // Require the type to be naturally aligned.
  if (!begin.isZero() && !begin.isMultipleOf(getNaturalAlignment(CGM, type))) {

    // Try splitting vector types.
    if (auto vecTy = dyn_cast<llvm::VectorType>(type)) {
      auto split = splitLegalVectorType(CGM, end - begin, vecTy);
      auto eltTy = split.first;
      auto numElts = split.second;

      auto eltSize = (end - begin) / numElts;
      assert(eltSize == getTypeStoreSize(CGM, eltTy));
      for (size_t i = 0, e = numElts; i != e; ++i) {
        addLegalTypedData(eltTy, begin, begin + eltSize);
        begin += eltSize;
      }
      assert(begin == end);
      return;
    }

    return addOpaqueData(begin, end);
  }

  addEntry(type, begin, end);
}
Пример #2
0
void SwiftAggLowering::addEntry(llvm::Type *type,
                                CharUnits begin, CharUnits end) {
  assert((!type ||
          (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) &&
         "cannot add aggregate-typed data");
  assert(!type || begin.isMultipleOf(getNaturalAlignment(CGM, type)));

  // Fast path: we can just add entries to the end.
  if (Entries.empty() || Entries.back().End <= begin) {
    Entries.push_back({begin, end, type});
    return;
  }

  // Find the first existing entry that ends after the start of the new data.
  // TODO: do a binary search if Entries is big enough for it to matter.
  size_t index = Entries.size() - 1;
  while (index != 0) {
    if (Entries[index - 1].End <= begin) break;
    --index;
  }

  // The entry ends after the start of the new data.
  // If the entry starts after the end of the new data, there's no conflict.
  if (Entries[index].Begin >= end) {
    // This insertion is potentially O(n), but the way we generally build
    // these layouts makes that unlikely to matter: we'd need a union of
    // several very large types.
    Entries.insert(Entries.begin() + index, {begin, end, type});
    return;
  }

  // Otherwise, the ranges overlap.  The new range might also overlap
  // with later ranges.
restartAfterSplit:

  // Simplest case: an exact overlap.
  if (Entries[index].Begin == begin && Entries[index].End == end) {
    // If the types match exactly, great.
    if (Entries[index].Type == type) return;

    // If either type is opaque, make the entry opaque and return.
    if (Entries[index].Type == nullptr) {
      return;
    } else if (type == nullptr) {
      Entries[index].Type = nullptr;
      return;
    }

    // If they disagree in an ABI-agnostic way, just resolve the conflict
    // arbitrarily.
    if (auto entryType = getCommonType(Entries[index].Type, type)) {
      Entries[index].Type = entryType;
      return;
    }

    // Otherwise, make the entry opaque.
    Entries[index].Type = nullptr;
    return;
  }

  // Okay, we have an overlapping conflict of some sort.

  // If we have a vector type, split it.
  if (auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) {
    auto eltTy = vecTy->getElementType();
    CharUnits eltSize = (end - begin) / vecTy->getNumElements();
    assert(eltSize == getTypeStoreSize(CGM, eltTy));
    for (unsigned i = 0, e = vecTy->getNumElements(); i != e; ++i) {
      addEntry(eltTy, begin, begin + eltSize);
      begin += eltSize;
    }
    assert(begin == end);
    return;
  }

  // If the entry is a vector type, split it and try again.
  if (Entries[index].Type && Entries[index].Type->isVectorTy()) {
    splitVectorEntry(index);
    goto restartAfterSplit;
  }

  // Okay, we have no choice but to make the existing entry opaque.

  Entries[index].Type = nullptr;

  // Stretch the start of the entry to the beginning of the range.
  if (begin < Entries[index].Begin) {
    Entries[index].Begin = begin;
    assert(index == 0 || begin >= Entries[index - 1].End);
  }

  // Stretch the end of the entry to the end of the range; but if we run
  // into the start of the next entry, just leave the range there and repeat.
  while (end > Entries[index].End) {
    assert(Entries[index].Type == nullptr);

    // If the range doesn't overlap the next entry, we're done.
    if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) {
      Entries[index].End = end;
      break;
    }

    // Otherwise, stretch to the start of the next entry.
    Entries[index].End = Entries[index + 1].Begin;

    // Continue with the next entry.
    index++;

    // This entry needs to be made opaque if it is not already.
    if (Entries[index].Type == nullptr)
      continue;

    // Split vector entries unless we completely subsume them.
    if (Entries[index].Type->isVectorTy() &&
        end < Entries[index].End) {
      splitVectorEntry(index);
    }

    // Make the entry opaque.
    Entries[index].Type = nullptr;
  }
}