#pragma once #include "data.hpp" #include "embeddedlabel.hpp" #include "label.hpp" #include "node.hpp" #include "section.hpp" #include #include #include #include #include #include #include namespace zasm { namespace detail { struct ProgramState; } class Observer; class Program final { std::unique_ptr _state; public: Program(MachineMode mode); Program(const Program&) = delete; Program(Program&& other) noexcept; ~Program(); Program& operator=(const Program&) = delete; Program& operator=(Program&& other) noexcept; MachineMode getMode() const noexcept; /// /// This is primarily used by other components, this should not be directly used. /// detail::ProgramState& getState() const noexcept; /// /// Adds the observer to the program state, see the observer for the list of events. /// The same instance can be only registered once. /// /// The observer instance /// True if the observer was added bool addObserver(Observer& observer); /// /// Removes the observer instance from the program state. /// /// The observer instance /// True if the observer was removed bool removeObserver(Observer& observer) noexcept; public: /// /// Returns the first node in the Program, if none exists it will return null. /// const Node* getHead() const noexcept; /// /// Returns the last node in the Program, if none exists it will return null. /// const Node* getTail() const noexcept; /// /// Prepends the specified node to the start of the Program. /// /// The node to prepend /// The newly inserted node const Node* prepend(const Node* node) noexcept; /// /// Appends the specified node to the end of the Program. /// /// The node to append /// The newly inserted node const Node* append(const Node* node) noexcept; /// /// Inserts the node into the Program before the specified position. /// /// Position of insertion /// The node to insert /// The newly inserted node const Node* insertBefore(const Node* pos, const Node* node) noexcept; /// /// Inserts the node into the program after the specified position. /// /// Position of insertion /// The node to insert /// The newly inserted node const Node* insertAfter(const Node* pos, const Node* node) noexcept; /// /// Detaches the node from the program, the node will be not destroyed this just unlinks it from the /// program. /// /// The node to detach /// The next node /// Nodes that are detached are not tracked, make sure they don't get lost to avoid memory leaks const Node* detach(const Node* node) noexcept; /// /// Moves the node after the specified position, if the node is unlinked it will act as insert. /// /// Position of node to move after /// The node to move /// The moved node const Node* moveAfter(const Node* pos, const Node* node) noexcept; /// /// Moves the node before the specified position, if the node is unlinked it will act as insert. /// /// Position of node to move before /// The node to move /// The moved node const Node* moveBefore(const Node* pos, const Node* node) noexcept; /// /// Releases the memory of node back into the pool, the memory is considered invalid after the /// call. /// /// The node to destroy void destroy(const Node* node); /// /// Returns the current amount of nodes in the list. /// /// Node count std::size_t size() const noexcept; /// /// Clears the entire program state, pools will keep their /// capacity. /// void clear() noexcept; /// /// Sets the optional entry point. /// /// Entry Point void setEntryPoint(const Label& label); /// /// Gets the current set entry point. /// /// Label Label getEntryPoint() const noexcept; public: /// /// Allocates a new unlinked node with containing the specified value. /// /// The data to place inside the node /// Newly allocated node containing value const Node* createNode(const Instruction& instr); const Node* createNode(Instruction&& instr); const Node* createNode(const Data& data); const Node* createNode(Data&& data); const Node* createNode(const EmbeddedLabel& label); public: /// /// Creates a new label to be used for operands. /// The label should be bound with bindLabel to specify the position. /// /// Optional label name, pass null for none. /// Label Label createLabel(const char* name = nullptr); /// /// Binds the label to a new unlinked node. A label can be only bound once. /// /// The label to bind /// The new node which contains the label Expected bindLabel(const Label& label); /// /// Creates a new named external label that can be referenced and later /// patched by relocation items to modify the address. /// /// Optional label name, pass null for none. /// Label Label createExternalLabel(const char* name = nullptr); /// /// Returns if the specified label is an external label. /// /// Label to check /// True if label is external bool isLabelExternal(const Label& label) const noexcept; /// /// Gets or creates a new import label, this label can not be bound and is considered an external label. /// Import labels are unique per module name and import name so calling this twice with the same parameters /// returns the same label. /// This label provides a way to post-patch import addresses after serialization. /// /// Name of the module to import. /// Label Label getOrCreateImportLabel(const char* moduleName, const char* importName); /// /// Returns if the specified label is an import label. /// /// Label to check /// True if label is external bool isLabelImport(const Label& label) const noexcept; /// /// Returns a structure containing all the data stored for a label. /// /// The label to query the data for /// Returns LabelData on success, Error on failure. Expected getLabelData(const Label& label) const noexcept; public: /// /// Creates a new section that can be used to segment code and data. /// The section should be bound with bindSection to specify the position. /// /// The name of the new section /// One or multiple Section::Attribs /// Specifies the size the section is aligned to, this should be ideally one memory page. /// Section Section createSection(const char* name, Section::Attribs attribs, std::int32_t align); /// /// Binds the section to a new unlinked node. A section can be only bound once. /// /// The label to bind /// The new node which contains the section or Error Expected bindSection(const Section& section); /// /// Gets the section name. /// /// Section to set name for /// Name of the section, nullptr if invalid section const char* getSectionName(const Section& section) const noexcept; /// /// Sets the section name. /// /// Section to set name for /// The new name /// Error::None on success otherwise see Error Error setSectionName(const Section& section, const char* name); /// /// Gets the section alignment. /// /// Section to set align for /// The new alignment /// Section align, -1 if an invalid section was supplied. std::int32_t getSectionAlign(const Section& section) noexcept; /// /// Sets the section alignment. /// /// Section to set align for /// The new alignment /// Error::None on success otherwise see Error Error setSectionAlign(const Section& section, std::int32_t align) noexcept; }; } // namespace zasm