allow aliasing of registers in variables if we explictly ask for it (#711)

This commit is contained in:
water111
2021-07-22 20:14:08 -04:00
committed by GitHub
parent 36ccf341a9
commit 09c09ce35f
4 changed files with 48 additions and 13 deletions
+2 -1
View File
@@ -180,4 +180,5 @@
- Fields with type `(inline-array thing)` can now be set in statics.
- `meters`, `degrees`, and `seconds` types have been added.
- Bitfields with `symbol` fields used in an immediate `(new 'static ...)` can now define the symbol in the `new` form.
- Bitfields with `float` fields used in an immediate `(new 'static ...)` in code can use a non-constant floating point value.
- Bitfields with `float` fields used in an immediate `(new 'static ...)` in code can use a non-constant floating point value.
- Multiple variables assigned to the same register using `:reg` in `rlet` (or overlapping with `self` in a behavior) will now be merged to a single variable instead of causing a compiler error. Variables will have their own type, but they will all be an alias of the same exact register.
+5
View File
@@ -302,6 +302,11 @@ StackVarAddrVal* FunctionEnv::allocate_aligned_stack_variable(const TypeSpec& ts
return result;
}
RegVal* FunctionEnv::push_reg_val(std::unique_ptr<RegVal> in) {
m_iregs.push_back(std::move(in));
return m_iregs.back().get();
}
///////////////////
// LexicalEnv
///////////////////
+2
View File
@@ -208,6 +208,8 @@ class FunctionEnv : public DeclareEnv {
const std::vector<std::unique_ptr<RegVal>>& reg_vals() const { return m_iregs; }
RegVal* push_reg_val(std::unique_ptr<RegVal> in);
int segment = -1;
std::string method_of_type_name = "#f";
bool is_asm_func = false;
+39 -12
View File
@@ -75,21 +75,48 @@ Val* Compiler::compile_rlet(const goos::Object& form, const goos::Object& rest,
}
// alloc a register:
auto new_place_reg = env->make_ireg(ts, register_class);
new_place_reg->mark_as_settable();
RegVal* new_place_reg = nullptr;
if (def_args.has_named("reg")) {
IRegConstraint constraint;
constraint.ireg = new_place_reg->ireg();
constraint.contrain_everywhere = true;
constraint.desired_register = parse_register(def_args.named.at("reg"));
if (def_args.has_named("reset-here") &&
get_true_or_false(form, def_args.get_named("reset-here"))) {
reset_regs.push_back(new_place_reg);
auto desired_register = parse_register(def_args.named.at("reg"));
// we want to see if we already created a variable for this register, and reuse it.
for (auto& constr : fenv->constraints()) {
if (constr.desired_register == desired_register && constr.contrain_everywhere) {
auto reg_val_ptr = std::make_unique<RegVal>(constr.ireg, ts);
new_place_reg = fenv->push_reg_val(std::move(reg_val_ptr));
new_place_reg->mark_as_settable();
break;
}
}
new_place_reg->set_rlet_constraint(constraint.desired_register);
constraints.push_back(constraint);
if (!new_place_reg) {
for (auto& constr : constraints) {
if (constr.desired_register == desired_register && constr.contrain_everywhere) {
auto reg_val_ptr = std::make_unique<RegVal>(constr.ireg, ts);
new_place_reg = fenv->push_reg_val(std::move(reg_val_ptr));
new_place_reg->mark_as_settable();
break;
}
}
}
}
if (!new_place_reg) {
new_place_reg = env->make_ireg(ts, register_class);
new_place_reg->mark_as_settable();
if (def_args.has_named("reg")) {
IRegConstraint constraint;
constraint.ireg = new_place_reg->ireg();
constraint.contrain_everywhere = true;
constraint.desired_register = parse_register(def_args.named.at("reg"));
if (def_args.has_named("reset-here") &&
get_true_or_false(form, def_args.get_named("reset-here"))) {
reset_regs.push_back(new_place_reg);
}
new_place_reg->set_rlet_constraint(constraint.desired_register);
constraints.push_back(constraint);
}
}
lenv->vars[new_place_name.as_symbol()->name] = new_place_reg;