Print test summary
This commit is contained in:
95
include/elna/ir.hpp
Normal file
95
include/elna/ir.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include "elna/parser.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace elna::ir
|
||||
{
|
||||
class Node;
|
||||
class Definition;
|
||||
class Operand;
|
||||
class BinaryExpression;
|
||||
class Variable;
|
||||
class VariableDeclaration;
|
||||
class Number;
|
||||
|
||||
struct IRVisitor
|
||||
{
|
||||
virtual void visit(Node *) = 0;
|
||||
virtual void visit(Definition *) = 0;
|
||||
virtual void visit(Operand *) = 0;
|
||||
virtual void visit(BinaryExpression *) = 0;
|
||||
virtual void visit(Variable *) = 0;
|
||||
virtual void visit(Number *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* AST node.
|
||||
*/
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
virtual void accept(IRVisitor *) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Definition.
|
||||
*/
|
||||
class Definition : public Node
|
||||
{
|
||||
public:
|
||||
BinaryExpression **statements;
|
||||
std::size_t statementsLength;
|
||||
Operand *result;
|
||||
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Statement : public Node
|
||||
{
|
||||
};
|
||||
|
||||
class Operand : public Node
|
||||
{
|
||||
public:
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Number : public Operand
|
||||
{
|
||||
public:
|
||||
std::int32_t value;
|
||||
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class Variable : public Operand
|
||||
{
|
||||
public:
|
||||
std::size_t counter;
|
||||
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class BinaryExpression : public Statement
|
||||
{
|
||||
public:
|
||||
Operand *lhs, *rhs;
|
||||
BinaryOperator _operator;
|
||||
|
||||
BinaryExpression(Operand *lhs, Operand *rhs, BinaryOperator _operator);
|
||||
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
|
||||
class BangExpression : public Statement
|
||||
{
|
||||
Operand *operand;
|
||||
|
||||
public:
|
||||
BangExpression(Operand *operand);
|
||||
|
||||
virtual void accept(IRVisitor *visitor) override;
|
||||
};
|
||||
}
|
@ -14,10 +14,10 @@ namespace elna
|
||||
class const_iterator
|
||||
{
|
||||
std::string::const_iterator m_buffer;
|
||||
source_position m_position;
|
||||
Position m_position;
|
||||
|
||||
const_iterator(std::string::const_iterator buffer,
|
||||
const source_position position = source_position());
|
||||
const Position position = Position());
|
||||
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
@ -26,7 +26,7 @@ namespace elna
|
||||
using pointer = const value_type *;
|
||||
using reference = const value_type&;
|
||||
|
||||
const source_position& position() const noexcept;
|
||||
const Position& position() const noexcept;
|
||||
|
||||
reference operator*() const noexcept;
|
||||
pointer operator->() const noexcept;
|
||||
@ -43,38 +43,61 @@ namespace elna
|
||||
const_iterator end() const;
|
||||
|
||||
private:
|
||||
const std::string& m_buffer;
|
||||
const std::string m_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Union type representing a single token.
|
||||
*/
|
||||
struct token
|
||||
struct Token
|
||||
{
|
||||
/**
|
||||
* Token type.
|
||||
*/
|
||||
enum class type
|
||||
enum Type : std::uint16_t
|
||||
{
|
||||
word,
|
||||
TOKEN_NUMBER = 0,
|
||||
TOKEN_OPERATOR = 1,
|
||||
TOKEN_LET = 2,
|
||||
TOKEN_IDENTIFIER = 3,
|
||||
TOKEN_EQUALS = 4,
|
||||
TOKEN_VAR = 5,
|
||||
TOKEN_SEMICOLON = 6,
|
||||
TOKEN_LEFT_PAREN = 7,
|
||||
TOKEN_RIGHT_PAREN = 8,
|
||||
TOKEN_BANG = 9,
|
||||
TOKEN_DOT = 10,
|
||||
TOKEN_COMMA = 11,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Type of the token value.
|
||||
*/
|
||||
using value = std::string;
|
||||
union Value
|
||||
{
|
||||
std::int32_t number;
|
||||
const char *identifier;
|
||||
};
|
||||
|
||||
token(const type of, source::const_iterator begin, source::const_iterator end);
|
||||
Token(Type of, Position position);
|
||||
Token(Type of, std::int32_t value, Position position);
|
||||
Token(Type of, const char *value, Position position);
|
||||
Token(const Token& that);
|
||||
Token(Token&& that);
|
||||
~Token();
|
||||
|
||||
type of() const noexcept;
|
||||
const value& identifier() const noexcept;
|
||||
const source_position& position() const noexcept;
|
||||
Token& operator=(const Token& that);
|
||||
Token& operator=(Token&& that);
|
||||
|
||||
Type of() const noexcept;
|
||||
const char *identifier() const noexcept;
|
||||
std::int32_t number() const noexcept;
|
||||
const Position& position() const noexcept;
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
source_position m_position;
|
||||
type m_type;
|
||||
Type m_type;
|
||||
Value m_value;
|
||||
Position m_position;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -82,5 +105,5 @@ namespace elna
|
||||
*
|
||||
* \return Tokens or error.
|
||||
*/
|
||||
result<std::vector<token>> lex(const std::string& buffer);
|
||||
Token *lex(const char *buffer, CompileError *compile_error, std::size_t *length);
|
||||
}
|
||||
|
10
include/elna/parser.hpp
Normal file
10
include/elna/parser.hpp
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace elna
|
||||
{
|
||||
enum class BinaryOperator
|
||||
{
|
||||
sum,
|
||||
subtraction
|
||||
};
|
||||
}
|
@ -8,7 +8,7 @@ namespace elna
|
||||
/**
|
||||
* Position in the source text.
|
||||
*/
|
||||
struct source_position
|
||||
struct Position
|
||||
{
|
||||
/// Line.
|
||||
std::size_t line = 1;
|
||||
@ -20,18 +20,18 @@ namespace elna
|
||||
/**
|
||||
* A compilation error consists of an error message and position.
|
||||
*/
|
||||
struct compile_error
|
||||
struct CompileError
|
||||
{
|
||||
private:
|
||||
char const *message;
|
||||
source_position position;
|
||||
Position position;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param message Error text.
|
||||
* @param position Error position in the source text.
|
||||
*/
|
||||
compile_error(char const *message, const source_position position) noexcept;
|
||||
CompileError(char const *message, const Position position) noexcept;
|
||||
|
||||
/// Error text.
|
||||
const char *what() const noexcept;
|
||||
@ -44,5 +44,19 @@ namespace elna
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using result = boost::outcome_v2::result<T, compile_error>;
|
||||
using result = boost::outcome_v2::result<T, CompileError>;
|
||||
|
||||
enum class Target
|
||||
{
|
||||
text,
|
||||
high20,
|
||||
lower12i
|
||||
};
|
||||
|
||||
struct Reference
|
||||
{
|
||||
const char* name;
|
||||
size_t offset;
|
||||
Target target;
|
||||
};
|
||||
}
|
||||
|
148
include/elna/riscv.hpp
Normal file
148
include/elna/riscv.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "elna/ir.hpp"
|
||||
#include "elna/result.hpp"
|
||||
|
||||
namespace elna
|
||||
{
|
||||
enum class XRegister : std::uint8_t
|
||||
{
|
||||
zero = 0,
|
||||
ra = 1,
|
||||
sp = 2,
|
||||
gp = 3,
|
||||
tp = 4,
|
||||
t0 = 5,
|
||||
t1 = 6,
|
||||
t2 = 7,
|
||||
s0 = 8,
|
||||
s1 = 9,
|
||||
a0 = 10,
|
||||
a1 = 11,
|
||||
a2 = 12,
|
||||
a3 = 13,
|
||||
a4 = 14,
|
||||
a5 = 15,
|
||||
a6 = 16,
|
||||
a7 = 17,
|
||||
s2 = 18,
|
||||
s3 = 19,
|
||||
s4 = 20,
|
||||
s5 = 21,
|
||||
s6 = 22,
|
||||
s7 = 23,
|
||||
s8 = 24,
|
||||
s9 = 25,
|
||||
s10 = 26,
|
||||
s11 = 27,
|
||||
t3 = 28,
|
||||
t4 = 29,
|
||||
t5 = 30,
|
||||
t6 = 31,
|
||||
};
|
||||
|
||||
enum class Funct3 : std::uint8_t
|
||||
{
|
||||
addi = 0b000,
|
||||
slti = 0b001,
|
||||
sltiu = 0b011,
|
||||
andi = 0b111,
|
||||
ori = 0b110,
|
||||
xori = 0b100,
|
||||
slli = 0b000,
|
||||
srli = 0b101,
|
||||
srai = 0b101,
|
||||
add = 0b000,
|
||||
slt = 0b010,
|
||||
sltu = 0b011,
|
||||
_and = 0b111,
|
||||
_or = 0b110,
|
||||
_xor = 0b100,
|
||||
sll = 0b001,
|
||||
srl = 0b101,
|
||||
sub = 0b000,
|
||||
sra = 0b101,
|
||||
beq = 0b000,
|
||||
bne = 0b001,
|
||||
blt = 0b100,
|
||||
bltu = 0b110,
|
||||
bge = 0b101,
|
||||
bgeu = 0b111,
|
||||
fence = 0b000,
|
||||
fenceI = 0b001,
|
||||
csrrw = 0b001,
|
||||
csrrs = 0b010,
|
||||
csrrc = 0b011,
|
||||
csrrwi = 0b101,
|
||||
csrrsi = 0b110,
|
||||
csrrci = 0b111,
|
||||
priv = 0b000,
|
||||
sb = 0b000,
|
||||
sh = 0b001,
|
||||
sw = 0b010,
|
||||
lb = 0b000,
|
||||
lh = 0b001,
|
||||
lw = 0b010,
|
||||
lbu = 0b100,
|
||||
lhu = 0b101,
|
||||
jalr = 0b000,
|
||||
};
|
||||
|
||||
enum class Funct12 : std::uint8_t
|
||||
{
|
||||
ecall = 0b000000000000,
|
||||
ebreak = 0b000000000001,
|
||||
};
|
||||
|
||||
enum class Funct7 : std::uint8_t
|
||||
{
|
||||
none = 0,
|
||||
sub = 0b0100000
|
||||
};
|
||||
|
||||
enum class BaseOpcode : std::uint8_t
|
||||
{
|
||||
opImm = 0b0010011,
|
||||
lui = 0b0110111,
|
||||
auipc = 0b0010111,
|
||||
op = 0b0110011,
|
||||
jal = 0b1101111,
|
||||
jalr = 0b1100111,
|
||||
branch = 0b1100011,
|
||||
load = 0b0000011,
|
||||
store = 0b0100011,
|
||||
miscMem = 0b0001111,
|
||||
system = 0b1110011,
|
||||
};
|
||||
|
||||
struct Instruction
|
||||
{
|
||||
Instruction(BaseOpcode opcode);
|
||||
|
||||
Instruction& i(XRegister rd, Funct3 funct3, XRegister rs1, std::uint32_t immediate);
|
||||
Instruction& s(std::uint32_t imm1, Funct3 funct3, XRegister rs1, XRegister rs2);
|
||||
Instruction& r(XRegister rd, Funct3 funct3, XRegister rs1, XRegister rs2, Funct7 funct7 = Funct7::none);
|
||||
Instruction& u(XRegister rd, std::uint32_t imm);
|
||||
std::uint8_t *encode();
|
||||
|
||||
private:
|
||||
std::uint32_t instruction{ 0 };
|
||||
};
|
||||
|
||||
class RiscVVisitor : public ir::IRVisitor
|
||||
{
|
||||
Instruction *instructions;
|
||||
std::size_t instructionsLength;
|
||||
bool registerInUse;
|
||||
std::uint32_t variableCounter = 1;
|
||||
Reference references[3];
|
||||
|
||||
virtual void visit(ir::Node *) override;
|
||||
virtual void visit(ir::Definition *definition) override;
|
||||
virtual void visit(ir::Operand *operand) override;
|
||||
virtual void visit(ir::Variable *variable) override;
|
||||
virtual void visit(ir::Number *number) override;
|
||||
virtual void visit(ir::BinaryExpression *expression) override;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user