diff -r c4b1341297e5 -r ba85a47ee414 src/compiler/HIR.h --- a/src/compiler/HIR.h Mon Jun 10 00:46:29 2013 +0100 +++ b/src/compiler/HIR.h Mon Jun 10 01:04:43 2013 +0100 @@ -1,607 +1,607 @@ -/* - * Copyright (C) 2012 David Anderson - * - * This file is part of SourcePawn. - * - * SourcePawn is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free - * Software Foundation, either version 3 of the License, or (at your option) - * any later version. - * - * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * SourcePawn. If not, see http://www.gnu.org/licenses/. - */ -#ifndef _include_sp2_hir_h_ -#define _include_sp2_hir_h_ - -#include "../Types.h" -#include "../PoolAllocator.h" -#include "../Opcodes.h" -#include "Symbols.h" - -namespace ke { - -#define HIR_OPS(_) \ - _(Call) \ - _(Boolean) \ - _(Integer) \ - _(Float) \ - _(String) \ - _(Import) \ - _(Array) \ - _(Store) \ - _(ToRef) \ - _(NewDependentArray) \ - /* Special LValue types */ \ - _(Index) \ - _(Local) \ - _(Global) \ - _(Field) \ - /* End LValues */ \ - _(Unary) \ - _(Binary) \ - _(Convert) \ - _(PostIncDec) - -// Forward declarations. -#define _(name) class H##name; -HIR_OPS(_) -#undef _ - -class HIRVisitor; -class AstNode; -class HLValue; -class Array; - -class HIR : public PoolObject -{ - public: - enum HOp { -#define _(name) k##name, - HIR_OPS(_) -#undef _ - kTotalOps - }; - - public: - HIR(AstNode *node, Type *type) - : node_(node), - type_(type) - { - } - - Handle type() { - return type_; - } - AstNode *node() const { - return node_; - } - - virtual bool isLValue() const { - return false; - } - - virtual HOp op() const = 0; - virtual void accept(HIRVisitor *visitor) = 0; - -#define _(name) \ - bool is##name() const { \ - return op() == k##name; \ - } \ - H##name *to##name() { \ - assert(is##name()); \ - return reinterpret_cast(this); \ - } - HIR_OPS(_) -#undef _ - - HLValue *toLValue() { - assert(isLValue()); - return reinterpret_cast(this); - } - - private: - AstNode *node_; - ScopedRoot type_; -}; - -class BytecodeEmitter; - -class HIRVisitor -{ - public: -#define _(name) \ - virtual void visit##name(H##name *hir) { \ - assert(false); \ - } - HIR_OPS(_) -#undef _ -}; - -typedef PoolList HIRList; - -#define DEFINE_HIR(name) \ - virtual HOp op() const { \ - return k##name; \ - } \ - virtual void accept(HIRVisitor *visitor) { \ - visitor->visit##name(this); \ - } - -class HBoolean : public HIR -{ - public: - HBoolean(AstNode *node, Type *type, bool value) - : HIR(node, type), - value_(value) - { - } - - DEFINE_HIR(Boolean); - bool value() const { - return value_; - } - - private: - bool value_; -}; - -class HInteger : public HIR -{ - public: - HInteger(AstNode *node, Type *type, int value) - : HIR(node, type), - value_(value) - { - } - - DEFINE_HIR(Integer); - int value() const { - return value_; - } - - private: - int value_; -}; - -class HString : public HIR -{ - public: - HString(AstNode *node, Type *type, String *string) - : HIR(node, type), - string_(string) - { - } - - DEFINE_HIR(String); - Handle string() const { - return string_; - } - - private: - ScopedRoot string_; -}; - -class HImport : public HIR -{ - public: - HImport(AstNode *node, Type *type, unsigned index) - : HIR(node, type), - index_(index) - { - } - - DEFINE_HIR(Import); - unsigned index() const { - return index_; - } - - private: - unsigned index_; -}; - -class HArray : public HIR -{ - public: - HArray(AstNode *node, Type *type, Array *array, bool duplicate) - : HIR(node, type), - array_(array), - duplicate_(duplicate) - { - } - - DEFINE_HIR(Array); - Handle array() const { - return array_; - } - bool duplicate() const { - return duplicate_; - } - - private: - ScopedRoot array_; - bool duplicate_; -}; - -class HConvert : public HIR -{ - public: - HConvert(AstNode *node, Type *type, Opcode op, HIR *in) - : HIR(node, type), - op_(op), - in_(in) - { - } - - DEFINE_HIR(Convert); - Opcode opcode() const { - return op_; - } - HIR *in() const { - return in_; - } - - private: - Opcode op_; - HIR *in_; -}; - -class HLValue : public HIR -{ - public: - HLValue(AstNode *node, Type *type) - : HIR(node, type) - { - } - - // Pushes a reference to the LValue on the stack. - virtual void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_) = 0; - - // Duplicates a stack reference. - virtual void hold(BytecodeEmitter &emitter_) = 0; - - // Reorders the stack for a post-increment operation: - // REF VAL -> VAL REF VAL - virtual void swapAndPick(BytecodeEmitter &emitter_) = 0; - - // Given a stack layout of the form: - // [-1] value - // [-2..n] ref - // - // Emits a store to the reference. - virtual void store(BytecodeEmitter &emitter_) = 0; - virtual void load(BytecodeEmitter &emitter_) = 0; - - // Try to make a direct reference, if semantics allow it. False if the - // caller must allocate a reference to the stack. - virtual bool ref(BytecodeEmitter &emitter_) = 0; - - bool isLValue() const { - return true; - } -}; - -class HLocal : public HLValue -{ - public: - HLocal(AstNode *node, VariableSymbol *sym); - - DEFINE_HIR(Local); - - // Pushes a reference to the LValue on the stack. - void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); - void hold(BytecodeEmitter &emitter_); - void swapAndPick(BytecodeEmitter &emitter_); - void store(BytecodeEmitter &emitter_); - void load(BytecodeEmitter &emitter_); - bool ref(BytecodeEmitter &emitter_); - - VariableSymbol *sym() const { - return sym_; - } - - private: - VariableSymbol *sym_; -}; - -class HIndex : public HLValue -{ - public: - HIndex(AstNode *node, Type *type, HIR *left, HIR *right) - : HLValue(node, type), - left_(left), - right_(right) - { - } - - DEFINE_HIR(Index); - - void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); - void hold(BytecodeEmitter &emitter_); - void swapAndPick(BytecodeEmitter &emitter_); - void store(BytecodeEmitter &emitter_); - void load(BytecodeEmitter &emitter_); - bool ref(BytecodeEmitter &emitter_); - - HIR *base() const { - return left_; - } - HIR *index() const { - return right_; - } - - private: - HIR *left_; - HIR *right_; -}; - -class HField : public HLValue -{ - public: - HField(AstNode *node, HIR *left, Type *type, unsigned index) - : HLValue(node, type), - base_(left), - index_(index) - { - } - - DEFINE_HIR(Field); - - void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); - void hold(BytecodeEmitter &emitter_); - void swapAndPick(BytecodeEmitter &emitter_); - void store(BytecodeEmitter &emitter_); - void load(BytecodeEmitter &emitter_); - bool ref(BytecodeEmitter &emitter_); - - HIR *base() const { - return base_; - } - unsigned index() const { - return index_; - } - - private: - HIR *base_; - unsigned index_; -}; - -class HGlobal : public HLValue -{ - public: - HGlobal(AstNode *node, Symbol *sym) - : HLValue(node, sym->type()), - sym_(sym) - { - } - - DEFINE_HIR(Global); - - void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); - void hold(BytecodeEmitter &emitter_); - void swapAndPick(BytecodeEmitter &emitter_); - void store(BytecodeEmitter &emitter_); - void load(BytecodeEmitter &emitter_); - bool ref(BytecodeEmitter &emitter_); - - Symbol *sym() const { - return sym_; - } - - private: - Symbol *sym_; -}; - -class HBinary : public HIR -{ - public: - HBinary(AstNode *node, Type *type, TokenKind token, HIR *left, HIR *right) - : HIR(node, type), - token_(token), - left_(left), - right_(right) - { - } - - DEFINE_HIR(Binary); - TokenKind token() const { - return token_; - } - HIR *left() const { - return left_; - } - HIR *right() const { - return right_; - } - - private: - TokenKind token_; - HIR *left_; - HIR *right_; -}; - -class HFloat : public HIR -{ - public: - HFloat(AstNode *node, Type *type, float value) - : HIR(node, type), - value_(value) - { - } - - DEFINE_HIR(Float); - float value() const { - return value_; - } - - private: - float value_; -}; - -class HUnary : public HIR -{ - public: - HUnary(AstNode *node, Type *type, TokenKind tok, HIR *in) - : HIR(node, type), - in_(in), - token_(tok) - { - } - - DEFINE_HIR(Unary); - HIR *in() const { - return in_; - } - TokenKind token() const { - return token_; - } - - private: - HIR *in_; - TokenKind token_; -}; - -class HStore : public HIR -{ - public: - HStore(AstNode *node, HLValue *lval, HIR *rval) - : HIR(node, lval->type()), - kind_(TOK_ASSIGN), - lval_(lval), - rval_(rval) - { - } - - HStore(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval) - : HIR(node, lval->type()), - kind_(kind), - lval_(lval), - rval_(rval) - { - } - - DEFINE_HIR(Store); - - HLValue *lval() const { - return lval_; - } - HIR *rval() const { - return rval_; - } - TokenKind kind() const { - return kind_; - } - - private: - TokenKind kind_; - HLValue *lval_; - HIR *rval_; -}; - -class HPostIncDec : public HIR -{ - public: - HPostIncDec(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval) - : HIR(node, lval->type()), - kind_(kind), - lval_(lval), - rval_(rval) - { - } - - DEFINE_HIR(PostIncDec); - - HLValue *lval() const { - return lval_; - } - HIR *rval() const { - return rval_; - } - TokenKind kind() const { - return kind_; - } - - private: - TokenKind kind_; - HLValue *lval_; - HIR *rval_; -}; - -class HCall : public HIR -{ - public: - HCall(AstNode *node, Type *type, HIR *callee, HIRList *args) - : HIR(node, type), - callee_(callee), - args_(args) - { - } - - DEFINE_HIR(Call); - - HIR *callee() const { - return callee_; - } - HIRList *args() const { - return args_; - } - - private: - HIR *callee_; - HIRList *args_; -}; - -class HToRef : public HIR -{ - public: - HToRef(AstNode *node, Type *type, HIR *in) - : HIR(node, type), - in_(in) - { - } - - DEFINE_HIR(ToRef); - - HIR *in() const { - return in_; - } - - private: - HIR *in_; -}; - -class HNewDependentArray : public HIR -{ - public: - HNewDependentArray(AstNode *node, Type *type, HIR *base, HIR *index) - : HIR(node, type), - base_(base), - index_(index) - { - } - - DEFINE_HIR(NewDependentArray); - - HIR *base() const { - return base_; - } - HIR *index() const { - return index_; - } - - private: - HIR *base_; - HIR *index_; -}; - -#undef DEFINE_HIR - -void EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir); - -} - -#endif // _include_sp2_hir_h_ +/* + * Copyright (C) 2012 David Anderson + * + * This file is part of SourcePawn. + * + * SourcePawn is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) + * any later version. + * + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * SourcePawn. If not, see http://www.gnu.org/licenses/. + */ +#ifndef _include_sp2_hir_h_ +#define _include_sp2_hir_h_ + +#include "../Types.h" +#include "../PoolAllocator.h" +#include "../Opcodes.h" +#include "Symbols.h" + +namespace ke { + +#define HIR_OPS(_) \ + _(Call) \ + _(Boolean) \ + _(Integer) \ + _(Float) \ + _(String) \ + _(Import) \ + _(Array) \ + _(Store) \ + _(ToRef) \ + _(NewDependentArray) \ + /* Special LValue types */ \ + _(Index) \ + _(Local) \ + _(Global) \ + _(Field) \ + /* End LValues */ \ + _(Unary) \ + _(Binary) \ + _(Convert) \ + _(PostIncDec) + +// Forward declarations. +#define _(name) class H##name; +HIR_OPS(_) +#undef _ + +class HIRVisitor; +class AstNode; +class HLValue; +class Array; + +class HIR : public PoolObject +{ + public: + enum HOp { +#define _(name) k##name, + HIR_OPS(_) +#undef _ + kTotalOps + }; + + public: + HIR(AstNode *node, Type *type) + : node_(node), + type_(type) + { + } + + Handle type() { + return type_; + } + AstNode *node() const { + return node_; + } + + virtual bool isLValue() const { + return false; + } + + virtual HOp op() const = 0; + virtual void accept(HIRVisitor *visitor) = 0; + +#define _(name) \ + bool is##name() const { \ + return op() == k##name; \ + } \ + H##name *to##name() { \ + assert(is##name()); \ + return reinterpret_cast(this); \ + } + HIR_OPS(_) +#undef _ + + HLValue *toLValue() { + assert(isLValue()); + return reinterpret_cast(this); + } + + private: + AstNode *node_; + ScopedRoot type_; +}; + +class BytecodeEmitter; + +class HIRVisitor +{ + public: +#define _(name) \ + virtual void visit##name(H##name *hir) { \ + assert(false); \ + } + HIR_OPS(_) +#undef _ +}; + +typedef PoolList HIRList; + +#define DEFINE_HIR(name) \ + virtual HOp op() const { \ + return k##name; \ + } \ + virtual void accept(HIRVisitor *visitor) { \ + visitor->visit##name(this); \ + } + +class HBoolean : public HIR +{ + public: + HBoolean(AstNode *node, Type *type, bool value) + : HIR(node, type), + value_(value) + { + } + + DEFINE_HIR(Boolean); + bool value() const { + return value_; + } + + private: + bool value_; +}; + +class HInteger : public HIR +{ + public: + HInteger(AstNode *node, Type *type, int value) + : HIR(node, type), + value_(value) + { + } + + DEFINE_HIR(Integer); + int value() const { + return value_; + } + + private: + int value_; +}; + +class HString : public HIR +{ + public: + HString(AstNode *node, Type *type, String *string) + : HIR(node, type), + string_(string) + { + } + + DEFINE_HIR(String); + Handle string() const { + return string_; + } + + private: + ScopedRoot string_; +}; + +class HImport : public HIR +{ + public: + HImport(AstNode *node, Type *type, unsigned index) + : HIR(node, type), + index_(index) + { + } + + DEFINE_HIR(Import); + unsigned index() const { + return index_; + } + + private: + unsigned index_; +}; + +class HArray : public HIR +{ + public: + HArray(AstNode *node, Type *type, Array *array, bool duplicate) + : HIR(node, type), + array_(array), + duplicate_(duplicate) + { + } + + DEFINE_HIR(Array); + Handle array() const { + return array_; + } + bool duplicate() const { + return duplicate_; + } + + private: + ScopedRoot array_; + bool duplicate_; +}; + +class HConvert : public HIR +{ + public: + HConvert(AstNode *node, Type *type, Opcode op, HIR *in) + : HIR(node, type), + op_(op), + in_(in) + { + } + + DEFINE_HIR(Convert); + Opcode opcode() const { + return op_; + } + HIR *in() const { + return in_; + } + + private: + Opcode op_; + HIR *in_; +}; + +class HLValue : public HIR +{ + public: + HLValue(AstNode *node, Type *type) + : HIR(node, type) + { + } + + // Pushes a reference to the LValue on the stack. + virtual void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_) = 0; + + // Duplicates a stack reference. + virtual void hold(BytecodeEmitter &emitter_) = 0; + + // Reorders the stack for a post-increment operation: + // REF VAL -> VAL REF VAL + virtual void swapAndPick(BytecodeEmitter &emitter_) = 0; + + // Given a stack layout of the form: + // [-1] value + // [-2..n] ref + // + // Emits a store to the reference. + virtual void store(BytecodeEmitter &emitter_) = 0; + virtual void load(BytecodeEmitter &emitter_) = 0; + + // Try to make a direct reference, if semantics allow it. False if the + // caller must allocate a reference to the stack. + virtual bool ref(BytecodeEmitter &emitter_) = 0; + + bool isLValue() const { + return true; + } +}; + +class HLocal : public HLValue +{ + public: + HLocal(AstNode *node, VariableSymbol *sym); + + DEFINE_HIR(Local); + + // Pushes a reference to the LValue on the stack. + void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); + void hold(BytecodeEmitter &emitter_); + void swapAndPick(BytecodeEmitter &emitter_); + void store(BytecodeEmitter &emitter_); + void load(BytecodeEmitter &emitter_); + bool ref(BytecodeEmitter &emitter_); + + VariableSymbol *sym() const { + return sym_; + } + + private: + VariableSymbol *sym_; +}; + +class HIndex : public HLValue +{ + public: + HIndex(AstNode *node, Type *type, HIR *left, HIR *right) + : HLValue(node, type), + left_(left), + right_(right) + { + } + + DEFINE_HIR(Index); + + void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); + void hold(BytecodeEmitter &emitter_); + void swapAndPick(BytecodeEmitter &emitter_); + void store(BytecodeEmitter &emitter_); + void load(BytecodeEmitter &emitter_); + bool ref(BytecodeEmitter &emitter_); + + HIR *base() const { + return left_; + } + HIR *index() const { + return right_; + } + + private: + HIR *left_; + HIR *right_; +}; + +class HField : public HLValue +{ + public: + HField(AstNode *node, HIR *left, Type *type, unsigned index) + : HLValue(node, type), + base_(left), + index_(index) + { + } + + DEFINE_HIR(Field); + + void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); + void hold(BytecodeEmitter &emitter_); + void swapAndPick(BytecodeEmitter &emitter_); + void store(BytecodeEmitter &emitter_); + void load(BytecodeEmitter &emitter_); + bool ref(BytecodeEmitter &emitter_); + + HIR *base() const { + return base_; + } + unsigned index() const { + return index_; + } + + private: + HIR *base_; + unsigned index_; +}; + +class HGlobal : public HLValue +{ + public: + HGlobal(AstNode *node, Symbol *sym) + : HLValue(node, sym->type()), + sym_(sym) + { + } + + DEFINE_HIR(Global); + + void bind(HIRVisitor *visitor, BytecodeEmitter &emitter_); + void hold(BytecodeEmitter &emitter_); + void swapAndPick(BytecodeEmitter &emitter_); + void store(BytecodeEmitter &emitter_); + void load(BytecodeEmitter &emitter_); + bool ref(BytecodeEmitter &emitter_); + + Symbol *sym() const { + return sym_; + } + + private: + Symbol *sym_; +}; + +class HBinary : public HIR +{ + public: + HBinary(AstNode *node, Type *type, TokenKind token, HIR *left, HIR *right) + : HIR(node, type), + token_(token), + left_(left), + right_(right) + { + } + + DEFINE_HIR(Binary); + TokenKind token() const { + return token_; + } + HIR *left() const { + return left_; + } + HIR *right() const { + return right_; + } + + private: + TokenKind token_; + HIR *left_; + HIR *right_; +}; + +class HFloat : public HIR +{ + public: + HFloat(AstNode *node, Type *type, float value) + : HIR(node, type), + value_(value) + { + } + + DEFINE_HIR(Float); + float value() const { + return value_; + } + + private: + float value_; +}; + +class HUnary : public HIR +{ + public: + HUnary(AstNode *node, Type *type, TokenKind tok, HIR *in) + : HIR(node, type), + in_(in), + token_(tok) + { + } + + DEFINE_HIR(Unary); + HIR *in() const { + return in_; + } + TokenKind token() const { + return token_; + } + + private: + HIR *in_; + TokenKind token_; +}; + +class HStore : public HIR +{ + public: + HStore(AstNode *node, HLValue *lval, HIR *rval) + : HIR(node, lval->type()), + kind_(TOK_ASSIGN), + lval_(lval), + rval_(rval) + { + } + + HStore(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval) + : HIR(node, lval->type()), + kind_(kind), + lval_(lval), + rval_(rval) + { + } + + DEFINE_HIR(Store); + + HLValue *lval() const { + return lval_; + } + HIR *rval() const { + return rval_; + } + TokenKind kind() const { + return kind_; + } + + private: + TokenKind kind_; + HLValue *lval_; + HIR *rval_; +}; + +class HPostIncDec : public HIR +{ + public: + HPostIncDec(AstNode *node, TokenKind kind, HLValue *lval, HIR *rval) + : HIR(node, lval->type()), + kind_(kind), + lval_(lval), + rval_(rval) + { + } + + DEFINE_HIR(PostIncDec); + + HLValue *lval() const { + return lval_; + } + HIR *rval() const { + return rval_; + } + TokenKind kind() const { + return kind_; + } + + private: + TokenKind kind_; + HLValue *lval_; + HIR *rval_; +}; + +class HCall : public HIR +{ + public: + HCall(AstNode *node, Type *type, HIR *callee, HIRList *args) + : HIR(node, type), + callee_(callee), + args_(args) + { + } + + DEFINE_HIR(Call); + + HIR *callee() const { + return callee_; + } + HIRList *args() const { + return args_; + } + + private: + HIR *callee_; + HIRList *args_; +}; + +class HToRef : public HIR +{ + public: + HToRef(AstNode *node, Type *type, HIR *in) + : HIR(node, type), + in_(in) + { + } + + DEFINE_HIR(ToRef); + + HIR *in() const { + return in_; + } + + private: + HIR *in_; +}; + +class HNewDependentArray : public HIR +{ + public: + HNewDependentArray(AstNode *node, Type *type, HIR *base, HIR *index) + : HIR(node, type), + base_(base), + index_(index) + { + } + + DEFINE_HIR(NewDependentArray); + + HIR *base() const { + return base_; + } + HIR *index() const { + return index_; + } + + private: + HIR *base_; + HIR *index_; +}; + +#undef DEFINE_HIR + +void EmitHIR(Zone *zone, BytecodeEmitter &emitter, HIR *hir); + +} + +#endif // _include_sp2_hir_h_