mirror of
https://github.com/ProgramSnail/Lama.git
synced 2025-12-06 14:58:50 +00:00
compiler: make SymbolicStack to be struct
This commit is contained in:
parent
6d774ad42f
commit
b5564c6731
1 changed files with 135 additions and 160 deletions
|
|
@ -562,8 +562,10 @@ template <typename U> struct AbstractSymbolicStack {
|
||||||
// val peek : 'a t -> 'a symbolic_location
|
// val peek : 'a t -> 'a symbolic_location
|
||||||
// val peek2 : 'a t -> 'a symbolic_location * 'a symbolic_location
|
// val peek2 : 'a t -> 'a symbolic_location * 'a symbolic_location
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
/* Last allocated position on symbolic stack */
|
/* Last allocated position on symbolic stack */
|
||||||
struct StackState {
|
struct State {
|
||||||
struct S {
|
struct S {
|
||||||
size_t n;
|
size_t n;
|
||||||
};
|
};
|
||||||
|
|
@ -579,16 +581,13 @@ template <typename U> struct AbstractSymbolicStack {
|
||||||
const W &operator*() const { return val; }
|
const W &operator*() const { return val; }
|
||||||
const W &operator->() const { return val; }
|
const W &operator->() const { return val; }
|
||||||
};
|
};
|
||||||
using S = StackState::S;
|
using S = State::S;
|
||||||
using R = StackState::R;
|
using R = State::R;
|
||||||
using E = StackState::E;
|
using E = State::E;
|
||||||
|
|
||||||
struct T {
|
//
|
||||||
StackState state;
|
|
||||||
std::vector<U> registers;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SymbolicLocation {
|
struct Location {
|
||||||
struct Stack {
|
struct Stack {
|
||||||
int n;
|
int n;
|
||||||
};
|
};
|
||||||
|
|
@ -608,122 +607,119 @@ template <typename U> struct AbstractSymbolicStack {
|
||||||
return std::holds_alternative<S>(val);
|
return std::holds_alternative<S>(val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
using Stack = SymbolicLocation::Stack;
|
using Stack = Location::Stack;
|
||||||
using Register = SymbolicLocation::Register;
|
using Register = Location::Register;
|
||||||
|
|
||||||
static AbstractSymbolicStack::T empty(std::vector<U> registers) {
|
public:
|
||||||
return {{typename StackState::E{}}, std::move(registers)};
|
State state;
|
||||||
}
|
std::vector<U> registers;
|
||||||
|
|
||||||
static T next(T v) {
|
public:
|
||||||
StackState new_state =
|
AbstractSymbolicStack(std::vector<U> registers)
|
||||||
std::visit(utils::multifunc{
|
: state(typename State::E{}), registers(std::move(registers)) {}
|
||||||
[](const S &x) -> StackState { return {S(x.n)}; },
|
|
||||||
[&v](const R &x) -> StackState {
|
State next_state(const State &v) const {
|
||||||
if (x.n + 1 >= v.registers.size()) {
|
return std::visit(utils::multifunc{
|
||||||
|
[](const S &x) -> State { return {S(x.n)}; },
|
||||||
|
[this](const R &x) -> State {
|
||||||
|
if (x.n + 1 >= registers.size()) {
|
||||||
return {S(0)};
|
return {S(0)};
|
||||||
} else {
|
} else {
|
||||||
return {R(x.n + 1)};
|
return {R(x.n + 1)};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[](const E &) -> StackState { return {R(0)}; },
|
[](const E &) -> State { return {R(0)}; },
|
||||||
},
|
},
|
||||||
*v.state);
|
*v);
|
||||||
return {new_state, std::move(v.registers)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static T previous(T v) {
|
State previous_state(const State &v) const {
|
||||||
StackState new_state = std::visit(
|
return std::visit(utils::multifunc{
|
||||||
utils::multifunc{
|
[this](const S &x) -> State {
|
||||||
[&v](const S &x) -> StackState {
|
return x.n == 0 ? State{R{registers.size() - 1}}
|
||||||
return x.n == 0 ? StackState{R{v.registers.size() - 1}}
|
: State{S{x.n - 1}};
|
||||||
: StackState{S{x.n - 1}};
|
|
||||||
},
|
},
|
||||||
[](const R &x) -> StackState {
|
[](const R &x) -> State {
|
||||||
return x.n == 0 ? StackState{E{}} : StackState{R{x.n - 1}};
|
return x.n == 0 ? State{E{}} : State{R{x.n - 1}};
|
||||||
},
|
},
|
||||||
[](const E &) -> StackState {
|
[](const E &) -> State {
|
||||||
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
||||||
utils::unreachable();
|
utils::unreachable();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
*v.state);
|
*v);
|
||||||
return {new_state, std::move(v.registers)};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static SymbolicLocation location(const T &v) {
|
Location location(const std::optional<State> &another_state = {}) const {
|
||||||
return std::visit(
|
return std::visit(utils::multifunc{
|
||||||
utils::multifunc{
|
[](const S &x) -> Location { return {Stack(x.n)}; },
|
||||||
[](const S &x) -> SymbolicLocation { return {Stack(x.n)}; },
|
[this](const R &x) -> Location {
|
||||||
[&v](const R &x) -> SymbolicLocation {
|
return {Register{registers[x.n]}};
|
||||||
return {Register{v.registers[x.n]}};
|
|
||||||
},
|
},
|
||||||
[](const E &) -> SymbolicLocation {
|
[](const E &) -> Location {
|
||||||
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
failure("Empty stack %s: %d", __FILE__, __LINE__);
|
||||||
utils::unreachable();
|
utils::unreachable();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
*v.state);
|
another_state ? **another_state : *state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_empty(const T &v) {
|
bool is_empty() const {
|
||||||
return std::holds_alternative<typename StackState::E>(*v.state);
|
return std::holds_alternative<typename State::E>(*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BETTER: replace with range
|
// BETTER: replace with range
|
||||||
static std::vector<U> live_registers(const T &v) {
|
std::vector<U> live_registers() const {
|
||||||
return std::visit( //
|
return std::visit( //
|
||||||
utils::multifunc{
|
utils::multifunc{
|
||||||
[&v](const S &) { return v.registers; },
|
[this](const S &) { return registers; },
|
||||||
[&v](const R &x) {
|
[this](const R &x) {
|
||||||
std::vector<U> registers_prefix;
|
std::vector<U> registers_prefix;
|
||||||
registers_prefix.insert(registers_prefix.end(),
|
registers_prefix.insert(registers_prefix.end(), registers.begin(),
|
||||||
v.registers.begin(),
|
registers.begin() + x.n + 1);
|
||||||
v.registers.begin() + x.n + 1);
|
|
||||||
// NOTE: same to (Array.sub registers 0 (n + 1))
|
// NOTE: same to (Array.sub registers 0 (n + 1))
|
||||||
return registers_prefix;
|
return registers_prefix;
|
||||||
},
|
},
|
||||||
[](const E &) { return std::vector<U>{}; },
|
[](const E &) { return std::vector<U>{}; },
|
||||||
},
|
},
|
||||||
*v.state);
|
*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t stack_size(const T &v) {
|
size_t stack_size() const {
|
||||||
return std::visit(utils::multifunc{
|
return std::visit(utils::multifunc{
|
||||||
[](const S &x) { return x.n + 1; },
|
[](const S &x) { return x.n + 1; },
|
||||||
[](const auto &) -> size_t { return 0; },
|
[](const auto &) -> size_t { return 0; },
|
||||||
},
|
},
|
||||||
*v.state);
|
*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<T, SymbolicLocation> allocate(T v) {
|
Location allocate() {
|
||||||
// let state = next state in
|
state = next_state(state);
|
||||||
auto loc = location(v);
|
return location();
|
||||||
return {next(std::move(v)), loc};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::pair<T, SymbolicLocation> pop(T v) {
|
Location pop() {
|
||||||
auto loc = location(v);
|
state = previous_state(state);
|
||||||
return {previous(std::move(v)), loc};
|
return location();
|
||||||
}
|
}
|
||||||
|
|
||||||
static SymbolicLocation peek(const T &v) { return location(v); }
|
Location peek() const { return location(); }
|
||||||
|
|
||||||
static std::pair<SymbolicLocation, SymbolicLocation> peek2(const T &v) {
|
std::pair<Location, Location> peek2() const {
|
||||||
return {location(v), location(previous(v))};
|
return {location(), location(previous_state(state))};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SymbolicStack {
|
struct SymbolicStack {
|
||||||
using AbSS = AbstractSymbolicStack<Register::T>;
|
using AbSS = AbstractSymbolicStack<Register::T>;
|
||||||
|
|
||||||
using S = AbSS::StackState::S;
|
using S = AbSS::State::S;
|
||||||
using R = AbSS::StackState::R;
|
using R = AbSS::State::R;
|
||||||
using E = AbSS::StackState::E;
|
using E = AbSS::State::E;
|
||||||
|
|
||||||
using SymbolicLocation = AbSS::SymbolicLocation;
|
using Location = AbSS::Location;
|
||||||
using Stack = SymbolicLocation::Stack;
|
using Stack = Location::Stack;
|
||||||
using Register = SymbolicLocation::Register;
|
using Register = Location::Register;
|
||||||
|
|
||||||
// type t
|
// type t
|
||||||
|
|
||||||
|
|
@ -736,55 +732,45 @@ struct SymbolicStack {
|
||||||
// val peek : t -> opnd
|
// val peek : t -> opnd
|
||||||
// val peek2 : t -> opnd * opnd
|
// val peek2 : t -> opnd * opnd
|
||||||
|
|
||||||
struct T {
|
public:
|
||||||
AbSS::T state;
|
AbSS state;
|
||||||
size_t nlocals;
|
size_t nlocals;
|
||||||
};
|
|
||||||
|
|
||||||
|
public:
|
||||||
/* To use free argument registers we have to rewrite function call
|
/* To use free argument registers we have to rewrite function call
|
||||||
compilation. Otherwise we will result with the following code in
|
compilation. Otherwise we will result with the following code in
|
||||||
arguments setup: movq %rcx, %rdx movq %rdx, %rsi */
|
arguments setup: movq %rcx, %rdx movq %rdx, %rsi */
|
||||||
static T empty(size_t nlocals) {
|
SymbolicStack(size_t nlocals)
|
||||||
return {
|
: state(AbSS(Registers::extra_caller_saved_registers)), nlocals(nlocals) {
|
||||||
.state = AbSS::empty(Registers::extra_caller_saved_registers),
|
|
||||||
.nlocals = nlocals,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Opnd opnd_from_loc(const T &v, const SymbolicLocation &loc) {
|
Opnd opnd_from_loc(const Location &loc) const {
|
||||||
return std::visit(
|
return std::visit(
|
||||||
utils::multifunc{
|
utils::multifunc{
|
||||||
[](const Register &x) -> Opnd { return {Opnd::R{x.r}}; },
|
[](const Register &x) -> Opnd { return {Opnd::R{x.r}}; },
|
||||||
[&v](const Stack &x) -> Opnd { return Opnd::S{x.n + v.nlocals}; },
|
[this](const Stack &x) -> Opnd { return Opnd::S{x.n + nlocals}; },
|
||||||
},
|
},
|
||||||
*loc);
|
*loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_empty(const T &v) { return AbSS::is_empty(v.state); };
|
bool is_empty() const { return state.is_empty(); };
|
||||||
|
|
||||||
static std::vector<Opnd> live_registers(const T &v) {
|
std::vector<Opnd> live_registers() const {
|
||||||
return utils::transform<::Register::T, Opnd>(
|
return utils::transform<::Register::T, Opnd>(
|
||||||
AbSS::live_registers(v.state),
|
state.live_registers(), [](auto &&r) -> Opnd { return Opnd::R{r}; });
|
||||||
[](auto &&r) -> Opnd { return Opnd::R{r}; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t stack_size(const T &v) { return AbSS::stack_size(v.state); }
|
size_t stack_size() const { return state.stack_size(); }
|
||||||
|
|
||||||
static std::pair<T, Opnd> allocate(const T &v) {
|
Opnd allocate() { return opnd_from_loc(state.allocate()); }
|
||||||
auto [state, loc] = AbSS::allocate(v.state);
|
|
||||||
return {{std::move(state), v.nlocals}, opnd_from_loc(v, loc)};
|
|
||||||
} // TODO: check
|
|
||||||
|
|
||||||
static std::pair<T, Opnd> pop(const T &v) {
|
Opnd pop() { return opnd_from_loc(state.pop()); }
|
||||||
auto [state, loc] = AbSS::pop(v.state);
|
|
||||||
return {{std::move(state), v.nlocals}, opnd_from_loc(v, loc)};
|
|
||||||
}
|
|
||||||
|
|
||||||
static Opnd peek(const T &v) { return opnd_from_loc(v, AbSS::peek(v.state)); }
|
Opnd peek() const { return opnd_from_loc(state.peek()); }
|
||||||
|
|
||||||
static std::pair<Opnd, Opnd> peek2(const T &v) {
|
std::pair<Opnd, Opnd> peek2() const {
|
||||||
const auto [loc1, loc2] = AbSS::peek2(v.state);
|
const auto [loc1, loc2] = state.peek2();
|
||||||
return {opnd_from_loc(v, loc1), opnd_from_loc(v, loc2)};
|
return {opnd_from_loc(loc1), opnd_from_loc(loc2)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -799,11 +785,10 @@ struct Mode {
|
||||||
OS target_os;
|
OS target_os;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: rebuild in c++ way
|
// TODO: remove unrequired parts
|
||||||
struct Env {
|
struct Env {
|
||||||
private:
|
private:
|
||||||
const std::string chars =
|
const static std::string chars;
|
||||||
"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'";
|
|
||||||
|
|
||||||
// NOTE: is not required
|
// NOTE: is not required
|
||||||
// const std::vector<Opnd> argument_registers = Registers.argument_registers
|
// const std::vector<Opnd> argument_registers = Registers.argument_registers
|
||||||
|
|
@ -814,9 +799,9 @@ private:
|
||||||
size_t scount = 0; /* string count */
|
size_t scount = 0; /* string count */
|
||||||
size_t stack_slots = 0; /* maximal number of stack positions */
|
size_t stack_slots = 0; /* maximal number of stack positions */
|
||||||
size_t static_size = 0; /* static data size */
|
size_t static_size = 0; /* static data size */
|
||||||
SymbolicStack::T stack = SymbolicStack::empty(0); /* symbolic stack */
|
SymbolicStack stack = SymbolicStack(0); /* symbolic stack */
|
||||||
std::vector<std::vector<std::string>> locals;
|
std::vector<std::vector<std::string>> locals;
|
||||||
MapS<SymbolicStack::T> stackmap; /* labels to stack map */
|
MapS<SymbolicStack> stackmap; /* labels to stack map */
|
||||||
bool barrier = false; /* barrier condition */
|
bool barrier = false; /* barrier condition */
|
||||||
|
|
||||||
SetS externs;
|
SetS externs;
|
||||||
|
|
@ -833,7 +818,7 @@ public:
|
||||||
|
|
||||||
size_t nargs = 0; /* number of function arguments */
|
size_t nargs = 0; /* number of function arguments */
|
||||||
|
|
||||||
Mode mode;
|
const Mode mode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Env(Mode mode) : mode(std::move(mode)) {}
|
Env(Mode mode) : mode(std::move(mode)) {}
|
||||||
|
|
@ -850,13 +835,11 @@ public:
|
||||||
// TODO: add SymbolicStack functions to opimize
|
// TODO: add SymbolicStack functions to opimize
|
||||||
std::string print_stack() const {
|
std::string print_stack() const {
|
||||||
std::stringstream result;
|
std::stringstream result;
|
||||||
SymbolicStack::T stack_copy = stack;
|
SymbolicStack stack_copy = stack;
|
||||||
|
|
||||||
std::vector<std::string> elements;
|
std::vector<std::string> elements;
|
||||||
while (!SymbolicStack::is_empty(stack_copy)) {
|
while (!stack_copy.is_empty()) {
|
||||||
auto result = SymbolicStack::pop(std::move(stack_copy));
|
elements.push_back(to_string(stack_copy.pop()));
|
||||||
stack_copy = std::move(result.first);
|
|
||||||
elements.push_back(to_string(result.second));
|
|
||||||
}
|
}
|
||||||
std::reverse(elements.begin(), elements.end());
|
std::reverse(elements.begin(), elements.end());
|
||||||
for (const auto &element : elements) {
|
for (const auto &element : elements) {
|
||||||
|
|
@ -866,7 +849,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assert empty stack */
|
/* Assert empty stack */
|
||||||
void assert_empty_stack() const { assert(SymbolicStack::is_empty(stack)); }
|
void assert_empty_stack() const { assert(stack.is_empty()); }
|
||||||
|
|
||||||
/* check barrier condition */
|
/* check barrier condition */
|
||||||
bool is_barrier() { return barrier; }
|
bool is_barrier() { return barrier; }
|
||||||
|
|
@ -878,13 +861,13 @@ public:
|
||||||
void drop_barrier() { barrier = false; }
|
void drop_barrier() { barrier = false; }
|
||||||
|
|
||||||
/* drop stack */
|
/* drop stack */
|
||||||
void drop_stack() { stack = SymbolicStack::empty(static_size); }
|
void drop_stack() { stack = SymbolicStack(static_size); }
|
||||||
|
|
||||||
/* associates a stack to a label */
|
/* associates a stack to a label */
|
||||||
void set_stack(std::string const &l) { stackmap.insert({l, stack}); }
|
void set_stack(std::string const &l) { stackmap.insert({l, stack}); }
|
||||||
|
|
||||||
/* retrieves a stack for a label */
|
/* retrieves a stack for a label */
|
||||||
std::optional<SymbolicStack::T *> retrieve_stack(std::string const &l) {
|
std::optional<SymbolicStack *> retrieve_stack(std::string const &l) {
|
||||||
auto it = stackmap.find(l);
|
auto it = stackmap.find(l);
|
||||||
if (it != stackmap.end()) {
|
if (it != stackmap.end()) {
|
||||||
return &it->second;
|
return &it->second;
|
||||||
|
|
@ -929,26 +912,20 @@ public:
|
||||||
|
|
||||||
/* allocates a fresh position on a symbolic stack */
|
/* allocates a fresh position on a symbolic stack */
|
||||||
Opnd allocate() {
|
Opnd allocate() {
|
||||||
auto [new_stack, opnd] = SymbolicStack::allocate(stack);
|
auto opnd = stack.allocate();
|
||||||
stack = std::move(new_stack);
|
stack_slots = std::max(stack_slots, (static_size + stack.stack_size()));
|
||||||
stack_slots =
|
|
||||||
std::max(stack_slots, (static_size + SymbolicStack::stack_size(stack)));
|
|
||||||
return opnd;
|
return opnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pops one operand from the symbolic stack */
|
/* pops one operand from the symbolic stack */
|
||||||
Opnd pop() {
|
Opnd pop() { return stack.pop(); }
|
||||||
auto [new_stack, opnd] = SymbolicStack::pop(stack);
|
|
||||||
stack = std::move(new_stack);
|
|
||||||
return opnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is rdx register in use */
|
/* is rdx register in use */
|
||||||
bool rdx_in_use() const { return nargs > 2; }
|
bool rdx_in_use() const { return nargs > 2; }
|
||||||
|
|
||||||
std::pair<std::vector<SymbolicStack::SymbolicLocation>, size_t>
|
std::pair<std::vector<SymbolicStack::Location>, size_t>
|
||||||
arguments_locations(size_t n) {
|
arguments_locations(size_t n) {
|
||||||
using SymbolicLocation = SymbolicStack::SymbolicLocation;
|
using Location = SymbolicStack::Location;
|
||||||
using Register = SymbolicStack::Register;
|
using Register = SymbolicStack::Register;
|
||||||
using Stack = SymbolicStack::Stack;
|
using Stack = SymbolicStack::Stack;
|
||||||
|
|
||||||
|
|
@ -956,34 +933,31 @@ public:
|
||||||
std::vector<::Register::T> result;
|
std::vector<::Register::T> result;
|
||||||
result.insert(result.end(), argument_registers.begin(),
|
result.insert(result.end(), argument_registers.begin(),
|
||||||
argument_registers.begin() + n);
|
argument_registers.begin() + n);
|
||||||
return {
|
return {utils::transform<::Register::T, Location>(
|
||||||
utils::transform<::Register::T, SymbolicLocation>(
|
|
||||||
std::move(result),
|
std::move(result),
|
||||||
[](const auto &r) -> SymbolicLocation { return {Register{r}}; }),
|
[](const auto &r) -> Location { return {Register{r}}; }),
|
||||||
0};
|
0};
|
||||||
} else {
|
} else {
|
||||||
return {utils::concat( //
|
return {utils::concat( //
|
||||||
utils::transform<::Register::T, SymbolicLocation>(
|
utils::transform<::Register::T, Location>(
|
||||||
std::move(argument_registers),
|
std::move(argument_registers),
|
||||||
[](const auto &r) -> SymbolicLocation {
|
[](const auto &r) -> Location { return {Register{r}}; }),
|
||||||
return {Register{r}};
|
std::vector<Location>(
|
||||||
}),
|
|
||||||
std::vector<SymbolicLocation>(
|
|
||||||
n - Registers::argument_registers.size(), {Stack{}})),
|
n - Registers::argument_registers.size(), {Stack{}})),
|
||||||
n - Registers::argument_registers.size()};
|
n - Registers::argument_registers.size()};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* peeks the top of the stack (the stack does not change) */
|
/* peeks the top of the stack (the stack does not change) */
|
||||||
Opnd peek() const { return SymbolicStack::peek(stack); }
|
Opnd peek() const { return stack.peek(); }
|
||||||
|
|
||||||
/* peeks two topmost values from the stack (the stack itself does not
|
/* peeks two topmost values from the stack (the stack itself does not
|
||||||
* change)
|
* change)
|
||||||
*/
|
*/
|
||||||
std::pair<Opnd, Opnd> peek2() const { return ::SymbolicStack::peek2(stack); }
|
std::pair<Opnd, Opnd> peek2() const { return stack.peek2(); }
|
||||||
|
|
||||||
/* tag hash: gets a hash for a string tag */
|
/* tag hash: gets a hash for a string tag */
|
||||||
uint64_t hash(const std::string &tag) {
|
static uint64_t hash(const std::string &tag) {
|
||||||
assert(!tag.empty());
|
assert(!tag.empty());
|
||||||
uint64_t h = 0;
|
uint64_t h = 0;
|
||||||
for (size_t i = 0; i < std::min((tag.size() - 1), 9lu); ++i) {
|
for (size_t i = 0; i < std::min((tag.size() - 1), 9lu); ++i) {
|
||||||
|
|
@ -1071,7 +1045,7 @@ public:
|
||||||
nargs = new_nargs;
|
nargs = new_nargs;
|
||||||
static_size = new_nlocals;
|
static_size = new_nlocals;
|
||||||
stack_slots = new_nlocals;
|
stack_slots = new_nlocals;
|
||||||
stack = SymbolicStack::empty(new_nlocals);
|
stack = SymbolicStack(new_nlocals);
|
||||||
fname = f;
|
fname = f;
|
||||||
has_closure = new_has_closure;
|
has_closure = new_has_closure;
|
||||||
first_line = true;
|
first_line = true;
|
||||||
|
|
@ -1098,8 +1072,7 @@ public:
|
||||||
std::move(array_registers),
|
std::move(array_registers),
|
||||||
[](Register::T &&r) -> Opnd { return {r}; });
|
[](Register::T &&r) -> Opnd { return {r}; });
|
||||||
|
|
||||||
return utils::concat(std::move(array_result),
|
return utils::concat(std::move(array_result), stack.live_registers());
|
||||||
SymbolicStack::live_registers(stack));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool do_opt_stabs() const { return mode.target_os == OS::LINUX; }
|
bool do_opt_stabs() const { return mode.target_os == OS::LINUX; }
|
||||||
|
|
@ -1134,6 +1107,8 @@ public:
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const std::string Env::chars =
|
||||||
|
"_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'";
|
||||||
|
|
||||||
int stack_offset(int i) { return (i >= 0 ? (i + 1) : (-i + 1)) * word_size; }
|
int stack_offset(int i) { return (i >= 0 ? (i + 1) : (-i + 1)) * word_size; }
|
||||||
|
|
||||||
|
|
@ -1549,7 +1524,7 @@ namespace common {
|
||||||
std::pair<size_t, std::vector<Instr>> setup_arguments(Env &env, size_t nargs) {
|
std::pair<size_t, std::vector<Instr>> setup_arguments(Env &env, size_t nargs) {
|
||||||
const auto move_arguments =
|
const auto move_arguments =
|
||||||
[](std::vector<Opnd> &&args,
|
[](std::vector<Opnd> &&args,
|
||||||
std::vector<SymbolicStack::SymbolicLocation> &&arg_locs) {
|
std::vector<SymbolicStack::Location> &&arg_locs) {
|
||||||
using Register = SymbolicStack::Register;
|
using Register = SymbolicStack::Register;
|
||||||
|
|
||||||
assert(args.size() == arg_locs.size());
|
assert(args.size() == arg_locs.size());
|
||||||
|
|
@ -2262,10 +2237,10 @@ std::vector<Instr> compile(const Options &cmd, Env &env,
|
||||||
return compile_call(env, ".elem", 2, false);
|
return compile_call(env, ".elem", 2, false);
|
||||||
},
|
},
|
||||||
[&env](const SMInstr::CALL &x) -> std::vector<Instr> {
|
[&env](const SMInstr::CALL &x) -> std::vector<Instr> {
|
||||||
return compile_call(env, x.fname, x.n, x.tail); // TODO: call
|
return compile_call(env, x.fname, x.n, x.tail); // call
|
||||||
},
|
},
|
||||||
[&env](const SMInstr::CALLC &x) -> std::vector<Instr> {
|
[&env](const SMInstr::CALLC &x) -> std::vector<Instr> {
|
||||||
return compile_call(env, {}, x.n, x.tail); // TODO: closure call
|
return compile_call(env, {}, x.n, x.tail); // closure call
|
||||||
},
|
},
|
||||||
[&env](const SMInstr::SEXP &x) -> std::vector<Instr> {
|
[&env](const SMInstr::SEXP &x) -> std::vector<Instr> {
|
||||||
const auto s = env.allocate();
|
const auto s = env.allocate();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue