text: // Copyright 2010 the V8 project authors. All rights reserved.
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  //     * Redistributions of source code must retain the above copyright
  //       notice, this list of conditions and the following disclaimer.
  //     * Redistributions in binary form must reproduce the above
  //       copyright notice, this list of conditions and the following
  //       disclaimer in the documentation and/or other materials provided
  //       with the distribution.
  //     * Neither the name of Google Inc. nor the names of its
  //       contributors may be used to endorse or promote products derived
  //       from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  
  #ifndef V8_MIPS_CODEGEN_MIPS_H_
  #define V8_MIPS_CODEGEN_MIPS_H_
  
  namespace v8 {
  namespace internal {
  
  // Forward declarations
  class CompilationInfo;
  class DeferredCode;
  class RegisterAllocator;
  class RegisterFile;
  
  enum InitState { CONST_INIT, NOT_CONST_INIT };
  enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
  
  
  // -----------------------------------------------------------------------------
  // Reference support
  
  // A reference is a C++ stack-allocated object that keeps an ECMA
  // reference on the execution stack while in scope. For variables
  // the reference is empty, indicating that it isn't necessary to
  // store state on the stack for keeping track of references to those.
  // For properties, we keep either one (named) or two (indexed) values
  // on the execution stack to represent the reference.
  class Reference BASE_EMBEDDED {
   public:
    // The values of the types is important, see size().
    enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
    Reference(CodeGenerator* cgen,
              Expression* expression,
              bool persist_after_get = false);
    ~Reference();
  
    Expression* expression() const { return expression_; }
    Type type() const { return type_; }
    void set_type(Type value) {
      ASSERT_EQ(ILLEGAL, type_);
      type_ = value;
    }
  
    void set_unloaded() {
      ASSERT_NE(ILLEGAL, type_);
      ASSERT_NE(UNLOADED, type_);
      type_ = UNLOADED;
    }
    // The size the reference takes up on the stack.
    int size() const {
      return (type_ < SLOT) ? 0 : type_;
    }
  
    bool is_illegal() const { return type_ == ILLEGAL; }
    bool is_slot() const { return type_ == SLOT; }
    bool is_property() const { return type_ == NAMED || type_ == KEYED; }
    bool is_unloaded() const { return type_ == UNLOADED; }
  
    // Return the name. Only valid for named property references.
    Handle<String> GetName();
  
    // Generate code to push the value of the reference on top of the
    // expression stack.  The reference is expected to be already on top of
    // the expression stack, and it is consumed by the call unless the
    // reference is for a compound assignment.
    // If the reference is not consumed, it is left in place under its value.
    void GetValue();
  
    // Generate code to pop a reference, push the value of the reference,
    // and then spill the stack frame.
    inline void GetValueAndSpill();
  
    // Generate code to store the value on top of the expression stack in the
    // reference.  The reference is expected to be immediately below the value
    // on the expression stack.  The  value is stored in the location specified
    // by the reference, and is left on top of the stack, after the reference
    // is popped from beneath it (unloaded).
    void SetValue(InitState init_state);
  
   private:
    CodeGenerator* cgen_;
    Expression* expression_;
    Type type_;
    // Keep the reference on the stack after get, so it can be used by set later.
    bool persist_after_get_;
  };
  
  
  // -----------------------------------------------------------------------------
  // Code generation state
  
  // The state is passed down the AST by the code generator (and back up, in
  // the form of the state of the label pair).  It is threaded through the
  // call stack.  Constructing a state implicitly pushes it on the owning code
  // generator's stack of states, and destroying one implicitly pops it.
  
  class CodeGenState BASE_EMBEDDED {
   public:
    // Create an initial code generator state.  Destroying the initial state
    // leaves the code generator with a NULL state.
    explicit CodeGenState(CodeGenerator* owner);
  
    // Create a code generator state based on a code generator's current
    // state.  The new state has its own typeof state and pair of branch
    // labels.
    CodeGenState(CodeGenerator* owner,
                 JumpTarget* true_target,
                 JumpTarget* false_target);
  
    // Destroy a code generator state and restore the owning code generator's
    // previous state.
    ~CodeGenState();
  
    TypeofState typeof_state() const { return typeof_state_; }
    JumpTarget* true_target() const { return true_target_; }
    JumpTarget* false_target() const { return false_target_; }
  
   private:
    // The owning code generator.
    CodeGenerator* owner_;
  
    // A flag indicating whether we are compiling the immediate subexpression
    // of a typeof expression.
    TypeofState typeof_state_;
  
    JumpTarget* true_target_;
    JumpTarget* false_target_;
  
    // The previous state of the owning code generator, restored when
    // this state is destroyed.
    CodeGenState* previous_;
  };
  
  
  
  // -----------------------------------------------------------------------------
  // CodeGenerator
  
  class CodeGenerator: public AstVisitor {
   public:
    // Compilation mode.  Either the compiler is used as the primary
    // compiler and needs to setup everything or the compiler is used as
    // the secondary compiler for split compilation and has to handle
    // bailouts.
    enum Mode {
      PRIMARY,
      SECONDARY
    };
  
    // Takes a function literal, generates code for it. This function should only
    // be called by compiler.cc.
    static Handle<Code> MakeCode(CompilationInfo* info);
  
    // Printing of AST, etc. as requested by flags.
    static void MakeCodePrologue(CompilationInfo* info);
  
    // Allocate and install the code.
    static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
                                         Code::Flags flags,
                                         CompilationInfo* info);
  
  #ifdef ENABLE_LOGGING_AND_PROFILING
    static bool ShouldGenerateLog(Expression* type);
  #endif
  
    static void SetFunctionInfo(Handle<JSFunction> fun,
                                FunctionLiteral* lit,
                                bool is_toplevel,
                                Handle<Script> script);
  
    static void RecordPositions(MacroAssembler* masm, int pos);
  
    // Accessors
    MacroAssembler* masm() { return masm_; }
    VirtualFrame* frame() const { return frame_; }
    inline Handle<Script> script();
  
    bool has_valid_frame() const { return frame_ != NULL; }
  
    // Set the virtual frame to be new_frame, with non-frame register
    // reference counts given by non_frame_registers.  The non-frame
    // register reference counts of the old frame are returned in
    // non_frame_registers.
    void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
  
    void DeleteFrame();
  
    RegisterAllocator* allocator() const { return allocator_; }
  
    CodeGenState* state() { return state_; }
    void set_state(CodeGenState* state) { state_ = state; }
  
    void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
  
    static const int kUnknownIntValue = -1;
  
    // Number of instructions used for the JS return sequence. The constant is
    // used by the debugger to patch the JS return sequence.
    static const int kJSReturnSequenceLength = 7;
  
    // If the name is an inline runtime function call return the number of
    // expected arguments. Otherwise return -1.
    static int InlineRuntimeCallArgumentsCount(Handle<String> name);
  
   private:
    // Construction/Destruction.
    explicit CodeGenerator(MacroAssembler* masm);
  
    // Accessors.
    inline bool is_eval();
    inline Scope* scope();
  
    // Generating deferred code.
    void ProcessDeferred();
  
    // State
    bool has_cc() const  { return cc_reg_ != cc_always; }
    TypeofState typeof_state() const { return state_->typeof_state(); }
    JumpTarget* true_target() const  { return state_->true_target(); }
    JumpTarget* false_target() const  { return state_->false_target(); }
  
    // We don't track loop nesting level on mips yet.
    int loop_nesting() const { return 0; }
  
    // Node visitors.
    void VisitStatements(ZoneList<Statement*>* statements);
  
  #define DEF_VISIT(type) \
    void Visit##type(type* node);
    AST_NODE_LIST(DEF_VISIT)
  #undef DEF_VISIT
  
    // Visit a statement and then spill the virtual frame if control flow can
    // reach the end of the statement (ie, it does not exit via break,
    // continue, return, or throw).  This function is used temporarily while
    // the code generator is being transformed.
    inline void VisitAndSpill(Statement* statement);
  
    // Visit a list of statements and then spill the virtual frame if control
    // flow can reach the end of the list.
    inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
  
    // Main code generation function
    void Generate(CompilationInfo* info);
  
    // The following are used by class Reference.
    void LoadReference(Reference* ref);
    void UnloadReference(Reference* ref);
  
    MemOperand ContextOperand(Register context, int index) const {
      return MemOperand(context, Context::SlotOffset(index));
    }
  
    MemOperand SlotOperand(Slot* slot, Register tmp);
  
    // Expressions
    MemOperand GlobalObject() const  {
      return ContextOperand(cp, Context::GLOBAL_INDEX);
    }
  
    void LoadCondition(Expression* x,
                       JumpTarget* true_target,
                       JumpTarget* false_target,
                       bool force_cc);
    void Load(Expression* x);
    void LoadGlobal();
  
    // Generate code to push the value of an expression on top of the frame
    // and then spill the frame fully to memory.  This function is used
    // temporarily while the code generator is being transformed.
    inline void LoadAndSpill(Expression* expression);
  
    // Read a value from a slot and leave it on top of the expression stack.
    void LoadFromSlot(Slot* slot, TypeofState typeof_state);
    // Store the value on top of the stack to a slot.
    void StoreToSlot(Slot* slot, InitState init_state);
  
    struct InlineRuntimeLUT {
      void (CodeGenerator::*method)(ZoneList<Expression*>*);
      const char* name;
      int nargs;
    };
  
    static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
    bool CheckForInlineRuntimeCall(CallRuntime* node);
    static bool PatchInlineRuntimeEntry(Handle<String> name,
                                        const InlineRuntimeLUT& new_entry,
                                        InlineRuntimeLUT* old_entry);
  
    static Handle<Code> ComputeLazyCompile(int argc);
    void ProcessDeclarations(ZoneList<Declaration*>* declarations);
  
    Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
  
    // Declare global variables and functions in the given array of
    // name/value pairs.
    void DeclareGlobals(Handle<FixedArray> pairs);
  
    // Support for type checks.
    void GenerateIsSmi(ZoneList<Expression*>* args);
    void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
    void GenerateIsArray(ZoneList<Expression*>* args);
    void GenerateIsRegExp(ZoneList<Expression*>* args);
  
    // Support for construct call checks.
    void GenerateIsConstructCall(ZoneList<Expression*>* args);
  
    // Support for arguments.length and arguments[?].
    void GenerateArgumentsLength(ZoneList<Expression*>* args);
    void GenerateArguments(ZoneList<Expression*>* args);
  
    // Support for accessing the class and value fields of an object.
    void GenerateClassOf(ZoneList<Expression*>* args);
    void GenerateValueOf(ZoneList<Expression*>* args);
    void GenerateSetValueOf(ZoneList<Expression*>* args);
  
    // Fast support for charCodeAt(n).
    void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
  
    // Fast support for string.charAt(n) and string[n].
    void GenerateCharFromCode(ZoneList<Expression*>* args);
  
    // Fast support for object equality testing.
    void GenerateObjectEquals(ZoneList<Expression*>* args);
  
    void GenerateLog(ZoneList<Expression*>* args);
  
    // Fast support for Math.random().
    void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
  
    void GenerateIsObject(ZoneList<Expression*>* args);
    void GenerateIsFunction(ZoneList<Expression*>* args);
    void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
    void GenerateStringAdd(ZoneList<Expression*>* args);
    void GenerateSubString(ZoneList<Expression*>* args);
    void GenerateStringCompare(ZoneList<Expression*>* args);
    void GenerateRegExpExec(ZoneList<Expression*>* args);
    void GenerateNumberToString(ZoneList<Expression*>* args);
  
    // Fast call to math functions.
    void GenerateMathPow(ZoneList<Expression*>* args);
    void GenerateMathSin(ZoneList<Expression*>* args);
    void GenerateMathCos(ZoneList<Expression*>* args);
    void GenerateMathSqrt(ZoneList<Expression*>* args);
  
    // Simple condition analysis.
    enum ConditionAnalysis {
      ALWAYS_TRUE,
      ALWAYS_FALSE,
      DONT_KNOW
    };
    ConditionAnalysis AnalyzeCondition(Expression* cond);
  
    // Methods used to indicate which source code is generated for. Source
    // positions are collected by the assembler and emitted with the relocation
    // information.
    void CodeForFunctionPosition(FunctionLiteral* fun);
    void CodeForReturnPosition(FunctionLiteral* fun);
    void CodeForStatementPosition(Statement* node);
    void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
    void CodeForSourcePosition(int pos);
  
  #ifdef DEBUG
    // True if the registers are valid for entry to a block.
    bool HasValidEntryRegisters();
  #endif
  
    bool is_eval_;  // Tells whether code is generated for eval.
  
    Handle<Script> script_;
    List<DeferredCode*> deferred_;
  
    // Assembler
    MacroAssembler* masm_;  // to generate code
  
    CompilationInfo* info_;
  
    // Code generation state
    VirtualFrame* frame_;
    RegisterAllocator* allocator_;
    Condition cc_reg_;
    CodeGenState* state_;
  
    // Jump targets
    BreakTarget function_return_;
  
    // True if the function return is shadowed (ie, jumping to the target
    // function_return_ does not jump to the true function return, but rather
    // to some unlinking code).
    bool function_return_is_shadowed_;
  
    static InlineRuntimeLUT kInlineRuntimeLUT[];
  
    friend class VirtualFrame;
    friend class JumpTarget;
    friend class Reference;
    friend class FastCodeGenerator;
    friend class FullCodeGenerator;
    friend class FullCodeGenSyntaxChecker;
  
    DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
  };
  
  
  } }  // namespace v8::internal
  
  #endif  // V8_MIPS_CODEGEN_MIPS_H_
  