mirror of
https://github.com/YosysHQ/yosys.git
synced 2026-10-06 01:53:53 +02:00
twines: LeafIdString
This commit is contained in:
+23
-4
@@ -176,6 +176,10 @@ IdString TwinePool::stamp(IdString ref) const {
|
||||
return ref.stamped(serial_);
|
||||
}
|
||||
|
||||
LeafIdString TwinePool::stamp(LeafIdString ref) const {
|
||||
return LeafIdString(stamp(IdString(ref)));
|
||||
}
|
||||
|
||||
void TwinePool::check_owned(IdString ref) const {
|
||||
if constexpr (IdString::MAX_SERIAL != 0)
|
||||
log_assert(owns(ref));
|
||||
@@ -295,12 +299,12 @@ IdString TwinePool::intern(uint32_t prefix, std::string_view text) {
|
||||
return add_inner(TwineNode{prefix, text});
|
||||
}
|
||||
|
||||
IdString TwinePool::find(const std::string &name) const {
|
||||
LeafIdString TwinePool::find(const std::string &name) const {
|
||||
bool is_public = !name.empty() && name[0] == '\\';
|
||||
std::string_view content = name;
|
||||
if (is_public)
|
||||
content.remove_prefix(1);
|
||||
return stamp(find_content(TwineNode::NO_PREFIX, content).tag(is_public));
|
||||
return stamp(LeafIdString(find_content(TwineNode::NO_PREFIX, content)).tag(is_public));
|
||||
}
|
||||
|
||||
IdString TwinePool::find(TwineSpec t) const {
|
||||
@@ -340,11 +344,17 @@ IdString TwinePool::add(IdString prefix, std::string_view tail) {
|
||||
return stamp(intern((uint32_t)prefix.untag().raw(), tail).tag(prefix.isPublic()));
|
||||
}
|
||||
|
||||
IdString TwinePool::add(std::string s) {
|
||||
LeafIdString TwinePool::add(std::string s) {
|
||||
if (s.empty())
|
||||
return IdString::Null;
|
||||
auto [content, is_public] = twine_unescape(std::move(s));
|
||||
return stamp(intern(TwineNode::NO_PREFIX, content).tag(is_public));
|
||||
return stamp(LeafIdString(intern(TwineNode::NO_PREFIX, content)).tag(is_public));
|
||||
}
|
||||
|
||||
LeafIdString TwinePool::flatten(IdString ref) {
|
||||
if (ref == IdString::Null || ID::is_static(ref) || (*this)[ref].is_leaf())
|
||||
return LeafIdString(stamp(ref));
|
||||
return stamp(LeafIdString(intern(TwineNode::NO_PREFIX, unescaped_str(ref))).tag(ref.isPublic()));
|
||||
}
|
||||
|
||||
IdString TwinePool::copy_from(const TwinePool& src, IdString ref) {
|
||||
@@ -369,6 +379,11 @@ IdString TwinePool::copy_from(const TwinePool& src, IdString ref) {
|
||||
return IdString::Null;
|
||||
}
|
||||
|
||||
// Copying preserves structure, so leaves stay leaves
|
||||
LeafIdString TwinePool::copy_from(const TwinePool& src, LeafIdString ref) {
|
||||
return LeafIdString(copy_from(src, IdString(ref)));
|
||||
}
|
||||
|
||||
IdString TwinePool::find_from(const TwinePool& src, IdString ref) const {
|
||||
if (ref == IdString::Null)
|
||||
return ref;
|
||||
@@ -393,6 +408,10 @@ IdString TwinePool::find_from(const TwinePool& src, IdString ref) const {
|
||||
return IdString::Null;
|
||||
}
|
||||
|
||||
LeafIdString TwinePool::find_from(const TwinePool& src, LeafIdString ref) const {
|
||||
return LeafIdString(find_from(src, IdString(ref)));
|
||||
}
|
||||
|
||||
std::string TwinePool::ref_token(IdString ref) const {
|
||||
return "#" + std::to_string((uint64_t)serial_) + ":"
|
||||
+ std::to_string((uint64_t)stamp(ref).bits());
|
||||
|
||||
+43
-6
@@ -150,6 +150,30 @@ public:
|
||||
constexpr NullIdString::operator IdString() const { return IdString(); }
|
||||
constexpr bool NullIdString::operator==(IdString ref) const { return ref.empty(); }
|
||||
|
||||
/**
|
||||
* LeafIdString is an IdString that is statically known to be a leaf twine
|
||||
* (or Null). Handles only compare equal when they're structurally equal,
|
||||
* so a key that's looked up with static ids or strings interned with
|
||||
* TwinePool::add(std::string), like attribute and parameter keys,
|
||||
* has to be a leaf: a suffix twine spelling the same name wouldn't be found.
|
||||
*
|
||||
* Static ids are leaves. Otherwise, only the TwinePool methods that
|
||||
* intern leaves construct one, so where a suffix would sneak in,
|
||||
* the conversion has to be spelled out with TwinePool::flatten.
|
||||
*/
|
||||
struct LeafIdString : IdString {
|
||||
constexpr LeafIdString() = default;
|
||||
constexpr LeafIdString(NullIdString) {}
|
||||
|
||||
constexpr LeafIdString untag() const { return LeafIdString(IdString::untag()); }
|
||||
constexpr LeafIdString tag(bool pub) const { return LeafIdString(IdString::tag(pub)); }
|
||||
|
||||
private:
|
||||
explicit constexpr LeafIdString(IdString ref) : IdString(ref) {}
|
||||
friend struct ID;
|
||||
friend struct TwinePool;
|
||||
};
|
||||
|
||||
namespace hashlib {
|
||||
template<>
|
||||
struct hash_ops<IdString> {
|
||||
@@ -164,6 +188,8 @@ namespace hashlib {
|
||||
return h;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct hash_ops<LeafIdString> : hash_ops<IdString> {};
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +204,7 @@ enum : short {
|
||||
struct ID {
|
||||
// Static ids are name handles: non-'$' constids were '\'-escaped publics,
|
||||
// so their handles carry the publicity bit baked in at compile time.
|
||||
#define X(N) static constexpr IdString N = IdString(IDX_##N).tag((#N)[0] != '$');
|
||||
#define X(N) static constexpr LeafIdString N = LeafIdString(IdString(IDX_##N)).tag((#N)[0] != '$');
|
||||
#include "kernel/constids.inc"
|
||||
#undef X
|
||||
|
||||
@@ -188,7 +214,7 @@ struct ID {
|
||||
#undef X
|
||||
};
|
||||
|
||||
static constexpr IdString lookup(std::string_view name)
|
||||
static constexpr LeafIdString lookup(std::string_view name)
|
||||
{
|
||||
int low = 0, high = STATIC_TWINE_END;
|
||||
while (high - low >= 2) {
|
||||
@@ -202,19 +228,26 @@ struct ID {
|
||||
if (name != static_names[low])
|
||||
throw "unknown twine id";
|
||||
|
||||
return IdString(low).tag(name[0] != '$');
|
||||
return LeafIdString(IdString(low)).tag(name[0] != '$');
|
||||
}
|
||||
|
||||
static constexpr bool is_static(IdString ref) {
|
||||
return ref.untag().raw() < STATIC_TWINE_END;
|
||||
}
|
||||
|
||||
// All static twines are leaves
|
||||
static constexpr LeafIdString static_leaf(size_t raw) {
|
||||
if (!is_static(IdString(raw)))
|
||||
throw "not a static twine id";
|
||||
return LeafIdString(IdString(raw));
|
||||
}
|
||||
|
||||
// Static IdString can be constructed without a design pointer
|
||||
static std::string str(IdString ref);
|
||||
static std::string unescaped_str(IdString ref);
|
||||
};
|
||||
|
||||
template<size_t Raw> inline constexpr IdString constid = IdString(Raw);
|
||||
template<size_t Raw> inline constexpr LeafIdString constid = ID::static_leaf(Raw);
|
||||
|
||||
#define ID(id) (YOSYS_NAMESPACE_PREFIX constid<YOSYS_NAMESPACE_PREFIX ID::lookup(#id).raw()>)
|
||||
|
||||
@@ -354,6 +387,7 @@ struct TwinePool : HashConsPool<TwinePool, TwineNode, IdString> {
|
||||
size_t serial() const;
|
||||
bool owns(IdString ref) const;
|
||||
IdString stamp(IdString ref) const;
|
||||
LeafIdString stamp(LeafIdString ref) const;
|
||||
void check_owned(IdString ref) const;
|
||||
const TwineNode& operator[](IdString ref) const;
|
||||
|
||||
@@ -396,17 +430,20 @@ struct TwinePool : HashConsPool<TwinePool, TwineNode, IdString> {
|
||||
IdString prefix_of(IdString ref) const;
|
||||
|
||||
// Only finds leaves. For compatibility only
|
||||
IdString find(const std::string &name) const;
|
||||
LeafIdString find(const std::string &name) const;
|
||||
IdString find(TwineSpec t) const;
|
||||
// Doesn't infer publicity
|
||||
IdString add(TwineSpec t);
|
||||
IdString add(IdString prefix, std::string_view tail);
|
||||
IdString auto_prefix(const std::string *prefix);
|
||||
// Infers publicity from first character
|
||||
IdString add(std::string s);
|
||||
LeafIdString add(std::string s);
|
||||
LeafIdString flatten(IdString ref);
|
||||
IdString copy_from(const TwinePool& src, IdString ref);
|
||||
LeafIdString copy_from(const TwinePool& src, LeafIdString ref);
|
||||
// Non-mutating counterpart of copy_from
|
||||
IdString find_from(const TwinePool& src, IdString ref) const;
|
||||
LeafIdString find_from(const TwinePool& src, LeafIdString ref) const;
|
||||
// Opaque handle for files that never leave one run of yosys.
|
||||
// Only valid until garbage collection reuses the slot.
|
||||
std::string ref_token(IdString ref) const;
|
||||
|
||||
Reference in New Issue
Block a user