2020-09-13 21:32:55 -04:00
|
|
|
#pragma once
|
|
|
|
|
2020-09-12 13:11:42 -04:00
|
|
|
#include <string>
|
2020-10-16 17:08:26 -04:00
|
|
|
#include <vector>
|
2020-12-19 15:21:29 -05:00
|
|
|
#include "common/type_system/TypeSpec.h"
|
2020-09-12 13:11:42 -04:00
|
|
|
#include "goalc/emitter/ObjectGenerator.h"
|
2021-05-18 21:25:29 -04:00
|
|
|
#include "goalc/compiler/ConstantValue.h"
|
|
|
|
#include "common/util/BitUtils.h"
|
2020-09-12 13:11:42 -04:00
|
|
|
|
|
|
|
class StaticObject {
|
|
|
|
public:
|
|
|
|
virtual std::string print() const = 0;
|
|
|
|
|
|
|
|
struct LoadInfo {
|
|
|
|
bool requires_load = false;
|
|
|
|
int load_size = -1;
|
|
|
|
bool load_signed = false;
|
|
|
|
bool prefer_xmm = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual LoadInfo get_load_info() const = 0;
|
|
|
|
virtual void generate(emitter::ObjectGenerator* gen) = 0;
|
|
|
|
virtual int get_addr_offset() const = 0;
|
2020-12-02 19:51:42 -05:00
|
|
|
virtual ~StaticObject() = default;
|
2020-09-12 13:11:42 -04:00
|
|
|
|
|
|
|
emitter::StaticRecord rec;
|
|
|
|
};
|
|
|
|
|
2020-09-13 10:40:21 -04:00
|
|
|
class StaticFloat : public StaticObject {
|
|
|
|
public:
|
|
|
|
explicit StaticFloat(float _value, int _seg);
|
|
|
|
float value = 0;
|
|
|
|
int seg = -1;
|
|
|
|
std::string print() const override;
|
|
|
|
LoadInfo get_load_info() const override;
|
|
|
|
void generate(emitter::ObjectGenerator* gen) override;
|
|
|
|
int get_addr_offset() const override;
|
|
|
|
};
|
|
|
|
|
2020-10-16 17:08:26 -04:00
|
|
|
class StaticStructure : public StaticObject {
|
|
|
|
public:
|
|
|
|
StaticStructure(int _seg);
|
|
|
|
std::vector<u8> data;
|
|
|
|
int seg = -1;
|
|
|
|
std::string print() const override;
|
|
|
|
LoadInfo get_load_info() const override;
|
|
|
|
void generate_structure(emitter::ObjectGenerator* gen);
|
|
|
|
void generate(emitter::ObjectGenerator* gen) override;
|
|
|
|
int get_addr_offset() const override;
|
2021-02-25 22:49:46 -05:00
|
|
|
void set_offset(int offset) { m_offset = offset; }
|
2020-10-16 17:08:26 -04:00
|
|
|
|
|
|
|
struct SymbolRecord {
|
|
|
|
int offset = -1;
|
|
|
|
std::string name;
|
|
|
|
};
|
2020-12-19 15:21:29 -05:00
|
|
|
|
|
|
|
struct PointerRecord {
|
|
|
|
int offset_in_this = -1;
|
|
|
|
StaticStructure* dest = nullptr;
|
|
|
|
int offset_in_dest = -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<SymbolRecord> types;
|
2020-10-16 17:08:26 -04:00
|
|
|
std::vector<SymbolRecord> symbols;
|
2020-12-19 15:21:29 -05:00
|
|
|
std::vector<PointerRecord> pointers;
|
2020-10-16 17:08:26 -04:00
|
|
|
|
|
|
|
void add_symbol_record(std::string name, int offset);
|
2020-12-19 15:21:29 -05:00
|
|
|
void add_pointer_record(int offset_in_this, StaticStructure* dest, int offset_in_dest);
|
|
|
|
void add_type_record(std::string name, int offset);
|
2021-02-25 22:49:46 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
int m_offset = 0;
|
2020-10-16 17:08:26 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
class StaticBasic : public StaticStructure {
|
|
|
|
public:
|
|
|
|
std::string type_name;
|
|
|
|
StaticBasic(int _seg, std::string _type_name);
|
|
|
|
int get_addr_offset() const override;
|
2020-12-19 15:21:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
class StaticString : public StaticBasic {
|
|
|
|
public:
|
|
|
|
explicit StaticString(std::string data, int _seg);
|
|
|
|
std::string text;
|
|
|
|
std::string print() const override;
|
|
|
|
void generate(emitter::ObjectGenerator* gen) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Represents a "static value". Like a reference to a static structure (including pair, string,
|
|
|
|
* basic), a symbol, or some constant (bitfield, integer, float). Cannot be used to store a static
|
|
|
|
* structure itself, just a reference to one, meaning you cannot set an inlined structure to a
|
|
|
|
* StaticResult.
|
|
|
|
*/
|
|
|
|
class StaticResult {
|
|
|
|
public:
|
|
|
|
StaticResult() = default;
|
|
|
|
|
|
|
|
static StaticResult make_structure_reference(StaticStructure* structure, TypeSpec ts);
|
2021-05-18 21:25:29 -04:00
|
|
|
static StaticResult make_constant_data(const ConstantValue& data, TypeSpec ts);
|
|
|
|
static StaticResult make_constant_data(u64 data, const TypeSpec& ts);
|
2020-12-19 15:21:29 -05:00
|
|
|
static StaticResult make_symbol(const std::string& name);
|
2021-06-20 12:59:39 -04:00
|
|
|
static StaticResult make_type_ref(const std::string& type_name, int method_count);
|
2020-12-19 15:21:29 -05:00
|
|
|
|
|
|
|
const TypeSpec& typespec() const { return m_ts; }
|
|
|
|
bool is_reference() const { return m_kind == Kind::STRUCTURE_REFERENCE; }
|
|
|
|
bool is_constant_data() const { return m_kind == Kind::CONSTANT_DATA; }
|
|
|
|
bool is_symbol() const { return m_kind == Kind::SYMBOL; }
|
2021-06-20 12:59:39 -04:00
|
|
|
bool is_type() const { return m_kind == Kind::TYPE; }
|
2020-12-19 15:21:29 -05:00
|
|
|
|
|
|
|
StaticStructure* reference() const {
|
|
|
|
assert(is_reference());
|
|
|
|
return m_struct;
|
|
|
|
}
|
|
|
|
|
2021-05-18 21:25:29 -04:00
|
|
|
s32 constant_s32() const {
|
|
|
|
assert(is_constant_data() && m_constant_data && m_constant_data->size() == 8 &&
|
|
|
|
integer_fits(m_constant_data->value_64(), 4, true));
|
|
|
|
return (s32)m_constant_data->value_64();
|
2020-12-19 15:21:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& symbol_name() const {
|
2021-06-20 12:59:39 -04:00
|
|
|
assert(is_symbol() || is_type());
|
2020-12-19 15:21:29 -05:00
|
|
|
return m_symbol;
|
|
|
|
}
|
|
|
|
|
2021-06-20 12:59:39 -04:00
|
|
|
int method_count() const {
|
|
|
|
assert(is_type());
|
|
|
|
return m_method_count;
|
|
|
|
}
|
|
|
|
|
2021-05-18 21:25:29 -04:00
|
|
|
u64 constant_u64() const {
|
|
|
|
assert(is_constant_data() && m_constant_data && m_constant_data->size() == 8);
|
|
|
|
return m_constant_data->value_64();
|
|
|
|
}
|
|
|
|
|
|
|
|
const ConstantValue& constant() const {
|
|
|
|
assert(m_constant_data.has_value());
|
|
|
|
return *m_constant_data;
|
2020-12-19 15:21:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// used for all types
|
|
|
|
TypeSpec m_ts;
|
|
|
|
|
|
|
|
// used for only STRUCTURE_REFERENCE
|
|
|
|
StaticStructure* m_struct = nullptr;
|
|
|
|
|
|
|
|
// used for only constant data
|
2021-05-18 21:25:29 -04:00
|
|
|
std::optional<ConstantValue> m_constant_data;
|
2020-12-19 15:21:29 -05:00
|
|
|
|
2021-06-20 12:59:39 -04:00
|
|
|
// used for only symbol and type
|
2020-12-19 15:21:29 -05:00
|
|
|
std::string m_symbol;
|
|
|
|
|
2021-06-20 12:59:39 -04:00
|
|
|
// used only for type
|
|
|
|
int m_method_count = -1;
|
|
|
|
|
|
|
|
enum class Kind {
|
|
|
|
STRUCTURE_REFERENCE,
|
|
|
|
CONSTANT_DATA,
|
|
|
|
SYMBOL,
|
|
|
|
TYPE,
|
|
|
|
INVALID
|
|
|
|
} m_kind = Kind::INVALID;
|
2020-12-19 15:21:29 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
class StaticPair : public StaticStructure {
|
|
|
|
public:
|
|
|
|
StaticPair(StaticResult car, StaticResult cdr, int _seg);
|
|
|
|
int get_addr_offset() const override;
|
2020-10-16 17:08:26 -04:00
|
|
|
void generate(emitter::ObjectGenerator* gen) override;
|
2020-12-19 15:21:29 -05:00
|
|
|
void generate_item(const StaticResult& item, int offset);
|
|
|
|
|
|
|
|
private:
|
|
|
|
StaticResult m_car, m_cdr;
|
2020-10-16 17:08:26 -04:00
|
|
|
};
|