108 lines
3.6 KiB
C++
108 lines
3.6 KiB
C++
#pragma once
|
|
|
|
#include "elna/source/parser.hpp"
|
|
#include "elna/source/optimizer.hpp"
|
|
#include <filesystem>
|
|
#include <elfio/elfio.hpp>
|
|
|
|
namespace elna::riscv
|
|
{
|
|
/**
|
|
* Writer to a single label.
|
|
*/
|
|
struct elfio_section_writer
|
|
{
|
|
struct entry
|
|
{
|
|
std::string_view label;
|
|
const std::byte *data{ nullptr };
|
|
std::size_t size{ 0 };
|
|
};
|
|
|
|
/**
|
|
* An iterator over label and string pairs.
|
|
*/
|
|
struct iterator
|
|
{
|
|
using iterator_category = std::forward_iterator_tag;
|
|
using difference_type = ptrdiff_t;
|
|
using value_type = entry;
|
|
using pointer = const value_type *;
|
|
using reference = const value_type&;
|
|
|
|
reference operator*() const noexcept;
|
|
pointer operator->() const noexcept;
|
|
iterator& operator++();
|
|
iterator& operator++(int);
|
|
bool operator==(const iterator& that) const;
|
|
bool operator!=(const iterator& that) const;
|
|
|
|
private:
|
|
std::vector<std::string>::const_iterator labels;
|
|
std::vector<std::size_t>::const_iterator sizes;
|
|
value_type payload;
|
|
|
|
iterator(std::vector<std::string>::const_iterator labels, std::vector<std::size_t>::const_iterator sizes,
|
|
const std::byte *data)
|
|
: labels(labels), sizes(sizes)
|
|
{
|
|
if (data != nullptr)
|
|
{
|
|
payload = { *this->labels, data, *this->sizes};
|
|
}
|
|
}
|
|
|
|
iterator(std::vector<std::string>::const_iterator labels, std::vector<std::size_t>::const_iterator sizes)
|
|
: labels(labels), sizes(sizes), payload{}
|
|
{
|
|
}
|
|
|
|
friend elfio_section_writer;
|
|
};
|
|
explicit elfio_section_writer(ELFIO::section *section);
|
|
|
|
void operator()(const std::string& label, const std::byte *data, std::size_t size);
|
|
std::pair<std::string_view, bool> operator()(const std::byte *data, std::size_t size);
|
|
|
|
iterator begin() const;
|
|
iterator end() const;
|
|
|
|
ELFIO::section *section() noexcept;
|
|
|
|
private:
|
|
std::vector<std::string> labels;
|
|
std::vector<std::size_t> sizes;
|
|
ELFIO::section *m_section;
|
|
};
|
|
|
|
class elfio_writer final : public source::writer<std::byte>
|
|
{
|
|
ELFIO::section *text;
|
|
elfio_section_writer read_only;
|
|
ELFIO::symbol_section_accessor symbol_accessor;
|
|
ELFIO::string_section_accessor string_accessor;
|
|
|
|
public:
|
|
elfio_writer(ELFIO::section *text, ELFIO::section *read_only, ELFIO::symbol_section_accessor symbol_accessor,
|
|
ELFIO::string_section_accessor string_accessor);
|
|
|
|
std::size_t sink(const std::string& label, const std::byte *data, std::size_t size) override;
|
|
std::string_view sink(const std::byte *data, std::size_t size) override;
|
|
void sink(const std::string& label) override;
|
|
std::size_t size() const override;
|
|
};
|
|
|
|
/**
|
|
* Searches the content by label and returns its index or -1 when the
|
|
* label does not exist.
|
|
*
|
|
* \param symbol_accessor Object accessor.
|
|
* \param needle Label name.
|
|
* \return Data index.
|
|
*/
|
|
std::ptrdiff_t lookup(ELFIO::symbol_section_accessor symbol_accessor, const std::string& label);
|
|
|
|
void riscv32_elf(source::program *ast, source::intermediate_code_generator intermediate_code_generator,
|
|
std::shared_ptr<source::symbol_table> table, const std::filesystem::path& out_file);
|
|
}
|