Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Terminal
ios-obj-log/*
build/*
obj/*
rm-win-r.sh
rm-win-r.sh
3 changes: 3 additions & 0 deletions compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ endif()

# Include common headers
target_include_directories(lmc PUBLIC ${CMAKE_SOURCE_DIR}/include)

# Link against runtime library
target_link_libraries(lmc lmvm)
10 changes: 7 additions & 3 deletions compiler/ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
//

#pragma once
#include <cstdint>
#include <memory>
#include <vector>
#include <string>
#include <unordered_map>

#include "../include/lmx_export.hpp"

Expand All @@ -23,7 +21,7 @@ namespace lmx {

enum ASTKind {
Program,
Binary, Unary, NumLiteral, StringLiteral, BoolLiteral,
Binary, Unary, NumLiteral, StringLiteral, BoolLiteral, VectorLiteral,
BlockStmt,
IfStmt,
VarDecl,
Expand Down Expand Up @@ -219,6 +217,12 @@ struct StringNode final : public ExprNode {
~StringNode() override = default;
};

struct VectorNode final : public ExprNode {
std::vector<std::shared_ptr<ExprNode>> elements;
explicit VectorNode(std::vector<std::shared_ptr<ExprNode>> elems)
: ExprNode(ASTKind::VectorLiteral), elements(std::move(elems)){}
};

struct BinaryNode final : public ExprNode {
std::shared_ptr<ASTNode> left;
std::shared_ptr<ASTNode> right;
Expand Down
8 changes: 5 additions & 3 deletions compiler/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <fstream>
#include <iostream>

#include "../include/error.hpp"

#include "parser.hpp"

namespace lmx {
Expand All @@ -23,18 +25,18 @@ namespace lmx {
inline std::string read_file(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
std::cerr << "Failed to open file " << path << std::endl;
LM_ERROR("Failed to open file " + path);
return {};
}
return std::string(std::istreambuf_iterator<char>{file}, std::istreambuf_iterator<char>{});
return {std::istreambuf_iterator{file}, std::istreambuf_iterator<char>{}};
}
inline std::shared_ptr<ASTNode> compile(const std::string &path) {
std::string code = read_file(path);
if (code.empty()) return nullptr;
Lexer lexer(code);
auto tks = lexer.tokenize(code);

Parser parser(tks);
Parser parser(tks, code, path);
if (auto node = parser.parse_program(); node && !parser.error()) return node;
return nullptr;
}
Expand Down
102 changes: 96 additions & 6 deletions compiler/generator/emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <chrono>
#include <cstring>

#include "debug.hpp"

namespace lmx {
LMXOpcodeEmitter::Ret_Type LMXOpcodeEmitter::ret_type = None;
template<class T>
Expand All @@ -32,12 +34,39 @@ void LMXOpcodeEmitter::emit_mov_ri(std::vector<lmx::runtime::Op> &ops, uint8_t r
void LMXOpcodeEmitter::emit_mov_rr(std::vector<lmx::runtime::Op> &ops, uint8_t r1, uint8_t r2) {

if (r1 == r2) return;
if (ret_type == Reg) {
// 如果上一条指令的 目标寄存器 与本条指令的 源寄存器 相同
// 不生成新指令, 修改上条指令目标为本条目标
if (auto& last = ops.back(); last.operands[0] == r2) {
last.operands[0] = r1;
return;
if (ret_type == Reg && !ops.empty()) {
const auto& last_op = ops.back();
bool is_reg_return_op = false;
switch (last_op.op) {
case lmx::runtime::Opcode::MOV_RI:
case lmx::runtime::Opcode::MOV_RR:
case lmx::runtime::Opcode::MOV_RC:
case lmx::runtime::Opcode::ADD:
case lmx::runtime::Opcode::SUB:
case lmx::runtime::Opcode::MUL:
case lmx::runtime::Opcode::DIV:
case lmx::runtime::Opcode::MOD:
case lmx::runtime::Opcode::POW:
case lmx::runtime::Opcode::CMP_GE:
case lmx::runtime::Opcode::CMP_LT:
case lmx::runtime::Opcode::CMP_LE:
case lmx::runtime::Opcode::CMP_GT:
case lmx::runtime::Opcode::CMP_EQ:
case lmx::runtime::Opcode::CMP_NE:
case lmx::runtime::Opcode::AND:
case lmx::runtime::Opcode::OR:
case lmx::runtime::Opcode::LOCAL_GET:
is_reg_return_op = true;
break;
default:
is_reg_return_op = false;
break;
}
if (is_reg_return_op) {
if (last_op.operands[0] == r2) {
ops.back().operands[0] = r1;
return;
}
}
}
lmx::runtime::Op op(lmx::runtime::Opcode::MOV_RR);
Expand Down Expand Up @@ -257,6 +286,67 @@ void LMXOpcodeEmitter::emit_dec(std::vector<lmx::runtime::Op> &ops, uint8_t r) {
ops.push_back(op);
}

void LMXOpcodeEmitter::emit_mov_rm(std::vector<lmx::runtime::Op> &ops, uint8_t r1, uint8_t r2, int8_t offest) {
runtime::Op op(runtime::Opcode::MOV_RM);
op.operands[0] = r1;
op.operands[1] = r2;
op.operands[2] = static_cast<uint8_t>(offest);
ops.push_back(op);
ret_type = Reg;
}

void LMXOpcodeEmitter::emit_mov_mi(std::vector<lmx::runtime::Op> &ops, uint8_t r1, int8_t offest1, int64_t imm) {
runtime::Op op(runtime::Opcode::MOV_MI);
op.operands[0] = r1;
op.operands[1] = static_cast<uint8_t>(offest1);
write_imm(op.operands + 2, imm);
ops.push_back(op);
ret_type = None;
}

void LMXOpcodeEmitter::emit_mov_mr(std::vector<lmx::runtime::Op> &ops, uint8_t r1, int8_t offest1, uint8_t r2) {
runtime::Op op(runtime::Opcode::MOV_MR);
op.operands[0] = r1;
op.operands[1] = static_cast<uint8_t>(offest1);
op.operands[2] = r2;
ops.push_back(op);
ret_type = None;
}

void LMXOpcodeEmitter::emit_mov_mm(std::vector<lmx::runtime::Op> &ops, uint8_t r1, int8_t offest1, uint8_t r2, int8_t offest2) {
runtime::Op op(runtime::Opcode::MOV_MM);
op.operands[0] = r1;
op.operands[1] = static_cast<uint8_t>(offest1);
op.operands[2] = r2;
op.operands[3] = static_cast<uint8_t>(offest2);
ops.push_back(op);
ret_type = None;
}

void LMXOpcodeEmitter::emit_mov_mc(std::vector<lmx::runtime::Op> &ops, uint8_t r1, int8_t offest1, uint64_t idx) {
runtime::Op op(runtime::Opcode::MOV_MC);
op.operands[0] = r1;
op.operands[1] = static_cast<uint8_t>(offest1);
write_imm(op.operands + 2, std::bit_cast<int64_t>(idx));
ops.push_back(op);
ret_type = None;
}

void LMXOpcodeEmitter::emit_push(std::vector<lmx::runtime::Op>& ops, uint8_t reg) {
runtime::Op op(runtime::Opcode::PUSH);
op.operands[0] = reg;
ops.push_back(op);
ret_type = None;
}

void LMXOpcodeEmitter::emit_create_vector(std::vector<lmx::runtime::Op>& ops, uint8_t rd, uint8_t count) {
runtime::Op op(runtime::Opcode::CREATE_VECTOR);
op.operands[0] = rd;
op.operands[1] = count;
ops.push_back(op);
ret_type = Reg;
}

#undef getter_opt_code
} // namespace lmx

Expand Down
4 changes: 4 additions & 0 deletions compiler/generator/emit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class LMC_API LMXOpcodeEmitter {
static void emit_or(std::vector<lmx::runtime::Op> &ops, uint8_t r1, uint8_t r2, uint8_t r3);

static void emit_vmc(std::vector<lmx::runtime::Op> &ops, uint16_t idx);

static void emit_push(std::vector<lmx::runtime::Op>& ops, uint8_t reg);

static void emit_create_vector(std::vector<lmx::runtime::Op>& ops, uint8_t rd, uint8_t count);
};

} // namespace lmx
Loading
Loading