1.1 --- a/src/compiler/HIR.cpp Mon Nov 19 02:12:13 2012 -0800
1.2 +++ b/src/compiler/HIR.cpp Thu Dec 20 00:59:38 2012 -0800
1.3 @@ -47,6 +47,7 @@
1.4 void visitConvert(HConvert *convert);
1.5 void visitIndex(HIndex *index);
1.6 void visitPostIncDec(HPostIncDec *hir);
1.7 + void visitToRef(HToRef *hir);
1.8
1.9 private:
1.10 Zone *zone_;
1.11 @@ -114,6 +115,26 @@
1.12 __ getglobal(sym_);
1.13 }
1.14
1.15 +bool
1.16 +HGlobal::ref(BytecodeEmitter &emitter_)
1.17 +{
1.18 + return false;
1.19 +}
1.20 +
1.21 +static inline Type *
1.22 +MaybeDereference(Type *type)
1.23 +{
1.24 + if (type->isReference())
1.25 + return ReferenceType::cast(type)->contained();
1.26 + return type;
1.27 +}
1.28 +
1.29 +HLocal::HLocal(AstNode *node, VariableSymbol *sym)
1.30 + : HLValue(node, MaybeDereference(sym->type())),
1.31 + sym_(sym)
1.32 +{
1.33 +}
1.34 +
1.35 void
1.36 HLocal::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
1.37 {
1.38 @@ -149,7 +170,7 @@
1.39 HLocal::store(BytecodeEmitter &emitter_)
1.40 {
1.41 if (sym_->type()->isReference()) {
1.42 - __ setref(sym_->type()->contained_ref());
1.43 + __ setref(ReferenceType::cast(sym_->type())->contained());
1.44 } else {
1.45 if (sym_->storage() == VariableSymbol::Local)
1.46 __ setlocal(sym_);
1.47 @@ -164,7 +185,7 @@
1.48 HLocal::load(BytecodeEmitter &emitter_)
1.49 {
1.50 if (sym_->type()->isReference())
1.51 - __ getref(sym_->type());
1.52 + __ getref(ReferenceType::cast(sym_->type())->contained());
1.53 else if (sym_->storage() == VariableSymbol::Local)
1.54 __ getlocal(sym_);
1.55 else if (sym_->storage() == VariableSymbol::Arg)
1.56 @@ -173,6 +194,33 @@
1.57 assert(false);
1.58 }
1.59
1.60 +bool
1.61 +HLocal::ref(BytecodeEmitter &emitter_)
1.62 +{
1.63 + if (sym_->storage() == VariableSymbol::Heap) {
1.64 + // Closing over a reference should never pass SemA.
1.65 + assert(!sym_->type()->isReference());
1.66 +
1.67 + // We don't support direct references to heap-allocated locals. This
1.68 + // should probably be banned in SemA? But for now, just assert. :TODO:
1.69 + assert(false);
1.70 + return false;
1.71 + }
1.72 +
1.73 + if (sym_->type()->isReference()) {
1.74 + if (sym_->storage() == VariableSymbol::Local)
1.75 + __ getlocal(sym_);
1.76 + else if (sym_->storage() == VariableSymbol::Arg)
1.77 + __ getarg(sym_);
1.78 + else
1.79 + assert(false);
1.80 + } else {
1.81 + __ newref(sym_);
1.82 + }
1.83 +
1.84 + return true;
1.85 +}
1.86 +
1.87 void
1.88 HIndex::bind(HIRVisitor *visitor, BytecodeEmitter &emitter_)
1.89 {
1.90 @@ -208,6 +256,12 @@
1.91 __ getelem(type());
1.92 }
1.93
1.94 +bool
1.95 +HIndex::ref(BytecodeEmitter &emitter_)
1.96 +{
1.97 + return false;
1.98 +}
1.99 +
1.100 void
1.101 HIRTranslator::visitLocal(HLocal *local)
1.102 {
1.103 @@ -350,6 +404,20 @@
1.104 }
1.105
1.106 void
1.107 +HIRTranslator::visitToRef(HToRef *hir)
1.108 +{
1.109 + HIR *in = hir->in();
1.110 +
1.111 + // See if we can bind a direct reference.
1.112 + if (in->isLValue() && in->toLValue()->ref(emitter_))
1.113 + return;
1.114 +
1.115 + // No, we can't. So instead we create an on-stack reference.
1.116 + in->accept(this);
1.117 + __ slotref_lifo();
1.118 +}
1.119 +
1.120 +void
1.121 ke::EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir)
1.122 {
1.123 HIRTranslator translator(zone, emitter);