Files
sdk/runtime/vm/code_generator_ia32.h
T
hausner@google.com 4d3a5f658a Add PC descriptor for ret instruction
Adding a new kind of PcDescriptor to mark the location of
function returns in generated code. This will be needed to
put a single-step breakpoint just before the function return.

Also adding a NOP instruction after the ret, so that the
function return code pattern adds up to 5 bytes, which is needed
to patch in a breakpoint call.
Review URL: https://chromiumcodereview.appspot.com//9385022

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@4159 260f80e4-7a28-3924-810f-c04153c831b5
2012-02-11 01:02:09 +00:00

233 lines
8.2 KiB
C++

// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef VM_CODE_GENERATOR_IA32_H_
#define VM_CODE_GENERATOR_IA32_H_
#ifndef VM_CODE_GENERATOR_H_
#error Do not include code_generator_ia32.h directly; use code_generator.h.
#endif
#include "vm/assembler.h"
#include "vm/ast.h"
#include "vm/growable_array.h"
#include "vm/parser.h"
namespace dart {
// Forward declarations.
class Assembler;
class AstNode;
class CodeGenerator;
class SourceLabel;
class CodeGeneratorState : public StackResource {
public:
explicit CodeGeneratorState(CodeGenerator* codegen);
virtual ~CodeGeneratorState();
CodeGeneratorState* parent() const { return parent_; }
AstNode* root_node() const { return root_node_; }
void set_root_node(AstNode* value) { root_node_ = value; }
bool IsRootNode(AstNode* node) const {
return root_node_ == node;
}
int loop_level() const { return loop_level_; }
void set_loop_level(int loop_level) {
loop_level_ = loop_level;
}
int context_level() const { return context_level_; }
void set_context_level(int context_level) {
context_level_ = context_level;
}
int try_index() const { return current_try_index_; }
void set_try_index(int value) {
current_try_index_ = value;
}
private:
CodeGenerator* codegen_;
CodeGeneratorState* parent_;
AstNode* root_node_;
// The loop level reflects the lexical nesting of loop statements, regardless
// of the presence of captured variables.
int loop_level_;
// The runtime context level is only incremented when a new context is
// allocated and chained to the list of contexts. This occurs when the scopes
// at the current loop level contain captured variables.
int context_level_;
// We identify each try block in this function with an unique 'try index'
// value.
// The 'try index' is used to match the try blocks with the corresponding
// catch block (if one exists). The PC descriptors generated for
// statements in the try block use this index so that it can be matched
// to the appropriate catch block.
// The 'try index' value is generated by incrementing the try_index_
// variable in the CodeGenerator object.
// We store the 'try index' of the block of code that we are
// currently generating code for in the current_try_index_ variable.
int current_try_index_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGeneratorState);
};
class CodeGenerator : public AstNodeVisitor {
public:
CodeGenerator(Assembler* assembler, const ParsedFunction& parsed_function);
virtual ~CodeGenerator() { }
// Accessors.
Assembler* assembler() const { return assembler_; }
const ParsedFunction& parsed_function() const { return parsed_function_; }
void GenerateCode();
virtual void GenerateDeferredCode();
#define DEFINE_VISITOR_FUNCTION(type, name) \
virtual void Visit##type(type* node);
NODE_LIST(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION
CodeGeneratorState* state() const { return state_; }
void set_state(CodeGeneratorState* state) { state_ = state; }
// Add exception handler table to code.
void FinalizeExceptionHandlers(const Code& code);
// Add pc descriptors to code.
void FinalizePcDescriptors(const Code& code);
// Add local variable descriptors to code.
void FinalizeVarDescriptors(const Code& code);
// Allocate and return an arguments descriptor.
// Let 'num_names' be the length of 'optional_arguments_names'.
// Treat the first 'num_arguments - num_names' arguments as positional and
// treat the following 'num_names' arguments as named optional arguments.
static const Array& ArgumentsDescriptor(
int num_arguments,
const Array& optional_arguments_names);
virtual bool IsOptimizing() const {
return false;
}
virtual void CountBackwardLoop();
void GenerateReturnEpilog(ReturnNode* node);
private:
// TODO(srdjan): Remove the friendship once the two compilers are properly
// structured.
friend class OptimizingCodeGenerator;
// Forward declarations.
class DescriptorList;
class HandlerList;
// Return true if intrinsification was completed and no other code
// needs to be generated.
virtual bool TryIntrinsify() { return false; }
virtual void GeneratePreEntryCode();
void GenerateLegacyEntryCode();
void GenerateEntryCode();
void GenerateLoadVariable(Register dst, const LocalVariable& local);
void GeneratePushVariable(const LocalVariable& variable, Register scratch);
void GenerateStoreVariable(const LocalVariable& local,
Register src,
Register scratch);
void GenerateLogicalNotOp(UnaryOpNode* node);
void GenerateLogicalAndOrOp(BinaryOpNode* node);
void GenerateInstanceGetterCall(intptr_t node_id,
intptr_t token_index,
const String& field_name);
void GenerateInstanceSetterCall(intptr_t node_id,
intptr_t token_index,
const String& field_name);
void GenerateBinaryOperatorCall(intptr_t node_id,
intptr_t token_index,
const char* operator_name);
void GenerateStaticGetterCall(intptr_t token_index,
const Class& field_class,
const String& field_name);
void GenerateStaticSetterCall(intptr_t token_index,
const Class& field_class,
const String& field_name);
void GenerateLoadIndexed(intptr_t node_id, intptr_t token_index);
void GenerateStoreIndexed(intptr_t node_id,
intptr_t token_index,
bool preserve_value);
// Invokes funtion via an inline cache stub. 'num_args_checked' specifies
// the number of call arguments that are being checked in the inline cache.
void GenerateInstanceCall(intptr_t node_id,
intptr_t token_index,
const String& function_name,
int num_arguments,
const Array& optional_arguments_names,
intptr_t num_args_checked);
void GenerateInstanceOf(intptr_t node_id,
intptr_t token_index,
const AbstractType& type,
bool negate_result);
void GenerateAssertAssignable(intptr_t node_id,
intptr_t token_index,
const AbstractType& dst_type,
const String& dst_name);
void GenerateArgumentTypeChecks();
void GenerateConditionTypeCheck(intptr_t node_id, intptr_t token_index);
void GenerateInstantiatorTypeArguments(intptr_t token_index);
void GenerateTypeArguments(ConstructorCallNode* node,
bool is_cls_parameterized);
void TestClassAndJump(const Class& cls, Label *label);
intptr_t locals_space_size() const { return locals_space_size_; }
void set_locals_space_size(intptr_t value) { locals_space_size_ = value; }
bool IsResultNeeded(AstNode* node) const;
void GenerateCall(intptr_t token_index, const ExternalLabel* ext_label);
void GenerateCallRuntime(intptr_t node_id,
intptr_t token_index,
const RuntimeEntry& entry);
void GenerateInlinedFinallyBlocks(SourceLabel* label);
void ErrorMsg(intptr_t token_index, const char* format, ...);
int generate_next_try_index() { return try_index_ += 1; }
void MarkDeoptPoint(intptr_t node_id, intptr_t token_index);
void AddCurrentDescriptor(PcDescriptors::Kind kind,
intptr_t node_id,
intptr_t token_index);
Assembler* assembler_;
const ParsedFunction& parsed_function_;
intptr_t locals_space_size_;
CodeGeneratorState* state_;
DescriptorList* pc_descriptors_list_;
HandlerList* exception_handlers_list_;
int try_index_;
DISALLOW_IMPLICIT_CONSTRUCTORS(CodeGenerator);
};
} // namespace dart
#endif // VM_CODE_GENERATOR_IA32_H_