Skip to content

Commit

Permalink
[ORC-RT] Add string_view and span utilities for use by the ORC runtime.
Browse files Browse the repository at this point in the history
These are substitutes for std::string_view (and llvm::StringRef) and std::span
(and llvm::ArrayRef) for use by the ORC runtime.
  • Loading branch information
lhames committed May 20, 2021
1 parent a26288e commit d22b27c
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 0 deletions.
98 changes: 98 additions & 0 deletions compiler-rt/lib/orc/adt.h
@@ -0,0 +1,98 @@
//===----------------------- adt.h - Handy ADTs -----------------*- 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 file is a part of the ORC runtime support library.
//
//===----------------------------------------------------------------------===//

#ifndef ORC_RT_ADT_H
#define ORC_RT_ADT_H

#include <cstring>
#include <limits>
#include <string>

namespace __orc_rt {

constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();

/// A substitute for std::span (and llvm::ArrayRef).
/// FIXME: Remove in favor of std::span once we can use c++20.
template <typename T, std::size_t Extent = dynamic_extent> class span {
public:
typedef T element_type;
typedef std::remove_cv<T> value_type;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T *pointer;
typedef const T *const_pointer;
typedef T &reference;
typedef const T &const_reference;

typedef pointer iterator;

static constexpr std::size_t extent = Extent;

constexpr span() noexcept = default;
constexpr span(T *first, size_type count) noexcept
: Data(first), Size(count) {}

template <std::size_t N>
constexpr span(T (&arr)[N]) noexcept : Data(&arr[0]), Size(N) {}

constexpr iterator begin() const noexcept { return Data; }
constexpr iterator end() const noexcept { return Data + Size; }
constexpr pointer data() const noexcept { return Data; }
constexpr reference operator[](size_type idx) const { return Data[idx]; }
constexpr size_type size() const noexcept { return Size; }
constexpr bool empty() const noexcept { return Size == 0; }

private:
T *Data = nullptr;
size_type Size = 0;
};

/// A substitue for std::string_view (and llvm::StringRef).
/// FIXME: Remove in favor of std::string_view once we have c++17.
class string_view {
public:
typedef char value_type;
typedef char *pointer;
typedef const char *const_pointer;
typedef char &reference;
typedef const char &const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

typedef const_pointer const_iterator;
typedef const_iterator iterator;

constexpr string_view() noexcept = default;
constexpr string_view(const char *S, size_type Count)
: Data(S), Size(Count) {}
string_view(const char *S) : Data(S), Size(strlen(S)) {}

constexpr const_iterator begin() const noexcept { return Data; }
constexpr const_iterator end() const noexcept { return Data + Size; }
constexpr const_pointer data() const noexcept { return Data; }
constexpr const_reference operator[](size_type idx) { return Data[idx]; }
constexpr size_type size() const noexcept { return Size; }
constexpr bool empty() const noexcept { return Size == 0; }

private:
const char *Data = nullptr;
size_type Size = 0;
};

inline std::string to_string(string_view SV) {
return std::string(SV.data(), SV.size());
}

} // end namespace __orc_rt

#endif // ORC_RT_COMMON_H
1 change: 1 addition & 0 deletions compiler-rt/lib/orc/unittests/CMakeLists.txt
Expand Up @@ -80,6 +80,7 @@ macro(add_orc_unittest testname)
endmacro()

set(UNITTEST_SOURCES
adt_test.cpp
error_test.cpp
extensible_rtti_test.cpp
orc_unit_test_main.cpp
Expand Down
80 changes: 80 additions & 0 deletions compiler-rt/lib/orc/unittests/adt_test.cpp
@@ -0,0 +1,80 @@
//===-- adt_test.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
//
//===----------------------------------------------------------------------===//
//
// This file is a part of the ORC runtime.
//
//===----------------------------------------------------------------------===//

#include "adt.h"
#include "gtest/gtest.h"

using namespace __orc_rt;

TEST(ADTTest, SpanDefaultConstruction) {
span<int> S;
EXPECT_TRUE(S.empty()) << "Default constructed span not empty";
EXPECT_EQ(S.size(), 0U) << "Default constructed span size not zero";
EXPECT_EQ(S.begin(), S.end()) << "Default constructed span begin != end";
}

TEST(ADTTest, SpanConstructFromFixedArray) {
int A[] = {1, 2, 3, 4, 5};
span<int> S(A);
EXPECT_FALSE(S.empty()) << "Span should be non-empty";
EXPECT_EQ(S.size(), 5U) << "Span has unexpected size";
EXPECT_EQ(std::distance(S.begin(), S.end()), 5U)
<< "Unexpected iterator range size";
EXPECT_EQ(S.data(), &A[0]) << "Span data has unexpected value";
for (unsigned I = 0; I != S.size(); ++I)
EXPECT_EQ(S[I], A[I]) << "Unexpected span element value";
}

TEST(ADTTest, SpanConstructFromIteratorAndSize) {
int A[] = {1, 2, 3, 4, 5};
span<int> S(&A[0], 5);
EXPECT_FALSE(S.empty()) << "Span should be non-empty";
EXPECT_EQ(S.size(), 5U) << "Span has unexpected size";
EXPECT_EQ(std::distance(S.begin(), S.end()), 5U)
<< "Unexpected iterator range size";
EXPECT_EQ(S.data(), &A[0]) << "Span data has unexpected value";
for (unsigned I = 0; I != S.size(); ++I)
EXPECT_EQ(S[I], A[I]) << "Unexpected span element value";
}

TEST(ADTTest, StringViewDefaultConstruction) {
string_view S;
EXPECT_TRUE(S.empty()) << "Default constructed span not empty";
EXPECT_EQ(S.size(), 0U) << "Default constructed span size not zero";
EXPECT_EQ(S.begin(), S.end()) << "Default constructed span begin != end";
}

TEST(ADTTest, StringViewConstructFromCharPtrAndSize) {
const char *Str = "abcdefg";
string_view S(Str, 5);
EXPECT_FALSE(S.empty()) << "Span should be non-empty";
EXPECT_EQ(S.size(), 5U) << "Span has unexpected size";
EXPECT_EQ(std::distance(S.begin(), S.end()), 5U)
<< "Unexpected iterator range size";
EXPECT_EQ(S.data(), &Str[0]) << "Span data has unexpected value";
for (unsigned I = 0; I != S.size(); ++I)
EXPECT_EQ(S[I], Str[I]) << "Unexpected span element value";
}

TEST(ADTTest, StringViewConstructFromCharPtr) {
const char *Str = "abcdefg";
size_t StrLen = strlen(Str);
string_view S(Str);

EXPECT_FALSE(S.empty()) << "Span should be non-empty";
EXPECT_EQ(S.size(), StrLen) << "Span has unexpected size";
EXPECT_EQ(std::distance(S.begin(), S.end()), StrLen)
<< "Unexpected iterator range size";
EXPECT_EQ(S.data(), &Str[0]) << "Span data has unexpected value";
for (unsigned I = 0; I != S.size(); ++I)
EXPECT_EQ(S[I], Str[I]) << "Unexpected span element value";
}

0 comments on commit d22b27c

Please sign in to comment.