feat: first prototype of optimizers + alloca optimizer
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
build/
|
build/
|
||||||
|
.cache/
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
|
||||||
project(pl VERSION 0.0.1 LANGUAGES C CXX)
|
project(pl VERSION 0.0.1 LANGUAGES C CXX)
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include "parser/nodes.hpp"
|
||||||
#include "prelude/string.hpp"
|
#include "prelude/string.hpp"
|
||||||
#include "parser/ast.hpp"
|
|
||||||
#include "ir/value.hpp"
|
#include "ir/value.hpp"
|
||||||
#include "ir/ops.hpp"
|
#include "ir/ops.hpp"
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ namespace IR
|
|||||||
{
|
{
|
||||||
auto value = ParseExpression(varDecl->value());
|
auto value = ParseExpression(varDecl->value());
|
||||||
// TODO: gather type information from var decl signature, aka local <int> v = 0;
|
// TODO: gather type information from var decl signature, aka local <int> v = 0;
|
||||||
auto dst = AllocateNamed<Pointer>();
|
auto dst = AllocateNamed<Pointer>(value->GetType());
|
||||||
m_ops->Push(new AllocateOp(dst, value->GetType()));
|
m_ops->Push(new AllocateOp(dst, value->GetType()));
|
||||||
m_ops->Push(new StoreOp(value, reinterpret_cast<Pointer *>(dst)));
|
m_ops->Push(new StoreOp(value, reinterpret_cast<Pointer *>(dst)));
|
||||||
m_locals.insert(std::make_pair(varDecl->name(), reinterpret_cast<Pointer *>(dst)));
|
m_locals.insert(std::make_pair(varDecl->name(), reinterpret_cast<Pointer *>(dst)));
|
||||||
@@ -34,14 +34,14 @@ namespace IR
|
|||||||
|
|
||||||
ValueHandle *ParseVariable(const VariableNode *var)
|
ValueHandle *ParseVariable(const VariableNode *var)
|
||||||
{
|
{
|
||||||
// auto dst = AllocateValue();
|
|
||||||
// m_ops->Push(new LoadOp(dst, var->name()));
|
|
||||||
if (m_locals.find(var->name()) == m_locals.end())
|
if (m_locals.find(var->name()) == m_locals.end())
|
||||||
{
|
{
|
||||||
// TODO: throw proper error
|
// TODO: throw proper error
|
||||||
assert(0 && "ERROR: variable does not exist");
|
assert(0 && "ERROR: variable does not exist");
|
||||||
}
|
}
|
||||||
return reinterpret_cast<ValueHandle *>(m_locals[var->name()]);
|
auto dst = AllocateNamed<Instruction>(m_locals[var->name()]->GetValueType());
|
||||||
|
m_ops->Push(new LoadOp(dst, m_locals[var->name()]));
|
||||||
|
return reinterpret_cast<ValueHandle *>(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueHandle *ParseFnCall(const FnCallNode *fn)
|
ValueHandle *ParseFnCall(const FnCallNode *fn)
|
||||||
@@ -54,7 +54,7 @@ namespace IR
|
|||||||
argRegs.Push(arg);
|
argRegs.Push(arg);
|
||||||
}
|
}
|
||||||
// TODO: gather return type of the function
|
// TODO: gather return type of the function
|
||||||
auto dst = AllocateUnnamed<Void>();
|
auto dst = VoidValue();
|
||||||
m_ops->Push(new CallOp(dst, fn->name(), argRegs.view()));
|
m_ops->Push(new CallOp(dst, fn->name(), argRegs.view()));
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ namespace IR
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(0 && "unreachable");
|
assert(0 && "unreachable");
|
||||||
return reinterpret_cast<ValueHandle *>(new Void(0));
|
return reinterpret_cast<ValueHandle *>(new Void());
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueHandle *ParseExpression(const Node *expression)
|
ValueHandle *ParseExpression(const Node *expression)
|
||||||
@@ -187,12 +187,18 @@ namespace IR
|
|||||||
return new V(ValueHandle::kNoId, std::forward<Args>(args)...);
|
return new V(ValueHandle::kNoId, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ValueHandle *VoidValue()
|
||||||
|
{
|
||||||
|
return new Void();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Node *m_root = nullptr;
|
const Node *m_root = nullptr;
|
||||||
|
|
||||||
OpBuilder *m_ops = nullptr;
|
OpBuilder *m_ops = nullptr;
|
||||||
unsigned int m_value_counter = 0;
|
unsigned int m_value_counter = 0;
|
||||||
unsigned int m_block_counter = 0;
|
unsigned int m_block_counter = 0;
|
||||||
|
|
||||||
std::unordered_map<StringView, Pointer *> m_locals;
|
std::unordered_map<StringView, Pointer *> m_locals;
|
||||||
|
|
||||||
Builder<OpBuilder *> m_containers;
|
Builder<OpBuilder *> m_containers;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "prelude/string.hpp"
|
#include "prelude/string.hpp"
|
||||||
#include "parser/nodes.hpp"
|
|
||||||
#include "ir/value.hpp"
|
#include "ir/value.hpp"
|
||||||
#include "ir/op.hpp"
|
#include "ir/op.hpp"
|
||||||
#include "ir/block.hpp"
|
#include "ir/block.hpp"
|
||||||
@@ -21,7 +20,7 @@ namespace IR
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "EXTRN " << m_symbol.c_str();
|
sb << "extern " << m_symbol.c_str();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ namespace IR
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "LABEL " << m_name.c_str() << ':' << '\n';
|
sb << "label " << m_name.c_str() << ':' << '\n';
|
||||||
sb << m_body.Format(indent);
|
sb << m_body.Format(indent);
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
@@ -79,7 +78,7 @@ namespace IR
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << result()->Format() << " = ALLOCATE " << m_typ->Format();
|
sb << result()->Format() << " = allocate " << m_typ->Format();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +89,8 @@ namespace IR
|
|||||||
class LoadOp : public OpValued
|
class LoadOp : public OpValued
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LoadOp(ValueHandle *dest, StringView addr)
|
LoadOp(ValueHandle *dest, Pointer *ptr)
|
||||||
: OpValued(dest), m_addr(addr) {}
|
: OpValued(dest), m_ptr(ptr) {}
|
||||||
~LoadOp() {}
|
~LoadOp() {}
|
||||||
|
|
||||||
OP_TYPE(LOAD)
|
OP_TYPE(LOAD)
|
||||||
@@ -100,15 +99,12 @@ namespace IR
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << result()->Format() << " = LOAD \"" << m_addr.c_str() << "\"";
|
sb << result()->Format() << " = load " << m_ptr->Format();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
const StringView &addr() const { return m_addr; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringView m_addr;
|
Pointer* m_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StoreOp : public Op
|
class StoreOp : public Op
|
||||||
@@ -124,7 +120,7 @@ namespace IR
|
|||||||
{
|
{
|
||||||
StringBuilder sb;
|
StringBuilder sb;
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "STORE " << src()->Format() << ", " << dst()->Format();
|
sb << "store " << src()->Format() << ", " << dst()->Format();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,13 +148,14 @@ namespace IR
|
|||||||
switch (m_typ)
|
switch (m_typ)
|
||||||
{
|
{
|
||||||
case OpType::ADD:
|
case OpType::ADD:
|
||||||
return StringView("ADD");
|
return StringView("add");
|
||||||
case OpType::MUL:
|
case OpType::MUL:
|
||||||
return StringView("MUL");
|
return StringView("mul");
|
||||||
case OpType::SUB:
|
case OpType::SUB:
|
||||||
return StringView("SUB");
|
return StringView("sub");
|
||||||
case OpType::DIV:
|
case OpType::DIV:
|
||||||
return StringView("DIV");
|
return StringView("div");
|
||||||
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false && "unreachable");
|
assert(false && "unreachable");
|
||||||
@@ -198,10 +195,10 @@ namespace IR
|
|||||||
for (size_t i = 0; i < m_args.size; ++i)
|
for (size_t i = 0; i < m_args.size; ++i)
|
||||||
{
|
{
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << "PARAM " << m_args.data[i]->Format() << '\n';
|
sb << "param " << m_args.data[i]->Format() << '\n';
|
||||||
}
|
}
|
||||||
sb.AppendIndent(indent);
|
sb.AppendIndent(indent);
|
||||||
sb << result()->Format() << " = CALL " << m_callee.c_str();
|
sb << result()->Format() << " = call " << m_callee.c_str();
|
||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
include/ir/optimize.hpp
Normal file
34
include/ir/optimize.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ir/op.hpp"
|
||||||
|
#include "prelude/linkedlist.hpp"
|
||||||
|
|
||||||
|
namespace IR {
|
||||||
|
|
||||||
|
class Optimizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool Apply(DoubleLinkedList<Op*>& ops) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AllocOptimizer : public Optimizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool Apply(DoubleLinkedList<Op*>& ops) override
|
||||||
|
{
|
||||||
|
for (ListNode<Op*>* cur = ops.Begin(); cur != nullptr; )
|
||||||
|
{
|
||||||
|
auto op = cur->value;
|
||||||
|
if (op->GetType() == OpType::ALLOCATE)
|
||||||
|
{
|
||||||
|
auto tmp = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
ops.SpliceFront(tmp);
|
||||||
|
} else {
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
#include "prelude/string.hpp"
|
#include "prelude/string.hpp"
|
||||||
|
|
||||||
namespace IR
|
namespace IR
|
||||||
@@ -104,8 +105,8 @@ namespace IR
|
|||||||
class Pointer : public ValueHandle
|
class Pointer : public ValueHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Pointer(unsigned int id)
|
Pointer(unsigned int id, const Type* value_typ)
|
||||||
: ValueHandle(id)
|
: ValueHandle(id), m_value_typ(new Type(value_typ))
|
||||||
{
|
{
|
||||||
m_type = new Type{Type::Kind::Ptr};
|
m_type = new Type{Type::Kind::Ptr};
|
||||||
}
|
}
|
||||||
@@ -120,16 +121,19 @@ namespace IR
|
|||||||
return sb.view();
|
return sb.view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Type *GetValueType() const { return m_value_typ; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type *m_type;
|
Type *m_type;
|
||||||
|
Type *m_value_typ;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Remove void value and use void type only
|
|
||||||
class Void : public ValueHandle
|
class Void : public ValueHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Void(unsigned int id)
|
Void()
|
||||||
: ValueHandle(id)
|
: ValueHandle()
|
||||||
{
|
{
|
||||||
m_type = new Type{Type::Kind::Void};
|
m_type = new Type{Type::Kind::Void};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
|
||||||
#include "parser/lexer.hpp"
|
#include "parser/lexer.hpp"
|
||||||
#include "parser/nodes.hpp"
|
#include "parser/nodes.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
|
|||||||
79
include/prelude/file.hpp
Normal file
79
include/prelude/file.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "prelude/string.hpp"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Mode
|
||||||
|
{
|
||||||
|
WRITE,
|
||||||
|
READ,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
File(FILE* handle, Mode mode)
|
||||||
|
: m_handle(handle), m_mode(mode) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static File Open(const StringView& filename, Mode mode)
|
||||||
|
{
|
||||||
|
StringBuilder sb;
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case Mode::WRITE:
|
||||||
|
sb.Append('w');
|
||||||
|
break;
|
||||||
|
case Mode::READ:
|
||||||
|
sb.Append('r');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FILE* handle = fopen(filename.c_str(), sb.c_str());
|
||||||
|
return File(handle, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool Writable() const { return m_mode == File::Mode::WRITE; }
|
||||||
|
inline bool Readable() const { return m_mode == File::Mode::READ; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool Write(const StringView& content)
|
||||||
|
{
|
||||||
|
assert(Writable() && "attempt to write to a file in read only mode");
|
||||||
|
if (fwrite(content.c_str(), sizeof(char), content.size - 1, m_handle) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
StringView ReadAll(bool* status = nullptr)
|
||||||
|
{
|
||||||
|
auto fail = [&]() -> StringView {
|
||||||
|
if (status) *status = false;
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
if (status) *status = true;
|
||||||
|
|
||||||
|
assert(Readable() && "attempt to read from a file in write only mode");
|
||||||
|
if (fseek(m_handle, 0, SEEK_END) != 0) return fail();
|
||||||
|
|
||||||
|
auto size = ftell(m_handle);
|
||||||
|
if (size == -1 && status) return fail();
|
||||||
|
|
||||||
|
StringBuilder sb;
|
||||||
|
sb.ensure_extra(size);
|
||||||
|
|
||||||
|
size_t wrote = fread(sb.data, sizeof(char), size, m_handle);
|
||||||
|
if (wrote == 0) return fail();
|
||||||
|
|
||||||
|
sb.size = wrote;
|
||||||
|
return sb.view();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* m_handle;
|
||||||
|
Mode m_mode;
|
||||||
|
};
|
||||||
85
include/prelude/linkedlist.hpp
Normal file
85
include/prelude/linkedlist.hpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <cstddef>
|
||||||
|
#include "prelude/string.hpp"
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct ListNode
|
||||||
|
{
|
||||||
|
T value;
|
||||||
|
ListNode* prev = nullptr;
|
||||||
|
ListNode* next = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class DoubleLinkedList {
|
||||||
|
public:
|
||||||
|
DoubleLinkedList() = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static DoubleLinkedList<T> FromView(const View<T> &view)
|
||||||
|
{
|
||||||
|
auto list = DoubleLinkedList<T>();
|
||||||
|
for (size_t i = 0; i < view.size; ++i)
|
||||||
|
{
|
||||||
|
list.Append(new ListNode<T>(view.data[i]));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Append(ListNode<T>* node)
|
||||||
|
{
|
||||||
|
if (IsEmpty())
|
||||||
|
{
|
||||||
|
node->next = nullptr;
|
||||||
|
node->prev = nullptr;
|
||||||
|
tail = node;
|
||||||
|
head = node;
|
||||||
|
} else {
|
||||||
|
head->next = node;
|
||||||
|
node->prev = head;
|
||||||
|
node->next = nullptr;
|
||||||
|
head = node;
|
||||||
|
}
|
||||||
|
m_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Prepend(ListNode<T>* node)
|
||||||
|
{
|
||||||
|
if (IsEmpty())
|
||||||
|
{
|
||||||
|
Append(node);
|
||||||
|
} else {
|
||||||
|
tail->prev = node;
|
||||||
|
node->next = tail;
|
||||||
|
node->prev = nullptr;
|
||||||
|
tail = node;
|
||||||
|
m_size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpliceFront(ListNode<T>* node)
|
||||||
|
{
|
||||||
|
if (m_size == 1 && tail == node && head == node) return;
|
||||||
|
assert((node->next || node->prev) && "node should be inside of the linked list");
|
||||||
|
if (node == tail) return;
|
||||||
|
if (node == head) {
|
||||||
|
node->prev->next = nullptr;
|
||||||
|
head = node->prev;
|
||||||
|
} else {
|
||||||
|
node->prev->next = node->next;
|
||||||
|
node->next->prev = node->prev;
|
||||||
|
}
|
||||||
|
m_size--;
|
||||||
|
Prepend(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const { return m_size == 0; }
|
||||||
|
|
||||||
|
ListNode<T>* Begin() const { return tail; }
|
||||||
|
ListNode<T>* End() const { return head; }
|
||||||
|
private:
|
||||||
|
ListNode<T>* head = nullptr;
|
||||||
|
ListNode<T>* tail = nullptr;
|
||||||
|
size_t m_size = 0;
|
||||||
|
};
|
||||||
@@ -68,8 +68,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// using StringView = View<char>;
|
|
||||||
|
|
||||||
class StringView final : public View<char>
|
class StringView final : public View<char>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
35
src/main.cpp
35
src/main.cpp
@@ -1,11 +1,14 @@
|
|||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <print>
|
#include <print>
|
||||||
|
#include "ir/op.hpp"
|
||||||
|
#include "ir/optimize.hpp"
|
||||||
#include "parser/lexer.hpp"
|
#include "parser/lexer.hpp"
|
||||||
#include "parser/ast.hpp"
|
#include "parser/ast.hpp"
|
||||||
#include "ir/ir.hpp"
|
#include "ir/ir.hpp"
|
||||||
|
#include "prelude/string.hpp"
|
||||||
|
#include "prelude/linkedlist.hpp"
|
||||||
|
|
||||||
// #include "codegen/fasm_stack.hpp"
|
// #include "codegen/fasm_stack.hpp"
|
||||||
|
|
||||||
@@ -59,8 +62,36 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
for (size_t i = 0; i < ops.size; ++i)
|
for (size_t i = 0; i < ops.size; ++i)
|
||||||
{
|
{
|
||||||
printf("%s\n", ops.data[i]->Format(0).c_str());
|
auto op = ops.data[i];
|
||||||
|
if (op->GetType() == IR::OpType::FN)
|
||||||
|
{
|
||||||
|
auto fn = reinterpret_cast<IR::FnOp*>(op);
|
||||||
|
auto blockList = DoubleLinkedList<IR::Op*>::FromView(fn->body().ops());
|
||||||
|
|
||||||
|
auto allocaoptimz = IR::AllocOptimizer();
|
||||||
|
printf("fn <%s>: status = %d\n", fn->name().c_str(), allocaoptimz.Apply(blockList));
|
||||||
|
printf("fn %s:\n", fn->name().c_str());
|
||||||
|
for (ListNode<IR::Op*>* cur = blockList.Begin(); cur != nullptr; cur = cur->next)
|
||||||
|
{
|
||||||
|
printf("%s\n", cur->value->Format(2).c_str());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringBuilder sb;
|
||||||
|
// for (size_t i = 0; i < ops.size; ++i)
|
||||||
|
// {
|
||||||
|
// sb.AppendFormat("%s\n", ops.data[i]->Format(0).c_str());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// printf("%s\n", sb.c_str());
|
||||||
|
|
||||||
|
// auto output = File::Open("example.ll", File::Mode::WRITE);
|
||||||
|
// if (!output.Write(sb.view()))
|
||||||
|
// {
|
||||||
|
// fprintf(stderr, "ERROR: Failed to write IR to a file");
|
||||||
|
// }
|
||||||
|
// std::println("OK");
|
||||||
|
|
||||||
// StackFasmX86_64Generator gen;
|
// StackFasmX86_64Generator gen;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user