1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
6#define RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
12#include "vm/compiler/frontend/constant_reader.h"
13#include "vm/compiler/frontend/kernel_translation_helper.h"
14#include "vm/hash_map.h"
15#include "vm/object.h"
16#include "vm/parser.h" // For ParsedFunction.
17
18namespace dart {
19namespace kernel {
20
21class ScopeBuildingResult;
22
23class ScopeBuilder {
24 public:
25 explicit ScopeBuilder(ParsedFunction* parsed_function);
26
27 virtual ~ScopeBuilder() = default;
28
29 ScopeBuildingResult* BuildScopes();
30
31 private:
32 void VisitField();
33
34 void VisitProcedure();
35
36 void VisitConstructor();
37
38 void VisitFunctionNode();
39 void VisitNode();
40 void VisitInitializer();
41 void VisitExpression();
42 void VisitStatement();
43 void VisitArguments();
44 void VisitVariableDeclaration();
45 void VisitVariableGet(intptr_t declaration_binary_offset);
46 void VisitDartType();
47 void VisitInterfaceType(bool simple);
48 void VisitFunctionType(bool simple);
49 void VisitTypeParameterType();
50 void HandleLocalFunction(intptr_t parent_kernel_offset);
51
52 AbstractType& BuildAndVisitVariableType();
53
54 void EnterScope(intptr_t kernel_offset);
55 void ExitScope(TokenPosition start_position, TokenPosition end_position);
56
57 virtual void ReportUnexpectedTag(const char* variant, Tag tag);
58
59 // This enum controls which parameters would be marked as requring type
60 // check on the callee side.
61 enum ParameterTypeCheckMode {
62 // All parameters will be checked.
63 kTypeCheckAllParameters,
64
65 // Only parameters marked as covariant or generic-covariant-impl will be
66 // checked.
67 kTypeCheckForNonDynamicallyInvokedMethod,
68
69 // Only parameters *not* marked as covariant or generic-covariant-impl will
70 // be checked. The rest would be checked in the method itself.
71 // Inverse of kTypeCheckForNonDynamicallyInvokedMethod.
72 kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod,
73
74 // No parameters will be checked.
75 kTypeCheckForStaticFunction,
76 };
77
78 // This assumes that the reader is at a FunctionNode,
79 // about to read the positional parameters.
80 void AddPositionalAndNamedParameters(
81 intptr_t pos,
82 ParameterTypeCheckMode type_check_mode,
83 const ProcedureAttributesMetadata& attrs);
84
85 // This assumes that the reader is at a FunctionNode,
86 // about to read a parameter (i.e. VariableDeclaration).
87 void AddVariableDeclarationParameter(
88 intptr_t pos,
89 ParameterTypeCheckMode type_check_mode,
90 const ProcedureAttributesMetadata& attrs);
91
92 LocalVariable* MakeVariable(TokenPosition declaration_pos,
93 TokenPosition token_pos,
94 const String& name,
95 const AbstractType& type,
96 const InferredTypeMetadata* param_type_md = NULL);
97
98 void AddExceptionVariable(GrowableArray<LocalVariable*>* variables,
99 const char* prefix,
100 intptr_t nesting_depth);
101
102 void FinalizeExceptionVariable(GrowableArray<LocalVariable*>* variables,
103 GrowableArray<LocalVariable*>* raw_variables,
104 const String& symbol,
105 intptr_t nesting_depth);
106
107 void AddTryVariables();
108 void AddCatchVariables();
109 void FinalizeCatchVariables();
110 void AddIteratorVariable();
111 void AddSwitchVariable();
112
113 // Record an assignment or reference to a variable. If the occurrence is
114 // in a nested function, ensure that the variable is handled properly as a
115 // captured variable.
116 LocalVariable* LookupVariable(intptr_t declaration_binary_offset);
117
118 StringIndex GetNameFromVariableDeclaration(intptr_t kernel_offset,
119 const Function& function);
120
121 const String& GenerateName(const char* prefix, intptr_t suffix);
122
123 void HandleLoadReceiver();
124 void HandleSpecialLoad(LocalVariable** variable, const String& symbol);
125 void LookupCapturedVariableByName(LocalVariable** variable,
126 const String& name);
127
128 struct DepthState {
129 explicit DepthState(intptr_t function)
130 : loop_(0),
131 function_(function),
132 try_(0),
133 catch_(0),
134 finally_(0),
135 for_in_(0) {}
136
137 intptr_t loop_;
138 intptr_t function_;
139 intptr_t try_;
140 intptr_t catch_;
141 intptr_t finally_;
142 intptr_t for_in_;
143 };
144
145 ScopeBuildingResult* result_;
146 ParsedFunction* parsed_function_;
147
148 ActiveClass active_class_;
149
150 TranslationHelper translation_helper_;
151 Zone* zone_;
152
153 FunctionNodeHelper::AsyncMarker current_function_async_marker_;
154 LocalScope* current_function_scope_;
155 LocalScope* scope_;
156 DepthState depth_;
157
158 intptr_t name_index_;
159
160 bool needs_expr_temp_;
161 TokenPosition first_body_token_position_;
162
163 KernelReaderHelper helper_;
164 ConstantReader constant_reader_;
165 InferredTypeMetadataHelper inferred_type_metadata_helper_;
166 ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
167 TypeTranslator type_translator_;
168
169 DISALLOW_COPY_AND_ASSIGN(ScopeBuilder);
170};
171
172struct FunctionScope {
173 intptr_t kernel_offset;
174 LocalScope* scope;
175};
176
177class ScopeBuildingResult : public ZoneAllocated {
178 public:
179 ScopeBuildingResult()
180 : type_arguments_variable(NULL),
181 switch_variable(NULL),
182 finally_return_variable(NULL),
183 setter_value(NULL),
184 yield_jump_variable(NULL),
185 yield_context_variable(NULL),
186 raw_variable_counter_(0) {}
187
188 IntMap<LocalVariable*> locals;
189 IntMap<LocalScope*> scopes;
190 GrowableArray<FunctionScope> function_scopes;
191
192 // Only non-NULL for factory constructor functions.
193 LocalVariable* type_arguments_variable;
194
195 // Non-NULL when the function contains a switch statement.
196 LocalVariable* switch_variable;
197
198 // Non-NULL when the function contains a return inside a finally block.
199 LocalVariable* finally_return_variable;
200
201 // Non-NULL when the function is a setter.
202 LocalVariable* setter_value;
203
204 // Non-NULL if the function contains yield statement.
205 // TODO(27590) actual variable is called :await_jump_var, we should rename
206 // it to reflect the fact that it is used for both await and yield.
207 LocalVariable* yield_jump_variable;
208
209 // Non-NULL if the function contains yield statement.
210 // TODO(27590) actual variable is called :await_ctx_var, we should rename
211 // it to reflect the fact that it is used for both await and yield.
212 LocalVariable* yield_context_variable;
213
214 // Variables used in exception handlers, one per exception handler nesting
215 // level.
216 GrowableArray<LocalVariable*> exception_variables;
217 GrowableArray<LocalVariable*> stack_trace_variables;
218 GrowableArray<LocalVariable*> catch_context_variables;
219
220 // These are used to access the raw exception/stacktrace variables (and are
221 // used to put them into the captured variables in the context).
222 GrowableArray<LocalVariable*> raw_exception_variables;
223 GrowableArray<LocalVariable*> raw_stack_trace_variables;
224 intptr_t raw_variable_counter_;
225
226 // For-in iterators, one per for-in nesting level.
227 GrowableArray<LocalVariable*> iterator_variables;
228
229 private:
230 DISALLOW_COPY_AND_ASSIGN(ScopeBuildingResult);
231};
232
233// Returns true if the given method can skip type checks for all arguments
234// that are not covariant or generic covariant in its implementation.
235bool MethodCanSkipTypeChecksForNonCovariantArguments(
236 const Function& method,
237 const ProcedureAttributesMetadata& attrs);
238
239} // namespace kernel
240} // namespace dart
241
242#endif // RUNTIME_VM_COMPILER_FRONTEND_SCOPE_BUILDER_H_
243