Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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 library dart2js.ir_nodes_sexpr;
6
7 import '../constants/values.dart';
8 import '../universe/call_structure.dart' show CallStructure;
9 import '../util/util.dart';
10 import 'cps_ir_nodes.dart';
11
12 /// A [Decorator] is a function used by [SExpressionStringifier] to augment the
13 /// output produced for a node or reference. It can be provided to the
14 /// constructor.
15 typedef String Decorator(node, String s);
16
17 /// Generate a Lisp-like S-expression representation of an IR node as a string.
18 class SExpressionStringifier extends Indentation implements Visitor<String> {
19 final _Namer namer = new _Namer();
20
21 String newValueName(Primitive node) => namer.nameValue(node);
22 String newContinuationName(Continuation node) => namer.nameContinuation(node);
23 Decorator decorator;
24
25 SExpressionStringifier([this.decorator]) {
26 if (this.decorator == null) {
27 this.decorator = (node, String s) => s;
28 }
29 }
30
31 /// Create a stringifier with an extra layer of decoration.
32 SExpressionStringifier withDecorator(Decorator subDecorator) {
33 return new SExpressionStringifier((node, String s) {
34 return subDecorator(node, decorator(node, s));
35 });
36 }
37
38 /// Create a stringifier that displays type information.
39 SExpressionStringifier withTypes() => withDecorator(typeDecorator);
40
41 /// Creates a stringifier that adds annotations from a map;
42 /// see [Node.debugString].
43 SExpressionStringifier withAnnotations(Map annotations) {
44 return withDecorator(decoratorFromMap(annotations));
45 }
46
47 static Decorator decoratorFromMap(Map annotations) {
48 Map<Node, String> nodeMap = {};
49 for (var key in annotations.keys) {
50 if (key is Node) {
51 nodeMap[key] = '${annotations[key]}';
52 } else {
53 String text = key;
54 Node node = annotations[key];
55 if (nodeMap.containsKey(node)) {
56 // In case two annotations belong to the same node,
57 // put both annotations on that node.
58 nodeMap[node] += ' $text';
59 } else {
60 nodeMap[node] = text;
61 }
62 }
63 }
64 return (node, string) {
65 String text = nodeMap[node];
66 if (text != null) return '***$string*** $text';
67 return string;
68 };
69 }
70
71 static String typeDecorator(node, String string) {
72 return node is Variable ? '$string:${node.type}' : string;
73 }
74
75 String access(Reference<Definition> r) {
76 if (r == null) return '**** NULL ****';
77 return decorator(r, namer.getName(r.definition));
78 }
79
80 String optionalAccess(Reference<Definition> reference) {
81 return reference == null ? '()' : '(${access(reference)})';
82 }
83
84 String visitParameter(Parameter node) {
85 return namer.nameParameter(node);
86 }
87
88 String visitMutableVariable(MutableVariable node) {
89 return namer.nameMutableVariable(node);
90 }
91
92 /// Main entry point for creating a [String] from a [Node]. All recursive
93 /// calls must go through this method.
94 String visit(Node node) {
95 if (node == null) return '**** NULL ****';
96 String s = node.accept(this);
97 return decorator(node, s);
98 }
99
100 String formatOptionalParameter(Parameter parameter) {
101 return parameter == null ? '()' : '(${visit(parameter)})';
102 }
103
104 String visitFunctionDefinition(FunctionDefinition node) {
105 String name = node.element.name;
106 String interceptorParameter =
107 formatOptionalParameter(node.interceptorParameter);
108 String thisParameter = formatOptionalParameter(node.receiverParameter);
109 String parameters = node.parameters.map(visit).join(' ');
110 namer.setReturnContinuation(node.returnContinuation);
111 String body = indentBlock(() => visit(node.body));
112 return '$indentation'
113 '(FunctionDefinition $name $interceptorParameter $thisParameter '
114 '($parameters) return\n'
115 '$body)';
116 }
117
118 String visitLetPrim(LetPrim node) {
119 String name = newValueName(node.primitive);
120 String value = visit(node.primitive);
121 String bindings = '($name $value)';
122 String skip = ' ' * '(LetPrim ('.length;
123 while (node.body is LetPrim) {
124 node = node.body;
125 name = newValueName(node.primitive);
126 value = visit(node.primitive);
127 String binding = decorator(node, '($name $value)');
128 bindings += '\n${indentation}$skip$binding';
129 }
130 String body = indentBlock(() => visit(node.body));
131 return '$indentation(LetPrim ($bindings)\n$body)';
132 }
133
134 bool isBranchTarget(Continuation cont) {
135 return cont.hasExactlyOneUse && cont.firstRef.parent is Branch;
136 }
137
138 String visitLetCont(LetCont node) {
139 String conts;
140 bool first = true;
141 String skip = ' ' * '(LetCont ('.length;
142 for (Continuation continuation in node.continuations) {
143 // Branch continuations will be printed at their use site.
144 if (isBranchTarget(continuation)) continue;
145 if (first) {
146 first = false;
147 conts = visit(continuation);
148 } else {
149 // Each subsequent line is indented additional spaces to align it
150 // with the previous continuation.
151 conts += '\n${indentation}$skip${visit(continuation)}';
152 }
153 }
154 // If there were no continuations printed, just print the body.
155 if (first) return visit(node.body);
156
157 String body = indentBlock(() => visit(node.body));
158 return '$indentation(LetCont ($conts)\n$body)';
159 }
160
161 String visitLetHandler(LetHandler node) {
162 // There are no explicit references to the handler, so we leave it
163 // anonymous in the printed representation.
164 String parameters = node.handler.parameters
165 .map((p) => '${decorator(p, newValueName(p))}')
166 .join(' ');
167 String handlerBody =
168 indentBlock(() => indentBlock(() => visit(node.handler.body)));
169 String body = indentBlock(() => visit(node.body));
170 return '$indentation(LetHandler (($parameters)\n$handlerBody)\n$body)';
171 }
172
173 String visitLetMutable(LetMutable node) {
174 String name = visit(node.variable);
175 String value = access(node.valueRef);
176 String body = indentBlock(() => visit(node.body));
177 return '$indentation(LetMutable ($name $value)\n$body)';
178 }
179
180 String formatArguments(
181 CallStructure call, List<Reference<Primitive>> arguments,
182 [CallingConvention callingConvention = CallingConvention.Normal]) {
183 int positionalArgumentCount = call.positionalArgumentCount;
184 List<String> args =
185 arguments.take(positionalArgumentCount).map(access).toList();
186 List<String> argumentNames = call.getOrderedNamedArguments();
187 for (int i = 0; i < argumentNames.length; ++i) {
188 String name = argumentNames[i];
189 String arg = access(arguments[positionalArgumentCount + i]);
190 args.add("($name: $arg)");
191 }
192 // Constructors can have type parameter after the named arguments.
193 args.addAll(arguments
194 .skip(positionalArgumentCount + argumentNames.length)
195 .map(access));
196 return '(${args.join(' ')})';
197 }
198
199 String visitInvokeStatic(InvokeStatic node) {
200 String name = node.target.name;
201 String args =
202 formatArguments(node.selector.callStructure, node.argumentRefs);
203 return '(InvokeStatic $name $args)';
204 }
205
206 String visitInvokeMethod(InvokeMethod node) {
207 String name = node.selector.name;
208 String interceptor = optionalAccess(node.interceptorRef);
209 String receiver = access(node.receiverRef);
210 String arguments = formatArguments(
211 node.selector.callStructure, node.argumentRefs, node.callingConvention);
212 return '(InvokeMethod $interceptor $receiver $name $arguments)';
213 }
214
215 String visitInvokeMethodDirectly(InvokeMethodDirectly node) {
216 String interceptor = optionalAccess(node.interceptorRef);
217 String receiver = access(node.receiverRef);
218 String name = node.selector.name;
219 String arguments = formatArguments(
220 node.selector.callStructure, node.argumentRefs, node.callingConvention);
221 return '(InvokeMethodDirectly $interceptor $receiver $name $arguments)';
222 }
223
224 String visitInvokeConstructor(InvokeConstructor node) {
225 // TODO(karlklose): for illegal nodes constructed for tests or unresolved
226 // constructor calls in the DartBackend, we get an element with no enclosing
227 // class. Clean this up by introducing a name field to the node and
228 // removing [ErroneousElement]s from the IR.
229 String name = node.dartType != null
230 ? node.dartType.toString()
231 : node.target.enclosingClass.name;
232 if (!node.target.name.isEmpty) {
233 name = '${name}.${node.target.name}';
234 }
235 String args =
236 formatArguments(node.selector.callStructure, node.argumentRefs);
237 return '(InvokeConstructor $name $args)';
238 }
239
240 String visitInvokeContinuation(InvokeContinuation node) {
241 String name = access(node.continuationRef);
242 if (node.isRecursive) name = 'rec $name';
243 String args = node.argumentRefs == null
244 ? '**** NULL ****'
245 : node.argumentRefs.map(access).join(' ');
246 String escaping = node.isEscapingTry ? ' escape' : '';
247 return '$indentation(InvokeContinuation $name ($args)$escaping)';
248 }
249
250 String visitThrow(Throw node) {
251 String value = access(node.valueRef);
252 return '$indentation(Throw $value)';
253 }
254
255 String visitRethrow(Rethrow node) {
256 return '$indentation(Rethrow)';
257 }
258
259 String visitBranch(Branch node) {
260 String condition = access(node.conditionRef);
261 assert(isBranchTarget(node.trueContinuation));
262 assert(isBranchTarget(node.falseContinuation));
263 String trueCont = indentBlock(() => visit(node.trueContinuation));
264 String falseCont = indentBlock(() => visit(node.falseContinuation));
265 String strict = node.isStrictCheck ? 'Strict' : 'NonStrict';
266 return '$indentation(Branch $strict $condition\n$trueCont\n$falseCont)';
267 }
268
269 String visitUnreachable(Unreachable node) {
270 return '$indentation(Unreachable)';
271 }
272
273 String visitConstant(Constant node) {
274 String value = node.value.accept(new ConstantStringifier(), null);
275 return '(Constant $value)';
276 }
277
278 String visitContinuation(Continuation node) {
279 if (isBranchTarget(node)) {
280 assert(node.parameters.isEmpty);
281 assert(!node.isRecursive);
282 return indentBlock(() => visit(node.body));
283 }
284 String name = newContinuationName(node);
285 if (node.isRecursive) name = 'rec $name';
286 // TODO(karlklose): this should be changed to `.map(visit).join(' ')`
287 // and should recurse to [visit]. Currently we can't do that, because
288 // the unstringifier_test produces [LetConts] with dummy arguments on
289 // them.
290 String parameters = node.parameters
291 .map((p) => '${decorator(p, newValueName(p))}')
292 .join(' ');
293 String body = indentBlock(() => indentBlock(() => visit(node.body)));
294 return '($name ($parameters)\n$body)';
295 }
296
297 String visitGetMutable(GetMutable node) {
298 return '(GetMutable ${access(node.variableRef)})';
299 }
300
301 String visitSetMutable(SetMutable node) {
302 String value = access(node.valueRef);
303 return '(SetMutable ${access(node.variableRef)} $value)';
304 }
305
306 String visitTypeCast(TypeCast node) {
307 String value = access(node.valueRef);
308 String typeArguments = node.typeArgumentRefs.map(access).join(' ');
309 return '(TypeCast $value ${node.dartType} ($typeArguments))';
310 }
311
312 String visitTypeTest(TypeTest node) {
313 String value = access(node.valueRef);
314 String typeArguments = node.typeArgumentRefs.map(access).join(' ');
315 return '(TypeTest $value ${node.dartType} ($typeArguments))';
316 }
317
318 String visitTypeTestViaFlag(TypeTestViaFlag node) {
319 String interceptor = access(node.interceptorRef);
320 return '(TypeTestViaFlag $interceptor ${node.dartType})';
321 }
322
323 String visitLiteralList(LiteralList node) {
324 String values = node.valueRefs.map(access).join(' ');
325 return '(LiteralList ($values))';
326 }
327
328 String visitSetField(SetField node) {
329 String object = access(node.objectRef);
330 String field = node.field.name;
331 String value = access(node.valueRef);
332 return '(SetField $object $field $value)';
333 }
334
335 String visitGetField(GetField node) {
336 String object = access(node.objectRef);
337 String field = node.field.name;
338 return '(GetField $object $field)';
339 }
340
341 String visitGetStatic(GetStatic node) {
342 String element = node.element.name;
343 return '(GetStatic $element)';
344 }
345
346 String visitSetStatic(SetStatic node) {
347 String element = node.element.name;
348 String value = access(node.valueRef);
349 return '(SetStatic $element $value)';
350 }
351
352 String visitGetLazyStatic(GetLazyStatic node) {
353 String element = node.element.name;
354 return '(GetLazyStatic $element)';
355 }
356
357 String visitCreateBox(CreateBox node) {
358 return '(CreateBox)';
359 }
360
361 String visitCreateInstance(CreateInstance node) {
362 String className = node.classElement.name;
363 String arguments = node.argumentRefs.map(access).join(' ');
364 String typeInformation = optionalAccess(node.typeInformationRef);
365 return '(CreateInstance $className ($arguments) ($typeInformation))';
366 }
367
368 String visitInterceptor(Interceptor node) {
369 return '(Interceptor ${access(node.inputRef)})';
370 }
371
372 String visitReifyRuntimeType(ReifyRuntimeType node) {
373 return '(ReifyRuntimeType ${access(node.valueRef)})';
374 }
375
376 String visitReadTypeVariable(ReadTypeVariable node) {
377 return '(ReadTypeVariable ${access(node.targetRef)}.${node.variable})';
378 }
379
380 String visitTypeExpression(TypeExpression node) {
381 String args = node.argumentRefs.map(access).join(' ');
382 return '(TypeExpression ${node.kindAsString} ${node.dartType} ($args))';
383 }
384
385 String visitCreateInvocationMirror(CreateInvocationMirror node) {
386 String selector = node.selector.name;
387 String args = node.argumentRefs.map(access).join(' ');
388 return '(CreateInvocationMirror $selector ($args))';
389 }
390
391 String visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
392 String operator = node.operator.toString();
393 String args = node.argumentRefs.map(access).join(' ');
394 return '(ApplyBuiltinOperator $operator ($args))';
395 }
396
397 String visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
398 String method = node.method.toString();
399 String receiver = access(node.receiverRef);
400 String args = node.argumentRefs.map(access).join(' ');
401 return '(ApplyBuiltinMethod $method $receiver ($args))';
402 }
403
404 String visitForeignCode(ForeignCode node) {
405 String arguments = node.argumentRefs.map(access).join(' ');
406 return '(JS "${node.codeTemplate.source}" ($arguments))';
407 }
408
409 String visitGetLength(GetLength node) {
410 String object = access(node.objectRef);
411 return '(GetLength $object)';
412 }
413
414 String visitGetIndex(GetIndex node) {
415 String object = access(node.objectRef);
416 String index = access(node.indexRef);
417 return '(GetIndex $object $index)';
418 }
419
420 String visitSetIndex(SetIndex node) {
421 String object = access(node.objectRef);
422 String index = access(node.indexRef);
423 String value = access(node.valueRef);
424 return '(SetIndex $object $index $value)';
425 }
426
427 @override
428 String visitAwait(Await node) {
429 String value = access(node.inputRef);
430 return '(Await $value)';
431 }
432
433 @override
434 String visitYield(Yield node) {
435 String value = access(node.inputRef);
436 return '(Yield $value)';
437 }
438
439 String visitRefinement(Refinement node) {
440 String value = access(node.value);
441 return '(Refinement $value ${node.type})';
442 }
443
444 String visitBoundsCheck(BoundsCheck node) {
445 String object = access(node.objectRef);
446 String index = optionalAccess(node.indexRef);
447 String length = optionalAccess(node.lengthRef);
448 return '(BoundsCheck $object $index $length ${node.checkString})';
449 }
450
451 String visitReceiverCheck(ReceiverCheck node) {
452 String value = access(node.valueRef);
453 String condition = optionalAccess(node.conditionRef);
454 return '(ReceiverCheck $value ${node.selector} $condition '
455 '${node.flagString}))';
456 }
457 }
458
459 class ConstantStringifier extends ConstantValueVisitor<String, Null> {
460 // Some of these methods are unimplemented because we haven't had a need
461 // to print such constants. When printing is implemented, the corresponding
462 // parsing support should be added to SExpressionUnstringifier.parseConstant
463 // in the dart2js tests (currently in the file
464 // tests/compiler/dart2js/backend_dart/sexpr_unstringifier.dart).
465
466 String _failWith(ConstantValue constant) {
467 throw 'Stringification not supported for ${constant.toStructuredText()}';
468 }
469
470 String visitFunction(FunctionConstantValue constant, _) {
471 return '(Function "${constant.toDartText()}")';
472 }
473
474 String visitNull(NullConstantValue constant, _) {
475 return '(Null)';
476 }
477
478 String visitNonConstant(NonConstantValue constant, _) {
479 return '(NonConstant)';
480 }
481
482 String visitInt(IntConstantValue constant, _) {
483 return '(Int ${constant.toDartText()})';
484 }
485
486 String visitDouble(DoubleConstantValue constant, _) {
487 return '(Double ${constant.toDartText()})';
488 }
489
490 String visitBool(BoolConstantValue constant, _) {
491 return '(Bool ${constant.toDartText()})';
492 }
493
494 String visitString(StringConstantValue constant, _) {
495 return '(String ${constant.toDartText()})';
496 }
497
498 String visitList(ListConstantValue constant, _) {
499 String entries =
500 constant.entries.map((entry) => entry.accept(this, _)).join(' ');
501 return '(List $entries)';
502 }
503
504 String visitMap(MapConstantValue constant, _) {
505 List<String> elements = <String>[];
506 for (int i = 0; i < constant.keys.length; ++i) {
507 ConstantValue key = constant.keys[i];
508 ConstantValue value = constant.values[i];
509 elements.add('(${key.accept(this, _)} . ${value.accept(this, _)})');
510 }
511 return '(Map (${elements.join(' ')}))';
512 }
513
514 String visitConstructed(ConstructedConstantValue constant, _) {
515 return '(Constructed "${constant.toDartText()}")';
516 }
517
518 String visitType(TypeConstantValue constant, _) {
519 return '(Type "${constant.representedType}")';
520 }
521
522 String visitInterceptor(InterceptorConstantValue constant, _) {
523 return '(Interceptor "${constant.toDartText()}")';
524 }
525
526 String visitSynthetic(SyntheticConstantValue constant, _) {
527 return '(Synthetic "${constant.toDartText()}")';
528 }
529
530 String visitDeferred(DeferredConstantValue constant, _) {
531 return _failWith(constant);
532 }
533 }
534
535 class _Namer {
536 final Map<Node, String> _names = <Node, String>{};
537 int _valueCounter = 0;
538 int _continuationCounter = 0;
539
540 // TODO(sra): Make the methods not assert and print something indicating an
541 // error, so printer can be used to inspect broken terms.
542
543 String nameParameter(Parameter parameter) {
544 assert(!_names.containsKey(parameter));
545 String name =
546 parameter.hint != null ? parameter.hint.name : nameValue(parameter);
547 return _names[parameter] = name;
548 }
549
550 String nameMutableVariable(MutableVariable variable) {
551 assert(!_names.containsKey(variable));
552 return _names[variable] = variable.hint.name;
553 }
554
555 String nameContinuation(Continuation node) {
556 assert(!_names.containsKey(node));
557 return _names[node] = 'k${_continuationCounter++}';
558 }
559
560 String nameValue(Primitive node) {
561 assert(!_names.containsKey(node));
562 return _names[node] = 'v${_valueCounter++}';
563 }
564
565 void setReturnContinuation(Continuation node) {
566 assert(!_names.containsKey(node) || _names[node] == 'return');
567 _names[node] = 'return';
568 }
569
570 String getName(Node node) {
571 if (!_names.containsKey(node)) return 'MISSING_NAME';
572 return _names[node];
573 }
574 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698