mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 06:48:48 +00:00
wall, wextra, compiler: fix warnings & todos
This commit is contained in:
parent
c811d5ec50
commit
6d774ad42f
2 changed files with 110 additions and 161 deletions
|
|
@ -11,7 +11,7 @@
|
|||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run g++ -std=c++20 -DWITH_CHECK -Iinclude/ %{main} %{parser} %{analyzer} %{module_manager} %{runtime} %{obj} -o %{target})))
|
||||
(run g++ -Wall -Wextra -std=c++20 -DWITH_CHECK -Iinclude/ %{main} %{parser} %{analyzer} %{module_manager} %{runtime} %{obj} -o %{target})))
|
||||
|
||||
(rule
|
||||
(target types.o)
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run gcc -Iinclude/ -DWITH_CHECK -c %{src} -o %{target})))
|
||||
(run gcc -Wall -Wextra -Iinclude/ -DWITH_CHECK -c %{src} -o %{target})))
|
||||
|
||||
(rule
|
||||
(target interpreter.o)
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run gcc -Iinclude/ -DWITH_CHECK -c %{src} -o %{target})))
|
||||
(run gcc -Wall -Wextra -Iinclude/ -DWITH_CHECK -c %{src} -o %{target})))
|
||||
|
||||
(rule
|
||||
(target module_manager.o)
|
||||
|
|
@ -44,4 +44,4 @@
|
|||
(mode
|
||||
(promote (until-clean)))
|
||||
(action
|
||||
(run g++ -Iinclude/ -c %{src} -o %{target})))
|
||||
(run g++ -Wall -Wextra -Iinclude/ -c %{src} -o %{target})))
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ template <class... Ts> multifunc(Ts...) -> multifunc<Ts...>;
|
|||
#endif
|
||||
}
|
||||
|
||||
// TODO: use ranges transform
|
||||
// BETTER: use ranges transform
|
||||
template <typename T, typename U>
|
||||
std::vector<U> transform(std::vector<T> v, const std::function<U(T &&)> &f) {
|
||||
std::vector<U> result;
|
||||
|
|
@ -122,7 +122,7 @@ std::string labeled_scoped(int64_t i, const std::string_view s) {
|
|||
|
||||
} // namespace utils
|
||||
|
||||
enum class OS { // TODO: other oses
|
||||
enum class OS {
|
||||
LINUX,
|
||||
DARWIN,
|
||||
};
|
||||
|
|
@ -186,7 +186,7 @@ T of_64bit(const T &r) { return {.name = r.reg.name64, .reg = r.reg}; }
|
|||
|
||||
const std::string &to_string(const T &r) { return r.name; }
|
||||
|
||||
const auto none = Register::T{};
|
||||
// const auto none = Register::T{}; // NOTE: not used
|
||||
} // namespace Register
|
||||
|
||||
namespace Registers {
|
||||
|
|
@ -442,12 +442,12 @@ struct Instr {
|
|||
};
|
||||
/* a conditional jump */
|
||||
struct CJmp {
|
||||
std::string left;
|
||||
std::string right;
|
||||
}; // TODO: right names (?)
|
||||
std::string cmp;
|
||||
std::string label;
|
||||
};
|
||||
/* a non-conditional jump by a name */
|
||||
struct Jmp {
|
||||
std::string name;
|
||||
std::string label;
|
||||
};
|
||||
/* a non-conditional jump by indirect address */
|
||||
struct JmpI {
|
||||
|
|
@ -565,10 +565,10 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
/* Last allocated position on symbolic stack */
|
||||
struct StackState {
|
||||
struct S {
|
||||
int n;
|
||||
size_t n;
|
||||
};
|
||||
struct R {
|
||||
int n;
|
||||
size_t n;
|
||||
};
|
||||
struct E {};
|
||||
|
||||
|
|
@ -626,7 +626,7 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
return {R(x.n + 1)};
|
||||
}
|
||||
},
|
||||
[](const E &x) -> StackState { return {R(0)}; },
|
||||
[](const E &) -> StackState { return {R(0)}; },
|
||||
},
|
||||
*v.state);
|
||||
return {new_state, std::move(v.registers)};
|
||||
|
|
@ -636,14 +636,13 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
StackState new_state = std::visit(
|
||||
utils::multifunc{
|
||||
[&v](const S &x) -> StackState {
|
||||
return x.n == 0 ? StackState{R{
|
||||
static_cast<int>(v.registers.size() - 1)}}
|
||||
return x.n == 0 ? StackState{R{v.registers.size() - 1}}
|
||||
: StackState{S{x.n - 1}};
|
||||
},
|
||||
[&v](const R &x) -> StackState {
|
||||
[](const R &x) -> StackState {
|
||||
return x.n == 0 ? StackState{E{}} : StackState{R{x.n - 1}};
|
||||
},
|
||||
[](const E &x) -> StackState {
|
||||
[](const E &) -> StackState {
|
||||
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
||||
utils::unreachable();
|
||||
},
|
||||
|
|
@ -659,7 +658,7 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
[&v](const R &x) -> SymbolicLocation {
|
||||
return {Register{v.registers[x.n]}};
|
||||
},
|
||||
[](const E &x) -> SymbolicLocation {
|
||||
[](const E &) -> SymbolicLocation {
|
||||
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
||||
utils::unreachable();
|
||||
},
|
||||
|
|
@ -671,11 +670,11 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
return std::holds_alternative<typename StackState::E>(*v.state);
|
||||
}
|
||||
|
||||
// TODO: replace with range
|
||||
// BETTER: replace with range
|
||||
static std::vector<U> live_registers(const T &v) {
|
||||
return std::visit( //
|
||||
utils::multifunc{
|
||||
[&v](const S &x) { return v.registers; },
|
||||
[&v](const S &) { return v.registers; },
|
||||
[&v](const R &x) {
|
||||
std::vector<U> registers_prefix;
|
||||
registers_prefix.insert(registers_prefix.end(),
|
||||
|
|
@ -684,7 +683,7 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
// NOTE: same to (Array.sub registers 0 (n + 1))
|
||||
return registers_prefix;
|
||||
},
|
||||
[](const E &x) { return std::vector<U>{}; },
|
||||
[](const E &) { return std::vector<U>{}; },
|
||||
},
|
||||
*v.state);
|
||||
}
|
||||
|
|
@ -692,7 +691,7 @@ template <typename U> struct AbstractSymbolicStack {
|
|||
static size_t stack_size(const T &v) {
|
||||
return std::visit(utils::multifunc{
|
||||
[](const S &x) { return x.n + 1; },
|
||||
[](const auto &x) { return 0; },
|
||||
[](const auto &) -> size_t { return 0; },
|
||||
},
|
||||
*v.state);
|
||||
}
|
||||
|
|
@ -795,38 +794,19 @@ using SetS = std::unordered_set<std::string>;
|
|||
/* A map indexed by strings */
|
||||
template <typename T> using MapS = std::unordered_map<std::string, T>;
|
||||
|
||||
// TODO: any func required (?)
|
||||
template <typename Prg> struct Indexer {
|
||||
// let rec make_env m = function
|
||||
// | [] -> m
|
||||
// | LABEL l :: tl | FLABEL l :: tl -> make_env (M.add l tl m) tl
|
||||
// | _ :: tl -> make_env m tl
|
||||
// in
|
||||
// let m = make_env M.empty prg in
|
||||
// object
|
||||
// method is_label l = M.mem l m
|
||||
// method labeled l = M.find l m
|
||||
// end
|
||||
|
||||
MapS<Prg> m;
|
||||
};
|
||||
|
||||
struct Mode {
|
||||
bool is_debug;
|
||||
OS target_os;
|
||||
};
|
||||
|
||||
// FIXME: TODO: find out what is Prg
|
||||
using Prg = std::string;
|
||||
|
||||
// TODO: rebuild in c++ way
|
||||
struct Env : public Indexer<Prg> {
|
||||
struct Env {
|
||||
private:
|
||||
const std::string chars =
|
||||
"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'";
|
||||
|
||||
// NOTE: is not required
|
||||
// const std::vector<Opnd> argument_registers = Registers.argument_registers
|
||||
// // TODO: cast
|
||||
const size_t argument_registers_size = Registers::argument_registers.size();
|
||||
|
||||
private:
|
||||
SetS globals; /* a set of global variables */
|
||||
|
|
@ -836,7 +816,6 @@ private:
|
|||
size_t static_size = 0; /* static data size */
|
||||
SymbolicStack::T stack = SymbolicStack::empty(0); /* symbolic stack */
|
||||
std::vector<std::vector<std::string>> locals;
|
||||
/* function local variables */ // TODO: never used (?)
|
||||
MapS<SymbolicStack::T> stackmap; /* labels to stack map */
|
||||
bool barrier = false; /* barrier condition */
|
||||
|
||||
|
|
@ -886,23 +865,6 @@ public:
|
|||
return result.str();
|
||||
}
|
||||
|
||||
std::string print_locals() const {
|
||||
std::stringstream result;
|
||||
// TODO
|
||||
result << std::format("LOCALS: size = {}\n", static_size);
|
||||
for (const auto &l : locals) {
|
||||
result << "(";
|
||||
// NOTE: same to List.iter (fun (a, i) -> Printf.printf "%s=%d " a i) l;
|
||||
for (size_t i = 0; i < l.size(); ++i) {
|
||||
result << std::format("{}={} ", l[i],
|
||||
i); // TODO: exact format of locals
|
||||
}
|
||||
result << ")\n";
|
||||
}
|
||||
result << "END LOCALS\n";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
/* Assert empty stack */
|
||||
void assert_empty_stack() const { assert(SymbolicStack::is_empty(stack)); }
|
||||
|
||||
|
|
@ -953,10 +915,10 @@ public:
|
|||
return M{DataKind::F, ext, Addressed::A, x.s};
|
||||
},
|
||||
[](const ValT::Local &x) -> Opnd { return S{x.n}; },
|
||||
[this](const ValT::Arg &x) -> Opnd {
|
||||
return x.n < argument_registers_size
|
||||
[](const ValT::Arg &x) -> Opnd {
|
||||
return x.n < Registers::argument_registers.size()
|
||||
? Opnd{argument_registers[x.n]}
|
||||
: S{-(x.n - argument_registers_size) - 1};
|
||||
: S{-(x.n - Registers::argument_registers.size()) - 1};
|
||||
},
|
||||
[](const ValT::Access &x) -> Opnd {
|
||||
return I{static_cast<int>(word_size * (x.n + 1)), r15};
|
||||
|
|
@ -986,13 +948,11 @@ public:
|
|||
|
||||
std::pair<std::vector<SymbolicStack::SymbolicLocation>, size_t>
|
||||
arguments_locations(size_t n) {
|
||||
// TODO
|
||||
|
||||
using SymbolicLocation = SymbolicStack::SymbolicLocation;
|
||||
using Register = SymbolicStack::Register;
|
||||
using Stack = SymbolicStack::Stack;
|
||||
|
||||
if (n < argument_registers_size) {
|
||||
if (n < Registers::argument_registers.size()) {
|
||||
std::vector<::Register::T> result;
|
||||
result.insert(result.end(), argument_registers.begin(),
|
||||
argument_registers.begin() + n);
|
||||
|
|
@ -1008,9 +968,9 @@ public:
|
|||
[](const auto &r) -> SymbolicLocation {
|
||||
return {Register{r}};
|
||||
}),
|
||||
std::vector<SymbolicLocation>(n - argument_registers_size,
|
||||
{Stack{}})),
|
||||
n - argument_registers_size};
|
||||
std::vector<SymbolicLocation>(
|
||||
n - Registers::argument_registers.size(), {Stack{}})),
|
||||
n - Registers::argument_registers.size()};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1099,17 +1059,6 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
/* gets all string definitions */
|
||||
SetS get_strings() const {
|
||||
SetS result;
|
||||
result.reserve(stringm.size());
|
||||
for (const auto &str : stringm) {
|
||||
result.insert(
|
||||
str.first); // TODO: M.bindings -> take first elem argument (?)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* gets a number of stack positions allocated */
|
||||
size_t get_allocated() const { return stack_slots; }
|
||||
std::string get_allocated_size() const {
|
||||
|
|
@ -1206,9 +1155,7 @@ std::string to_code(const Env &env, const Opnd &opnd) {
|
|||
return std::format("{}(%rip)", x.name);
|
||||
}
|
||||
// else -> x.ext == Externality::E && x.kind == DataKind::D
|
||||
return std::format(
|
||||
"{}@GOTPCREL(%rip)",
|
||||
env.prefixed(x.name)); // TODO: does @ mean something (?)
|
||||
return std::format("{}@GOTPCREL(%rip)", env.prefixed(x.name));
|
||||
},
|
||||
[&env](const Opnd::C &x) {
|
||||
return std::format("${}", env.prefixed(x.name));
|
||||
|
|
@ -1248,7 +1195,7 @@ std::string to_code(const Env &env, const Instr &instr) {
|
|||
|
||||
return std::visit(
|
||||
utils::multifunc{
|
||||
[](const Cltd &x) -> std::string { return "\tcqo"; },
|
||||
[](const Cltd &) -> std::string { return "\tcqo"; },
|
||||
[](const Set &x) -> std::string {
|
||||
auto r = to_string(Register::of_8bit(x.reg));
|
||||
return std::format("\tset{}\t{}", x.suffix, std::move(r));
|
||||
|
|
@ -1283,7 +1230,7 @@ std::string to_code(const Env &env, const Instr &instr) {
|
|||
[&opnd_to_code](const Pop &x) -> std::string {
|
||||
return std::format("\tpopq\t{}", opnd_to_code(x.opnd));
|
||||
},
|
||||
[](const Ret &x) -> std::string { return "\tret"; },
|
||||
[](const Ret &) -> std::string { return "\tret"; },
|
||||
[&env](const Call &x) -> std::string {
|
||||
return std::format("\tcall\t{}", env.prefixed(x.name));
|
||||
},
|
||||
|
|
@ -1294,13 +1241,13 @@ std::string to_code(const Env &env, const Instr &instr) {
|
|||
return std::format("{}:\n", env.prefixed(x.name));
|
||||
},
|
||||
[&env](const Jmp &x) -> std::string {
|
||||
return std::format("\tjmp\t{}", env.prefixed(x.name));
|
||||
return std::format("\tjmp\t{}", env.prefixed(x.label));
|
||||
},
|
||||
[&opnd_to_code](const JmpI &x) -> std::string {
|
||||
return std::format("\tjmp\t*({})", opnd_to_code(x.opnd));
|
||||
},
|
||||
[&env](const CJmp &x) -> std::string {
|
||||
return std::format("\tj{}\t{}", x.left, env.prefixed(x.right));
|
||||
return std::format("\tj{}\t{}", x.cmp, env.prefixed(x.label));
|
||||
},
|
||||
[](const Meta &x) -> std::string {
|
||||
return std::format("{}\n", x.name);
|
||||
|
|
@ -1317,7 +1264,7 @@ std::string to_code(const Env &env, const Instr &instr) {
|
|||
[&opnd_to_code](const Sar1 &x) -> std::string {
|
||||
return std::format("\tsarq\t{}", opnd_to_code(x.opnd));
|
||||
},
|
||||
[](const Repmovsl &x) -> std::string { return "\trep movsq\t"; },
|
||||
[](const Repmovsl &) -> std::string { return "\trep movsq\t"; },
|
||||
},
|
||||
*instr);
|
||||
}
|
||||
|
|
@ -1604,7 +1551,6 @@ std::pair<size_t, std::vector<Instr>> setup_arguments(Env &env, size_t nargs) {
|
|||
[](std::vector<Opnd> &&args,
|
||||
std::vector<SymbolicStack::SymbolicLocation> &&arg_locs) {
|
||||
using Register = SymbolicStack::Register;
|
||||
using Stack = SymbolicStack::Stack;
|
||||
|
||||
assert(args.size() == arg_locs.size());
|
||||
|
||||
|
|
@ -2037,7 +1983,7 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
env.register_extern(x.name);
|
||||
return {};
|
||||
},
|
||||
[](const SMInstr::IMPORT &x)
|
||||
[](const SMInstr::IMPORT &)
|
||||
-> std::vector<Instr> { // NOTE: not required in bytecode
|
||||
return {};
|
||||
},
|
||||
|
|
@ -2093,7 +2039,7 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
Mov{rax, env.loc(x.v)}}
|
||||
: std::vector<Instr>{Mov{s, env.loc(x.v)}};
|
||||
},
|
||||
[&env](const SMInstr::STA &x) -> std::vector<Instr> {
|
||||
[&env](const SMInstr::STA &) -> std::vector<Instr> {
|
||||
return compile_call(env, ".sta", 3, false);
|
||||
},
|
||||
[&env](const SMInstr::STI &) -> std::vector<Instr> {
|
||||
|
|
@ -2107,13 +2053,13 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
[&env](const SMInstr::BINOP &x) -> std::vector<Instr> {
|
||||
return compile_binop(env, x.opr);
|
||||
},
|
||||
[&env](const SMInstr::LABEL &x) -> std::vector<Instr> {
|
||||
[](const SMInstr::LABEL &x) -> std::vector<Instr> {
|
||||
return {Label{x.s}};
|
||||
},
|
||||
[&env](const SMInstr::FLABEL &x) -> std::vector<Instr> {
|
||||
[](const SMInstr::FLABEL &x) -> std::vector<Instr> {
|
||||
return {Label{x.s}};
|
||||
},
|
||||
[&env](const SMInstr::SLABEL &x) -> std::vector<Instr> {
|
||||
[](const SMInstr::SLABEL &x) -> std::vector<Instr> {
|
||||
return {Label{x.s}};
|
||||
},
|
||||
[&env](const SMInstr::JMP &x) -> std::vector<Instr> {
|
||||
|
|
@ -2140,8 +2086,7 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
|
||||
const std::string name = (x.f[0] == 'L' ? x.f.substr(1) : x.f);
|
||||
|
||||
const auto stabs = [&env, &cmd, &x,
|
||||
&name]() -> std::vector<Instr> {
|
||||
const auto stabs = [&env, &x, &name]() -> std::vector<Instr> {
|
||||
if (!env.do_opt_stabs()) {
|
||||
return {};
|
||||
}
|
||||
|
|
@ -2176,7 +2121,8 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
}
|
||||
|
||||
auto argc_correct_label = x.f + "_argc_correct";
|
||||
auto pat_addr = // TODO: check that the same string
|
||||
auto pat_addr = // TODO: check is that is the same string to
|
||||
// ocaml version one
|
||||
env.register_string(
|
||||
"Function %s called with incorrect arguments count. \
|
||||
Expected: %d. Actual: %d\\n");
|
||||
|
|
@ -2205,65 +2151,68 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
env.assert_empty_stack();
|
||||
const bool has_closure = !x.closure.empty();
|
||||
env.enter(x.f, x.nargs, x.nlocals, has_closure);
|
||||
return utils::concat(std::move(stabs_code), Instr{Meta{"\t.cfi_startproc"}},
|
||||
(x.f == cmd.topname ? std::vector<Instr>{
|
||||
Mov{M{DataKind::D, Externality::I, Addressed::V, "init"}, rax},
|
||||
Binop{Opr::TEST, rax, rax},
|
||||
CJmp{"z", "continue"},
|
||||
Ret{},
|
||||
Label{"_ERROR"},
|
||||
Call{utils::labeled("binoperror")},
|
||||
Ret{},
|
||||
Label{"_ERROR2"},
|
||||
Call {utils::labeled("binoperror2")},
|
||||
Ret{},
|
||||
Label{"continue"},
|
||||
Mov {L {1}, M {DataKind::D, Externality::I, Addressed::V, "init"}},
|
||||
} :std::vector<Instr>{}),
|
||||
std::vector<Instr>{
|
||||
Push{rbp},
|
||||
Meta{"\t.cfi_def_cfa_offset\t8"},
|
||||
Meta{"\t.cfi_offset 5, -8"},
|
||||
Mov{rsp, rbp},
|
||||
Meta{"\t.cfi_def_cfa_register\t5"},
|
||||
Binop {Opr::SUB, C{env.lsize()}, rsp},
|
||||
Mov {rdi, r12},
|
||||
Mov {rsi, r13},
|
||||
Mov {rcx, r14},
|
||||
Mov {rsp, rdi},
|
||||
Lea {filler, rsi},
|
||||
Mov {C{env.get_allocated_size()}, rcx},
|
||||
Repmovsl{},
|
||||
Mov {r12, rdi},
|
||||
Mov {r13, rsi},
|
||||
Mov {r14, rcx},
|
||||
},
|
||||
(x.f == "main"? std::vector<Instr>{
|
||||
/* Align stack as `main` function could be called misaligned */
|
||||
Mov {L{0xF}, rax},
|
||||
Binop{Opr::TEST, rsp, rax},
|
||||
CJmp{"z", "ALIGNED"},
|
||||
Push{filler},
|
||||
Label{"ALIGNED"},
|
||||
/* Initialize gc and arguments */
|
||||
Push{rdi},
|
||||
Push{rsi},
|
||||
Call{"__gc_init"},
|
||||
Pop{rsi},
|
||||
Pop{rdi},
|
||||
Call{"set_args"},
|
||||
} :
|
||||
std::vector<Instr>{}),
|
||||
(x.f == cmd.topname ?
|
||||
// TODO: optimize filter
|
||||
utils::transform<std::string, Instr>(utils::filter<std::string>(std::vector<std::string>{imports}, [](const auto& i) { return i != "Std"; }),
|
||||
[](const auto& i) -> Instr { return Call{std::format("init" + i)}; })
|
||||
: std::vector<Instr>{}),
|
||||
std::move(check_argc_code)
|
||||
);
|
||||
// TODO
|
||||
return utils::concat(
|
||||
std::move(stabs_code),
|
||||
Instr{Meta{"\t.cfi_startproc"}},
|
||||
(x.f == cmd.topname ? std::vector<Instr>{
|
||||
Mov{M{DataKind::D, Externality::I, Addressed::V, "init"}, rax},
|
||||
Binop{Opr::TEST, rax, rax},
|
||||
CJmp{"z", "continue"},
|
||||
Ret{},
|
||||
Label{"_ERROR"},
|
||||
Call{utils::labeled("binoperror")},
|
||||
Ret{},
|
||||
Label{"_ERROR2"},
|
||||
Call {utils::labeled("binoperror2")},
|
||||
Ret{},
|
||||
Label{"continue"},
|
||||
Mov {L {1}, M {DataKind::D, Externality::I, Addressed::V, "init"}},
|
||||
} : std::vector<Instr>{}),
|
||||
std::vector<Instr>{
|
||||
Push{rbp},
|
||||
Meta{"\t.cfi_def_cfa_offset\t8"},
|
||||
Meta{"\t.cfi_offset 5, -8"},
|
||||
Mov{rsp, rbp},
|
||||
Meta{"\t.cfi_def_cfa_register\t5"},
|
||||
Binop {Opr::SUB, C{env.lsize()}, rsp},
|
||||
Mov {rdi, r12},
|
||||
Mov {rsi, r13},
|
||||
Mov {rcx, r14},
|
||||
Mov {rsp, rdi},
|
||||
Lea {filler, rsi},
|
||||
Mov {C{env.get_allocated_size()}, rcx},
|
||||
Repmovsl{},
|
||||
Mov {r12, rdi},
|
||||
Mov {r13, rsi},
|
||||
Mov {r14, rcx},
|
||||
},
|
||||
(x.f == "main"? std::vector<Instr>{
|
||||
/* Align stack as `main` function could be called misaligned */
|
||||
Mov {L{0xF}, rax},
|
||||
Binop{Opr::TEST, rsp, rax},
|
||||
CJmp{"z", "ALIGNED"},
|
||||
Push{filler},
|
||||
Label{"ALIGNED"},
|
||||
/* Initialize gc and arguments */
|
||||
Push{rdi},
|
||||
Push{rsi},
|
||||
Call{"__gc_init"},
|
||||
Pop{rsi},
|
||||
Pop{rdi},
|
||||
Call{"set_args"},
|
||||
} : std::vector<Instr>{}),
|
||||
(x.f == cmd.topname ? // TODO: optimize filter
|
||||
utils::transform<std::string, Instr>(
|
||||
utils::filter<std::string>(
|
||||
std::vector<std::string>{imports},
|
||||
[](const auto &i) { return i != "Std"; }),
|
||||
[](const auto &i) -> Instr {
|
||||
return Call{std::format("init" + i)};
|
||||
}) : std::vector<Instr>{}),
|
||||
std::move(check_argc_code)
|
||||
);
|
||||
},
|
||||
[&env](const SMInstr::END &y) -> std::vector<Instr> {
|
||||
[&env](const SMInstr::END &) -> std::vector<Instr> {
|
||||
const auto x = env.pop();
|
||||
env.assert_empty_stack();
|
||||
const auto &name = env.fname;
|
||||
|
|
@ -2303,13 +2252,13 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
std::move(stabs));
|
||||
|
||||
env.leave();
|
||||
return std::move(result);
|
||||
return result;
|
||||
},
|
||||
[&env](const SMInstr::RET &) -> std::vector<Instr> {
|
||||
const auto x = env.peek();
|
||||
return {Mov{x, rax}, Jmp{env.epilogue()}};
|
||||
},
|
||||
[&env](const SMInstr::ELEM &x) -> std::vector<Instr> {
|
||||
[&env](const SMInstr::ELEM &) -> std::vector<Instr> {
|
||||
return compile_call(env, ".elem", 2, false);
|
||||
},
|
||||
[&env](const SMInstr::CALL &x) -> std::vector<Instr> {
|
||||
|
|
@ -2324,7 +2273,7 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
|||
return utils::concat(mov(L{box(env.hash(x.tag))}, s),
|
||||
std::move(code));
|
||||
},
|
||||
[&env](const SMInstr::DROP &x) -> std::vector<Instr> {
|
||||
[&env](const SMInstr::DROP &) -> std::vector<Instr> {
|
||||
env.pop();
|
||||
return {};
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue