================
@@ -0,0 +1,201 @@
+//===-- CodeGen/CGObjCMacConstantLiteralUtil.h - ----------------*- C++ 
-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This should be used for things that effect the ABI of
+// Obj-C constant initializer literals (`-fobjc-constant-literals`) to allow
+// future changes without breaking the ABI promises.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CGOBJCMACCONSTANTLITERALUTIL_H
+#define LLVM_CLANG_LIB_CODEGEN_CGOBJCMACCONSTANTLITERALUTIL_H
+
+#include "CGObjCRuntime.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include <numeric>
+
+namespace clang {
+namespace CodeGen {
+namespace CGObjCMacConstantLiteralUtil {
+
+class NSConstantNumberMapInfo {
+
+  enum class MapInfoType {
+    Empty,
+    Tombstone,
+    Int,
+    Float,
+  };
+
+  MapInfoType InfoType;
+  QualType QType;
+  llvm::APSInt Int;
+  llvm::APFloat Float;
+
+  /// Default constructor that can create Empty or Tombstone info entries
+  explicit NSConstantNumberMapInfo(MapInfoType I = MapInfoType::Empty)
+      : InfoType(I), QType(QualType()), Int(), Float(0.0) {}
+
+  bool isEmptyOrTombstone() const {
+    return InfoType == MapInfoType::Empty || InfoType == 
MapInfoType::Tombstone;
+  }
+
+public:
+  NSConstantNumberMapInfo(const QualType &QT, const llvm::APSInt &V)
+      : InfoType(MapInfoType::Int), QType(QT), Int(V), Float(0.0) {}
+  NSConstantNumberMapInfo(const QualType &QT, const llvm::APFloat &V)
+      : InfoType(MapInfoType::Float), QType(QT), Int(), Float(V) {}
+
+  unsigned getHashValue() const {
+    assert(!isEmptyOrTombstone() && "Cannot hash empty or tombstone map 
info!");
+
+    unsigned QTypeHash = llvm::DenseMapInfo<QualType>::getHashValue(
+        llvm::DenseMapInfo<QualType>::getTombstoneKey());
+
+    if (InfoType == MapInfoType::Int)
+      return llvm::detail::combineHashValue((unsigned)Int.getZExtValue(),
+                                            QTypeHash);
+
+    assert(InfoType == MapInfoType::Float);
+    return llvm::detail::combineHashValue(
+        (unsigned)Float.bitcastToAPInt().getZExtValue(), QTypeHash);
+  }
+
+  static inline NSConstantNumberMapInfo getEmptyKey() {
+    return NSConstantNumberMapInfo();
+  }
+
+  static inline NSConstantNumberMapInfo getTombstoneKey() {
+    return NSConstantNumberMapInfo(MapInfoType::Tombstone);
+  }
+
+  bool operator==(const NSConstantNumberMapInfo &RHS) const {
+    if (InfoType != RHS.InfoType || QType != RHS.QType)
+      return false;
+
+    // Handle the empty and tombstone equality
+    if (isEmptyOrTombstone())
+      return true;
+
+    if (InfoType == MapInfoType::Int)
+      return llvm::APSInt::isSameValue(Int, RHS.Int);
+
+    assert(InfoType == MapInfoType::Float);
+
+    // handle -0, NaN, and infinities correctly
+    return Float.bitwiseIsEqual(RHS.Float);
+  }
+};
+
+using std::iota;
+
+class NSDictionaryBuilder {
+  SmallVector<llvm::Constant *, 16> Keys;
+  SmallVector<llvm::Constant *, 16> Objects;
+  uint64_t Opts;
+
+public:
+  enum class Options : uint64_t { Sorted = 1 };
+
+  NSDictionaryBuilder(const ObjCDictionaryLiteral *E,
+                      const ArrayRef<llvm::Constant *> &KYS,
+                      const ArrayRef<llvm::Constant *> &OBS,
+                      const Options O = Options::Sorted) {
+    assert((KYS.size() == OBS.size()) &&
+           "NSConstantDictionary requires key / value pairs!"
+           "keys and objects not of equal size!");
+
+    Opts = static_cast<uint64_t>(O);
+    uint64_t const NumElements = KYS.size();
+
+    // Reserve the capacity for the sorted keys & values
+    Keys.reserve(NumElements);
+    Objects.reserve(NumElements);
+
+    // Setup the element indicies 0 ..< NumElements
+    SmallVector<size_t, 16> ElementIndicies;
+    ElementIndicies.reserve(NumElements);
+    for (size_t i = 0; i < NumElements; i++) {
+      ElementIndicies.push_back(i);
+    }
+    std::iota(ElementIndicies.begin(), ElementIndicies.end(), 0);
----------------
ahatanak wrote:

Indices are still needed here because we use the keys of 
`ObjCDictionaryLiteral` to sort the elements.

We could refactor to avoid indices, but the tradeoff isn't obvious to me.

https://github.com/llvm/llvm-project/pull/185130
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to