|
|
@@ -39,14 +39,16 @@ struct Identity {
|
|
|
};
|
|
|
|
|
|
template <bool scalar>
|
|
|
-struct RegWrapper {
|
|
|
- RegWrapper(EmitContext& ctx, Value value)
|
|
|
- : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} {
|
|
|
- if (allocated) {
|
|
|
+class RegWrapper {
|
|
|
+public:
|
|
|
+ RegWrapper(EmitContext& ctx, const IR::Value& ir_value) : reg_alloc{ctx.reg_alloc} {
|
|
|
+ const Value value{reg_alloc.Peek(ir_value)};
|
|
|
+ if (value.type == Type::Register) {
|
|
|
+ inst = ir_value.InstRecursive();
|
|
|
+ reg = Register{value};
|
|
|
+ } else {
|
|
|
const bool is_long{value.type == Type::F64 || value.type == Type::U64};
|
|
|
reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg();
|
|
|
- } else {
|
|
|
- reg = Register{value};
|
|
|
}
|
|
|
switch (value.type) {
|
|
|
case Type::Register:
|
|
|
@@ -68,8 +70,11 @@ struct RegWrapper {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
~RegWrapper() {
|
|
|
- if (allocated) {
|
|
|
+ if (inst) {
|
|
|
+ reg_alloc.Unref(*inst);
|
|
|
+ } else {
|
|
|
reg_alloc.FreeReg(reg);
|
|
|
}
|
|
|
}
|
|
|
@@ -78,19 +83,42 @@ struct RegWrapper {
|
|
|
return std::conditional_t<scalar, ScalarRegister, Register>{Value{reg}};
|
|
|
}
|
|
|
|
|
|
+private:
|
|
|
RegAlloc& reg_alloc;
|
|
|
+ IR::Inst* inst{};
|
|
|
Register reg{};
|
|
|
- bool allocated{};
|
|
|
+};
|
|
|
+
|
|
|
+template <typename ArgType>
|
|
|
+class ValueWrapper {
|
|
|
+public:
|
|
|
+ ValueWrapper(EmitContext& ctx, const IR::Value& ir_value_)
|
|
|
+ : reg_alloc{ctx.reg_alloc}, ir_value{ir_value_}, value{reg_alloc.Peek(ir_value)} {}
|
|
|
+
|
|
|
+ ~ValueWrapper() {
|
|
|
+ if (!ir_value.IsImmediate()) {
|
|
|
+ reg_alloc.Unref(*ir_value.InstRecursive());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ArgType Extract() {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+private:
|
|
|
+ RegAlloc& reg_alloc;
|
|
|
+ const IR::Value& ir_value;
|
|
|
+ ArgType value;
|
|
|
};
|
|
|
|
|
|
template <typename ArgType>
|
|
|
auto Arg(EmitContext& ctx, const IR::Value& arg) {
|
|
|
if constexpr (std::is_same_v<ArgType, Register>) {
|
|
|
- return RegWrapper<false>{ctx, ctx.reg_alloc.Consume(arg)};
|
|
|
+ return RegWrapper<false>{ctx, arg};
|
|
|
} else if constexpr (std::is_same_v<ArgType, ScalarRegister>) {
|
|
|
- return RegWrapper<true>{ctx, ctx.reg_alloc.Consume(arg)};
|
|
|
+ return RegWrapper<true>{ctx, arg};
|
|
|
} else if constexpr (std::is_base_of_v<Value, ArgType>) {
|
|
|
- return Identity{ArgType{ctx.reg_alloc.Consume(arg)}};
|
|
|
+ return ValueWrapper<ArgType>{ctx, arg};
|
|
|
} else if constexpr (std::is_same_v<ArgType, const IR::Value&>) {
|
|
|
return Identity{arg};
|
|
|
} else if constexpr (std::is_same_v<ArgType, u32>) {
|