Target type size

This commit is contained in:
York Jasper Niebuhr 2025-10-26 12:53:35 +01:00
parent 631fab7431
commit 6b716fbd56
5 changed files with 46 additions and 4 deletions

View File

@ -34,3 +34,13 @@ Custom UNSPECs can not get through vregs or a few later passes
-> architecture specific, dynamic operands though
-> can not get optimized (O1+ does optimizations in RTL, mostly after vregs)
-> could replace asm with normal "set" RTL close to final pass to remove architecture dependence
Plugin is per compilation unit
-> static label counters start at 0 for each
-> labels are local symbols in symbtab
-> symtab entries like "df *ABS* 0000000000000000 main.c" indicate block begin for new file
-> "main.c" and "sub/main.c" both only specify "main.c" (no way to differentiate)
-> emit UID symbol per CU to match symbol block to unique label set
-> structs with same name can habe different definitions in different CUs (disallow this for now)
-> anonymous structs can not really be matched between CUs without type hash (disallow this for now)
-> later, use hash(type) to match structs between CUs to randomize as one

View File

@ -4,7 +4,7 @@
<sourcefile>.spslr:
SPSLR_FINALIZE_HEADER <CU filename> <CU uid symbol>
target <hash> <local uid> <size> <field count>
target <name> <local uid> <size> <field count>
f <offset> <size> <flags>
f <offset> <size> <flags>
...
@ -20,7 +20,8 @@ dpin <symbol> <offset> <level> <target uid>
Datapins for same var/symbol are randomized in order of their level, from bottom of nest to top
The CU uid symbol helps differentiating between e.g. "file.c" and "sub/file.c" (symbtab has no idea)
Between CUs, types with the same hash are considered to be the same type
Between CUs, types with the same name HAVE TO HAVE the same layout -> randomized together
To begin with, anonymous types are not allowed for randomization (later solved with hash(type) instead of name)!
*/

View File

@ -15,6 +15,9 @@ void on_finish_unit(void* plugin_data, void* user_data) {
std::cout << "Finishing unit \"" << lbasename(main_input_filename) << "\" ..." << std::endl;
for (const auto& [uid, target] : TargetType::all())
std::cout << " Target " << uid << " -> \"" << target.name() << "\" (" << target.size() << ")" << std::endl;
for (const DataPin& dpin : dpins()) {
std::cout << " Data pin at symbol \"" << dpin.symbol << "\":" << std::endl;
for (const DataPin::Component& c : dpin.components)

View File

@ -1,6 +1,7 @@
#pragma once
#include <cstddef>
#include <map>
#include <unordered_map>
#include <string>
#include <list>
#include <limits>
@ -27,6 +28,7 @@ private:
UID m_uid;
std::size_t m_flags;
tree m_main_variant;
std::size_t m_size;
// Fields are identified by their offsets
std::map<std::size_t, Field> m_fields;
@ -44,12 +46,14 @@ public:
std::string name() const;
const Field* field(std::size_t off, bool exact = true) const;
UID uid() const;
std::size_t size() const;
static void add(tree t);
static std::size_t count();
static const TargetType* find(tree t); // O(n)
static const TargetType* find(UID uid); // O(1)
static bool reference(tree ref, UID& target, std::size_t& offset);
static const std::unordered_map<UID, TargetType>& all();
private:
friend void on_finish_type(void*, void*);
bool fetch_fields(bool redo = false);

View File

@ -1,5 +1,4 @@
#include <stage0.h>
#include <unordered_map>
#include <functional>
#include <safe-langhooks.h>
@ -14,7 +13,7 @@ static tree get_record_main_variant(tree t) {
return TYPE_MAIN_VARIANT(t);
}
TargetType::TargetType(tree t) : m_uid{ UID_INVALID }, m_flags{ 0 } {
TargetType::TargetType(tree t) : m_uid{ UID_INVALID }, m_flags{ 0 }, m_size{ 0 } {
if (!(m_main_variant = get_record_main_variant(t)))
return;
@ -75,6 +74,13 @@ UID TargetType::uid() const {
return m_uid;
}
std::size_t TargetType::size() const {
if (!valid() || !(m_flags & FLAG_FIELDS))
return 0;
return m_size;
}
void TargetType::add(tree t) {
if (find(t) != nullptr)
return;
@ -206,6 +212,10 @@ bool TargetType::reference(tree ref, UID& target, std::size_t& offset) {
return true;
}
const std::unordered_map<UID, TargetType>& TargetType::all() {
return targets;
}
static bool foreach_record_field(tree t, std::function<bool(const TargetType::Field&)> callback) {
if (!t || TREE_CODE(t) != RECORD_TYPE)
return false;
@ -285,6 +295,20 @@ bool TargetType::fetch_fields(bool redo) {
if (!foreach_record_field(m_main_variant, per_field_callback))
return false;
// Get struct size
tree size_tree = TYPE_SIZE(m_main_variant);
if (!size_tree || TREE_CODE(size_tree) != INTEGER_CST)
return false;
HOST_WIDE_INT size_bits = tree_to_uhwi(size_tree);
if (size_bits < 0 || size_bits % 8 != 0)
return false;
m_size = static_cast<std::size_t>(size_bits / 8);
// Everything done
m_fields = std::move(tmp_fields);
m_flags |= FLAG_FIELDS;
return true;