cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
137 lines
4.0 KiB
C++
137 lines
4.0 KiB
C++
//===-- lib/runtime/stack.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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Trivial implementation of stack that can be used on all targets.
|
|
// It is a list based stack with dynamic allocation/deallocation
|
|
// of the list nodes.
|
|
|
|
#ifndef FLANG_RT_RUNTIME_STACK_H_
|
|
#define FLANG_RT_RUNTIME_STACK_H_
|
|
|
|
#include "flang-rt/runtime/memory.h"
|
|
#include "flang-rt/runtime/terminator.h"
|
|
|
|
namespace Fortran::runtime {
|
|
// Storage for the Stack elements of type T.
|
|
template <typename T, unsigned N> struct StackStorage {
|
|
RT_API_ATTRS void *getElement(unsigned i) {
|
|
if (i < N) {
|
|
return storage[i];
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
RT_API_ATTRS const void *getElement(unsigned i) const {
|
|
if (i < N) {
|
|
return storage[i];
|
|
} else {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
private:
|
|
// Storage to hold N elements of type T.
|
|
// It is declared as an array of bytes to avoid
|
|
// default construction (if any is implied by type T).
|
|
alignas(T) char storage[N][sizeof(T)];
|
|
};
|
|
|
|
// 0-size specialization that provides no storage.
|
|
template <typename T> struct alignas(T) StackStorage<T, 0> {
|
|
RT_API_ATTRS void *getElement(unsigned) { return nullptr; }
|
|
RT_API_ATTRS const void *getElement(unsigned) const { return nullptr; }
|
|
};
|
|
|
|
template <typename T, unsigned N = 0> class Stack : public StackStorage<T, N> {
|
|
public:
|
|
Stack() = delete;
|
|
Stack(const Stack &) = delete;
|
|
Stack(Stack &&) = delete;
|
|
RT_API_ATTRS Stack(Terminator &terminator) : terminator_{terminator} {}
|
|
RT_API_ATTRS ~Stack() {
|
|
while (!empty()) {
|
|
pop();
|
|
}
|
|
}
|
|
RT_API_ATTRS void push(const T &object) {
|
|
if (void *ptr{this->getElement(size_)}) {
|
|
new (ptr) T{object};
|
|
} else {
|
|
top_ = New<List>{terminator_}(top_, object).release();
|
|
}
|
|
++size_;
|
|
}
|
|
RT_API_ATTRS void push(T &&object) {
|
|
if (void *ptr{this->getElement(size_)}) {
|
|
new (ptr) T{std::move(object)};
|
|
} else {
|
|
top_ = New<List>{terminator_}(top_, std::move(object)).release();
|
|
}
|
|
++size_;
|
|
}
|
|
template <typename... Args> RT_API_ATTRS void emplace(Args &&...args) {
|
|
if (void *ptr{this->getElement(size_)}) {
|
|
new (ptr) T{std::forward<Args>(args)...};
|
|
} else {
|
|
top_ =
|
|
New<List>{terminator_}(top_, std::forward<Args>(args)...).release();
|
|
}
|
|
++size_;
|
|
}
|
|
RT_API_ATTRS T &top() {
|
|
RUNTIME_CHECK(terminator_, size_ > 0);
|
|
if (void *ptr{this->getElement(size_ - 1)}) {
|
|
return *reinterpret_cast<T *>(ptr);
|
|
} else {
|
|
RUNTIME_CHECK(terminator_, top_);
|
|
return top_->object_;
|
|
}
|
|
}
|
|
RT_API_ATTRS const T &top() const {
|
|
RUNTIME_CHECK(terminator_, size_ > 0);
|
|
if (void *ptr{this->getElement(size_ - 1)}) {
|
|
return *reinterpret_cast<const T *>(ptr);
|
|
} else {
|
|
RUNTIME_CHECK(terminator_, top_);
|
|
return top_->object_;
|
|
}
|
|
}
|
|
RT_API_ATTRS void pop() {
|
|
RUNTIME_CHECK(terminator_, size_ > 0);
|
|
if (void *ptr{this->getElement(size_ - 1)}) {
|
|
reinterpret_cast<T *>(ptr)->~T();
|
|
} else {
|
|
RUNTIME_CHECK(terminator_, top_);
|
|
List *next{top_->next_};
|
|
top_->~List();
|
|
FreeMemory(top_);
|
|
top_ = next;
|
|
}
|
|
--size_;
|
|
}
|
|
RT_API_ATTRS bool empty() const { return size_ == 0; }
|
|
|
|
private:
|
|
struct List {
|
|
template <typename... Args>
|
|
RT_API_ATTRS List(List *next, Args &&...args)
|
|
: next_(next), object_(std::forward<Args>(args)...) {}
|
|
RT_API_ATTRS List(List *next, const T &object)
|
|
: next_(next), object_(object) {}
|
|
RT_API_ATTRS List(List *next, T &&object)
|
|
: next_(next), object_(std::move(object)) {}
|
|
List *next_{nullptr};
|
|
T object_;
|
|
};
|
|
List *top_{nullptr};
|
|
std::size_t size_{0};
|
|
Terminator &terminator_;
|
|
};
|
|
} // namespace Fortran::runtime
|
|
#endif // FLANG_RT_RUNTIME_STACK_H_
|