Skip to content

Commit 9b0f2f5

Browse files
committed
Reference hax
1 parent de4ac15 commit 9b0f2f5

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

include/Type.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ struct SuperType: Type {
157157

158158
class PointerType: public SuperType, public Makeable<PointerType> {
159159
public:
160-
using SuperType::SuperType;
160+
explicit PointerType(Type *);
161161
Type * copy() const override {
162162
return (new PointerType(subtype != nullptr? subtype->copy() : nullptr))->steal(*this);
163163
}
@@ -282,3 +282,6 @@ struct InitializerType: Type, Makeable<InitializerType> {
282282
protected:
283283
std::string stringify() const override;
284284
};
285+
286+
/** If the argument is a ReferenceType, then its subtype is returned. Otherwise the argument is returned directly. */
287+
Type & unwrap(Type &type);

src/Expr.cpp

+27-7
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ void compileCall(const VregPtr &destination, Function &function, const Context &
4242
auto *expr = std::get<Expr *>(argument);
4343
auto argument_type = expr->getType(context);
4444
argument_register->setType(*argument_type);
45+
4546
if (fn_arg_type->isReference()) {
4647
function.addComment("compileCall: compiling address into reference argument");
4748
if (!expr->compileAddress(argument_register, function, context))
@@ -51,6 +52,7 @@ void compileCall(const VregPtr &destination, Function &function, const Context &
5152
"Structs cannot be directly passed to functions; use a pointer");
5253
} else
5354
expr->compile(argument_register, function, context, 1);
55+
5456
try {
5557
typeCheck(*argument_type, *fn_arg_type, argument_register, function, expr->getLocation());
5658
} catch (std::out_of_range &err) {
@@ -947,11 +949,15 @@ bool VariableExpr::compileAddress(const VregPtr &destination, Function &function
947949
} else {
948950
const size_t offset = function.stackOffsets.at(var);
949951
function.addComment("Get variable lvalue for " + name);
950-
function.add<SubIInstruction>(function.precolored(Why::framePointerOffset), destination,
951-
immLikeReg(destination, static_cast<int>(offset)))->setDebug(*this);
952952
if (var->getType()->isReference()) {
953+
auto temp = function.newVar(destination->getType());
954+
function.add<SubIInstruction>(function.precolored(Why::framePointerOffset), temp,
955+
immLikeReg(temp, static_cast<int>(offset)))->setDebug(*this);
953956
function.addComment("Load reference lvalue for " + name);
954-
function.add<LoadRInstruction>(destination, destination)->setDebug(*this);
957+
function.add<LoadRInstruction>(temp, destination)->setDebug(*this);
958+
} else {
959+
function.add<SubIInstruction>(function.precolored(Why::framePointerOffset), destination,
960+
immLikeReg(destination, static_cast<int>(offset)))->setDebug(*this);
955961
}
956962
}
957963
} else if (const auto fn = context.scope->lookupFunction(name, getLocation())) {
@@ -1058,10 +1064,17 @@ std::string StringExpr::getID(Program &program) const {
10581064
void DerefExpr::compile(VregPtr destination, Function &function, const Context &context, size_t multiplier) {
10591065
if (auto fnptr = getOperator(context)) {
10601066
compileCall(destination, function, context, fnptr, {subexpr.get()}, getLocation(), multiplier);
1061-
} else {
1067+
} else if (destination) {
10621068
checkType(context);
1063-
subexpr->compile(destination, function, context, multiplier);
1064-
function.add<LoadRInstruction>(destination, destination)->setDebug(*this);
1069+
auto type = TypePtr(getType(context));
1070+
auto temp = function.newVar(type);
1071+
subexpr->compile(temp, function, context, multiplier);
1072+
function.addComment("Loading in DerefExpr::compile");
1073+
if (auto ref = type->ptrcast<ReferenceType>()) // Pointers to references really shouldn't be a thing..
1074+
destination->setType(*ref->subtype);
1075+
else
1076+
destination->setType(*type);
1077+
function.add<LoadRInstruction>(temp, destination)->setDebug(*this);
10651078
}
10661079
}
10671080

@@ -1419,14 +1432,20 @@ void AssignExpr::compile(VregPtr destination, Function &function, const Context
14191432
if (auto fnptr = function.program.getOperator({left_type.get(), right_type.get()}, CPMTOK_ASSIGN, getLocation())) {
14201433
compileCall(destination, function, context, fnptr, {left.get(), right.get()}, getLocation(), multiplier);
14211434
} else {
1435+
function.addComment("Begin assignment");
14221436
auto addr_var = function.newVar();
14231437
if (!destination)
14241438
destination = function.newVar();
14251439
TypePtr right_type = right->getType(context);
1440+
14261441
if (!left->compileAddress(addr_var, function, context))
14271442
throw LvalueError(std::string(*left->getType(context)));
1428-
if (destination)
1443+
1444+
if (destination) {
1445+
info() << getLocation() << ": " << *addr_var->getType() << '\n';
14291446
destination->setType(*addr_var->getType());
1447+
}
1448+
14301449
if (right_type->isInitializer()) {
14311450
auto *initializer_expr = right->cast<InitializerExpr>();
14321451
if (initializer_expr->isConstructor) {
@@ -1462,6 +1481,7 @@ void AssignExpr::compile(VregPtr destination, Function &function, const Context
14621481
function.add<MultIInstruction>(destination, destination, immLikeReg(destination,
14631482
static_cast<int>(multiplier)))->setDebug(*this);
14641483
}
1484+
function.addComment("End assignment");
14651485
}
14661486
}
14671487

src/Type.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
#include "Scope.h"
1212
#include "Type.h"
1313

14+
Type & unwrap(Type &type) {
15+
if (auto *ref = type.cast<ReferenceType>())
16+
return *ref->subtype;
17+
return type;
18+
}
19+
1420
Type::operator std::string() const {
1521
if (isConst)
1622
return (isLvalue? "^" : "") + stringify() + " const";
@@ -81,6 +87,16 @@ SuperType::operator OperandType() const {
8187
return out;
8288
}
8389

90+
PointerType::PointerType(Type *subtype_): SuperType(nullptr) {
91+
if (auto *ref = subtype_->cast<ReferenceType>()) {
92+
subtype = ref->subtype;
93+
ref->subtype = nullptr;
94+
delete ref;
95+
} else {
96+
subtype = subtype_;
97+
}
98+
}
99+
84100
bool PointerType::similar(const Type &other, bool ignore_const) const {
85101
if (other.isReferenceOf(*this, ignore_const))
86102
return isLvalue;

0 commit comments

Comments
 (0)