OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
8 | 8 |
9 | 9 |
10 String buildJavaScriptFunction(FunctionElement element, | 10 String buildJavaScriptFunction(FunctionElement element, |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 final Set<HInstruction> generateAtUseSite; | 149 final Set<HInstruction> generateAtUseSite; |
150 final Map<HPhi, String> logicalOperations; | 150 final Map<HPhi, String> logicalOperations; |
151 final Map<Element, ElementAction> breakAction; | 151 final Map<Element, ElementAction> breakAction; |
152 final Map<Element, ElementAction> continueAction; | 152 final Map<Element, ElementAction> continueAction; |
153 final Equivalence<HPhi> phiEquivalence; | 153 final Equivalence<HPhi> phiEquivalence; |
154 | 154 |
155 Element equalsNullElement; | 155 Element equalsNullElement; |
156 Element boolifiedEqualsNullElement; | 156 Element boolifiedEqualsNullElement; |
157 int indent = 0; | 157 int indent = 0; |
158 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; | 158 int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; |
| 159 JSBinaryOperatorPrecedence unsignedShiftPrecedences; |
159 HGraph currentGraph; | 160 HGraph currentGraph; |
160 /** | 161 /** |
161 * Whether the code-generation should try to generate an expression | 162 * Whether the code-generation should try to generate an expression |
162 * instead of a sequence of statements. | 163 * instead of a sequence of statements. |
163 */ | 164 */ |
164 int generationState = STATE_STATEMENT; | 165 int generationState = STATE_STATEMENT; |
165 /** | 166 /** |
166 * While generating expressions, we can't insert variable declarations. | 167 * While generating expressions, we can't insert variable declarations. |
167 * Instead we declare them at the end of the function | 168 * Instead we declare them at the end of the function |
168 */ | 169 */ |
(...skipping 18 matching lines...) Expand all Loading... |
187 this.parameters, | 188 this.parameters, |
188 this.parameterNames) | 189 this.parameterNames) |
189 : names = new Map<int, String>(), | 190 : names = new Map<int, String>(), |
190 prefixes = new Map<String, int>(), | 191 prefixes = new Map<String, int>(), |
191 usedNames = new Set<String>(), | 192 usedNames = new Set<String>(), |
192 buffer = new StringBuffer(), | 193 buffer = new StringBuffer(), |
193 generateAtUseSite = new Set<HInstruction>(), | 194 generateAtUseSite = new Set<HInstruction>(), |
194 logicalOperations = new Map<HPhi, String>(), | 195 logicalOperations = new Map<HPhi, String>(), |
195 breakAction = new Map<Element, ElementAction>(), | 196 breakAction = new Map<Element, ElementAction>(), |
196 continueAction = new Map<Element, ElementAction>(), | 197 continueAction = new Map<Element, ElementAction>(), |
197 phiEquivalence = new Equivalence<HPhi>() { | 198 phiEquivalence = new Equivalence<HPhi>(), |
| 199 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
198 | 200 |
199 for (final name in parameterNames.getValues()) { | 201 for (final name in parameterNames.getValues()) { |
200 prefixes[name] = 0; | 202 prefixes[name] = 0; |
201 } | 203 } |
202 | 204 |
203 // Create a namespace for temporaries. | 205 // Create a namespace for temporaries. |
204 prefixes[TEMPORARY_PREFIX] = 0; | 206 prefixes[TEMPORARY_PREFIX] = 0; |
205 | 207 |
206 Interceptors interceptors = compiler.builder.interceptors; | 208 Interceptors interceptors = compiler.builder.interceptors; |
207 equalsNullElement = interceptors.getEqualsNullInterceptor(); | 209 equalsNullElement = interceptors.getEqualsNullInterceptor(); |
(...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 beginExpression(operatorPrecedences.precedence); | 1106 beginExpression(operatorPrecedences.precedence); |
1105 use(node.left, operatorPrecedences.left); | 1107 use(node.left, operatorPrecedences.left); |
1106 buffer.add(' $op '); | 1108 buffer.add(' $op '); |
1107 use(node.right, operatorPrecedences.right); | 1109 use(node.right, operatorPrecedences.right); |
1108 endExpression(operatorPrecedences.precedence); | 1110 endExpression(operatorPrecedences.precedence); |
1109 } else { | 1111 } else { |
1110 visitInvokeStatic(node); | 1112 visitInvokeStatic(node); |
1111 } | 1113 } |
1112 } | 1114 } |
1113 | 1115 |
| 1116 // We want the outcome of bit-operations to be positive. We use the unsigned |
| 1117 // shift operator to achieve this. |
| 1118 visitBitInvokeBinary(HBinaryBitOp node, String op) { |
| 1119 if (node.builtin){ |
| 1120 beginExpression(unsignedShiftPrecedences.precedence); |
| 1121 visitInvokeBinary(node, op); |
| 1122 buffer.add(' >>> 0'); |
| 1123 endExpression(unsignedShiftPrecedences.precedence); |
| 1124 } else { |
| 1125 visitInvokeBinary(node, op); |
| 1126 } |
| 1127 } |
| 1128 |
1114 visitInvokeUnary(HInvokeUnary node, String op) { | 1129 visitInvokeUnary(HInvokeUnary node, String op) { |
1115 if (node.builtin) { | 1130 if (node.builtin) { |
1116 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); | 1131 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
1117 buffer.add('$op'); | 1132 buffer.add('$op'); |
1118 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); | 1133 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); |
1119 endExpression(JSPrecedence.PREFIX_PRECEDENCE); | 1134 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
1120 } else { | 1135 } else { |
1121 visitInvokeStatic(node); | 1136 visitInvokeStatic(node); |
1122 } | 1137 } |
1123 } | 1138 } |
1124 | 1139 |
| 1140 // We want the outcome of bit-operations to be positive. We use the unsigned |
| 1141 // shift operator to achieve this. |
| 1142 visitBitInvokeUnary(HInvokeUnary node, String op) { |
| 1143 if (node.builtin){ |
| 1144 beginExpression(unsignedShiftPrecedences.precedence); |
| 1145 visitInvokeUnary(node, op); |
| 1146 buffer.add(' >>> 0'); |
| 1147 endExpression(unsignedShiftPrecedences.precedence); |
| 1148 } else { |
| 1149 visitInvokeUnary(node, op); |
| 1150 } |
| 1151 } |
| 1152 |
1125 visitEquals(HEquals node) { | 1153 visitEquals(HEquals node) { |
1126 if (node.builtin) { | 1154 if (node.builtin) { |
1127 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1155 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
1128 use(node.left, JSPrecedence.EQUALITY_PRECEDENCE); | 1156 use(node.left, JSPrecedence.EQUALITY_PRECEDENCE); |
1129 buffer.add(' === '); | 1157 buffer.add(' === '); |
1130 use(node.right, JSPrecedence.RELATIONAL_PRECEDENCE); | 1158 use(node.right, JSPrecedence.RELATIONAL_PRECEDENCE); |
1131 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1159 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
1132 } else if (node.element === equalsNullElement || | 1160 } else if (node.element === equalsNullElement || |
1133 node.element === boolifiedEqualsNullElement) { | 1161 node.element === boolifiedEqualsNullElement) { |
1134 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1162 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
1135 use(node.target, JSPrecedence.CALL_PRECEDENCE); | 1163 use(node.target, JSPrecedence.CALL_PRECEDENCE); |
1136 buffer.add('('); | 1164 buffer.add('('); |
1137 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 1165 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
1138 buffer.add(')'); | 1166 buffer.add(')'); |
1139 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1167 endExpression(JSPrecedence.CALL_PRECEDENCE); |
1140 } else { | 1168 } else { |
1141 visitInvokeStatic(node); | 1169 visitInvokeStatic(node); |
1142 } | 1170 } |
1143 } | 1171 } |
1144 | 1172 |
1145 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); | 1173 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); |
1146 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); | 1174 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); |
1147 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); | 1175 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); |
1148 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); | 1176 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); |
1149 // Truncating divide does not have a JS equivalent. | 1177 // Truncating divide does not have a JS equivalent. |
1150 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); | 1178 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); |
1151 // Modulo cannot be mapped to the native operator (different semantics). | 1179 // Modulo cannot be mapped to the native operator (different semantics). |
1152 visitModulo(HModulo node) => visitInvokeStatic(node); | 1180 visitModulo(HModulo node) => visitInvokeStatic(node); |
1153 | 1181 |
1154 visitBitAnd(HBitAnd node) => visitInvokeBinary(node, '&'); | 1182 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); |
1155 visitBitNot(HBitNot node) => visitInvokeUnary(node, '~'); | 1183 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); |
1156 visitBitOr(HBitOr node) => visitInvokeBinary(node, '|'); | 1184 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); |
1157 visitBitXor(HBitXor node) => visitInvokeBinary(node, '^'); | 1185 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); |
1158 | 1186 |
1159 // We need to check if the left operand is negative in order to use | 1187 // We need to check if the left operand is negative in order to use |
1160 // the native operator. | 1188 // the native operator. |
1161 visitShiftRight(HShiftRight node) => visitInvokeStatic(node); | 1189 visitShiftRight(HShiftRight node) => visitInvokeStatic(node); |
1162 | 1190 |
1163 // Shift left cannot be mapped to the native operator (different semantics). | 1191 // Shift left cannot be mapped to the native operator (different semantics). |
1164 visitShiftLeft(HShiftLeft node) => visitInvokeStatic(node); | 1192 visitShiftLeft(HShiftLeft node) => visitInvokeStatic(node); |
1165 | 1193 |
1166 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); | 1194 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); |
1167 | 1195 |
(...skipping 1232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2400 startBailoutSwitch(); | 2428 startBailoutSwitch(); |
2401 } | 2429 } |
2402 } | 2430 } |
2403 | 2431 |
2404 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2432 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
2405 if (labeledBlockInfo.body.start.hasGuards()) { | 2433 if (labeledBlockInfo.body.start.hasGuards()) { |
2406 endBailoutSwitch(); | 2434 endBailoutSwitch(); |
2407 } | 2435 } |
2408 } | 2436 } |
2409 } | 2437 } |
OLD | NEW |