189 ^ compiler checkCache: (compiler idFor: node) |
189 ^ compiler checkCache: (compiler idFor: node) |
190 ! ! |
190 ! ! |
191 |
191 |
192 !PPCCodeGenerator methodsFor:'private'! |
192 !PPCCodeGenerator methodsFor:'private'! |
193 |
193 |
|
194 checkBlockIsInlinable: block |
|
195 "Check whether the given block could be inlined. If not, |
|
196 throw an error. If yes, this method is noop. |
|
197 |
|
198 A block is inlineable if and only if it's a purely functional |
|
199 (see PPCASTUtilities>>checkBlockIsPurelyFunctional:inClass: for |
|
200 details) |
|
201 |
|
202 As a side-effect, copy all self-sent methods from the block |
|
203 to the target class. |
|
204 " |
|
205 | blockNode | |
|
206 |
|
207 blockNode := block sourceNode. |
|
208 "In Smalltalk implementation which use cheap-block optimization (Smalltalk/X) it may |
|
209 happen that home context of the block is nil (in case of cheap blocks)" |
|
210 block home notNil ifTrue:[ |
|
211 | blockClass | |
|
212 |
|
213 blockClass := block home receiver class. |
|
214 PPCASTUtilities new checkNodeIsFunctional: blockNode inClass: blockClass. |
|
215 "The above code should raise an error when block is not functional (i.e., when not |
|
216 inlineable, so if the control flow reach this point, block is OK and we can safely |
|
217 copy self-sent methods." |
|
218 self copySelfSentMethodsOf: blockNode inClass: blockClass |
|
219 ]. |
|
220 |
|
221 "Created: / 27-07-2015 / 14:40:07 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
222 "Modified: / 27-07-2015 / 15:52:59 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
223 ! |
|
224 |
|
225 copySelfSentMethodsOf: anRBProgramNode inClass: aClass |
|
226 PPCASTUtilities new withAllMessageNodesOf: anRBProgramNode sentToSelfDo: [ :node| |
|
227 | method source | |
|
228 |
|
229 method := aClass lookupSelector: node selector. |
|
230 method isNil ifTrue:[ |
|
231 PPCCompilationError new signalWith: 'oops, no method found (internal error)!!'. |
|
232 ]. |
|
233 source := method source. |
|
234 source isNil ifTrue:[ |
|
235 PPCCompilationError new signalWith: 'unavailable source for method ', method printString ,'!!'. |
|
236 ]. |
|
237 "Following actually copies the method to the target class, |
|
238 though the APU is not nice. This has to be cleaned up" |
|
239 (compiler cachedValue: node selector) isNil ifTrue:[ |
|
240 compiler cache: node selector as: (PPCMethod new id: node selector; source: source; yourself). |
|
241 "Now compile self-sends of the just copied method" |
|
242 self copySelfSentMethodsOf: method parseTree inClass: aClass |
|
243 ]. |
|
244 ] |
|
245 |
|
246 "Created: / 27-07-2015 / 14:50:47 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
247 ! |
|
248 |
194 withAllVariableNodesOf: anRBProgramNode do: aBlock |
249 withAllVariableNodesOf: anRBProgramNode do: aBlock |
195 "Enumerate all chilren of `anRBProgramNode` (including itself) |
250 "Enumerate all chilren of `anRBProgramNode` (including itself) |
196 and evaluate `aBlock` for each variable node. |
251 and evaluate `aBlock` for each variable node. |
197 This is a replacement for Smalltalk/X's RBProgramNode>>variableNodesDo: |
252 This is a replacement for Smalltalk/X's RBProgramNode>>variableNodesDo: |
198 which is not present in Pharo" |
253 which is not present in Pharo" |
223 |
278 |
224 notCharSetPredicateBody: node |
279 notCharSetPredicateBody: node |
225 | classificationId classification | |
280 | classificationId classification | |
226 self error: 'deprecated.'. |
281 self error: 'deprecated.'. |
227 classification := node extendClassification: node predicate classification. |
282 classification := node extendClassification: node predicate classification. |
228 classificationId := (compiler idFor: classification prefixed: #classification). |
283 classificationId := (compiler idFor: classification defaultName: #classification). |
229 compiler addConstant: classification as: classificationId. |
284 compiler addConstant: classification as: classificationId. |
230 |
285 |
231 compiler addOnLine: '(', classificationId, ' at: context peek asInteger)'. |
286 compiler addOnLine: '(', classificationId, ' at: context peek asInteger)'. |
232 compiler indent. |
287 compiler indent. |
233 compiler add: ' ifTrue: [ self error: '' predicate not expected'' ]'. |
288 compiler add: ' ifTrue: [ self error: '' predicate not expected'' ]'. |
264 ! |
319 ! |
265 |
320 |
266 startMethodForNode:node |
321 startMethodForNode:node |
267 node isMarkedForInline ifTrue:[ |
322 node isMarkedForInline ifTrue:[ |
268 compiler startInline: (compiler idFor: node). |
323 compiler startInline: (compiler idFor: node). |
269 compiler addComment: 'BEGIN inlined code of ' , node printString. |
324 compiler codeComment: 'BEGIN inlined code of ' , node printString. |
270 compiler indent. |
325 compiler indent. |
271 ] ifFalse:[ |
326 ] ifFalse:[ |
272 compiler startMethod: (compiler idFor: node). |
327 compiler startMethod: (compiler idFor: node). |
273 compiler addComment: 'GENERATED by ' , node printString. |
328 compiler codeComment: 'GENERATED by ' , node printString. |
274 compiler allocateReturnVariable. |
329 compiler allocateReturnVariable. |
275 ]. |
330 ]. |
276 |
331 |
277 "Created: / 23-04-2015 / 15:51:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
332 "Created: / 23-04-2015 / 15:51:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
278 "Modified: / 23-04-2015 / 19:13:25 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
333 "Modified: / 23-04-2015 / 19:13:25 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
309 !PPCCodeGenerator methodsFor:'visiting'! |
364 !PPCCodeGenerator methodsFor:'visiting'! |
310 |
365 |
311 visitActionNode: node |
366 visitActionNode: node |
312 | blockNode blockBody blockNodesVar blockNeedsCollection blockMatches childValueVars | |
367 | blockNode blockBody blockNodesVar blockNeedsCollection blockMatches childValueVars | |
313 |
368 |
|
369 self checkBlockIsInlinable: node block. |
314 blockNode := node block sourceNode copy. |
370 blockNode := node block sourceNode copy. |
315 self assert: blockNode arguments size == 1. |
371 self assert: blockNode arguments size == 1. |
316 blockNodesVar := blockNode arguments first . |
372 blockNodesVar := blockNode arguments first . |
317 blockBody := blockNode body. |
373 blockBody := blockNode body. |
318 |
374 |
333 blockNeedsCollection := true. |
389 blockNeedsCollection := true. |
334 node child isSequenceNode ifTrue:[ |
390 node child isSequenceNode ifTrue:[ |
335 blockNeedsCollection := false. |
391 blockNeedsCollection := false. |
336 blockMatches := IdentityDictionary new."Must use IDENTITY dict as nodes have overwritten their #=!!!!!!" |
392 blockMatches := IdentityDictionary new."Must use IDENTITY dict as nodes have overwritten their #=!!!!!!" |
337 childValueVars := node child preferredChildrenVariableNames. |
393 childValueVars := node child preferredChildrenVariableNames. |
338 self withAllVariableNodesOf: blockBody do:[:variableNode| |
394 PPCASTUtilities new withAllVariableNodesOf: blockBody do:[:variableNode| |
339 variableNode name = blockNodesVar name ifTrue:[ |
395 variableNode name = blockNodesVar name ifTrue:[ |
340 "Check if variable node matches..." |
396 "Check if variable node matches..." |
341 variableNode parent isMessage ifTrue:[ |
397 variableNode parent isMessage ifTrue:[ |
342 | parent | |
398 | parent | |
343 |
399 |
364 ]. |
420 ]. |
365 |
421 |
366 blockNeedsCollection ifTrue:[ |
422 blockNeedsCollection ifTrue:[ |
367 "Bad, we have to use the collection. |
423 "Bad, we have to use the collection. |
368 Replace all references to blockNodeVar to retvalVar..." |
424 Replace all references to blockNodeVar to retvalVar..." |
369 self withAllVariableNodesOf: blockBody do:[:variableNode| |
425 PPCASTUtilities new withAllVariableNodesOf: blockBody do:[:variableNode| |
370 variableNode name = blockNodesVar name ifTrue:[ |
426 variableNode name = blockNodesVar name ifTrue:[ |
371 variableNode name: self retvalVar. |
427 variableNode name: self retvalVar. |
372 ]. |
428 ]. |
373 ]. |
429 ]. |
374 ] ifFalse:[ |
430 ] ifFalse:[ |
432 |
488 |
433 visitCharSetPredicateNode: node |
489 visitCharSetPredicateNode: node |
434 |
490 |
435 | classification classificationId | |
491 | classification classificationId | |
436 classification := node extendClassification: node predicate classification. |
492 classification := node extendClassification: node predicate classification. |
437 classificationId := compiler idFor: classification prefixed: #classification. |
493 classificationId := compiler idFor: classification defaultName: #classification. |
438 compiler addConstant: classification as: classificationId. |
494 compiler addConstant: classification as: classificationId. |
439 |
495 |
440 compiler add: '(', classificationId, ' at: context peek asInteger)'. |
496 compiler add: '(', classificationId, ' at: context peek asInteger)'. |
441 compiler indent. |
497 compiler indent. |
442 compiler add: 'ifFalse: ['. |
498 compiler add: 'ifFalse: ['. |
450 visitCharacterNode: node |
506 visitCharacterNode: node |
451 | chid | |
507 | chid | |
452 node character ppcPrintable ifTrue: [ |
508 node character ppcPrintable ifTrue: [ |
453 chid := node character storeString |
509 chid := node character storeString |
454 ] ifFalse: [ |
510 ] ifFalse: [ |
455 chid := compiler idFor: node character prefixed: #char. |
511 chid := compiler idFor: node character defaultName: #char. |
456 compiler addConstant: (Character value: node character asInteger) as: chid . |
512 compiler addConstant: (Character value: node character asInteger) as: chid . |
457 ]. |
513 ]. |
458 |
514 |
459 compiler add: '(context peek == ', chid, ')'. |
515 compiler add: '(context peek == ', chid, ')'. |
460 compiler indent. |
516 compiler indent. |
593 ]. |
650 ]. |
594 compiler code: blockBody. |
651 compiler code: blockBody. |
595 ] |
652 ] |
596 |
653 |
597 "Created: / 02-06-2015 / 17:28:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
654 "Created: / 02-06-2015 / 17:28:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
598 "Modified: / 19-06-2015 / 07:06:19 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
655 "Modified: / 27-07-2015 / 15:49:58 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
599 ! |
656 ! |
600 |
657 |
601 visitMessagePredicateNode: node |
658 visitMessagePredicateNode: node |
602 compiler add: '(context peek ', node message, ') ifFalse: ['. |
659 compiler add: '(context peek ', node message, ') ifFalse: ['. |
603 compiler codeError: 'predicate not found'. |
660 compiler codeError: 'predicate not found'. |
614 ! |
671 ! |
615 |
672 |
616 visitNotCharSetPredicateNode: node |
673 visitNotCharSetPredicateNode: node |
617 | classificationId classification | |
674 | classificationId classification | |
618 classification := node extendClassification: node predicate classification. |
675 classification := node extendClassification: node predicate classification. |
619 classificationId := (compiler idFor: classification prefixed: #classification). |
676 classificationId := (compiler idFor: classification defaultName: #classification). |
620 compiler addConstant: classification as: classificationId. |
677 compiler addConstant: classification as: classificationId. |
621 |
678 |
622 compiler addOnLine: '(', classificationId, ' at: context peek asInteger)'. |
679 compiler addOnLine: '(', classificationId, ' at: context peek asInteger)'. |
623 compiler indent. |
680 compiler indent. |
624 compiler add: ' ifTrue: ['. |
681 compiler add: ' ifTrue: ['. |
632 visitNotCharacterNode: node |
689 visitNotCharacterNode: node |
633 | chid | |
690 | chid | |
634 node character ppcPrintable ifTrue: [ |
691 node character ppcPrintable ifTrue: [ |
635 chid := node character storeString |
692 chid := node character storeString |
636 ] ifFalse: [ |
693 ] ifFalse: [ |
637 chid := compiler idFor: node character prefixed: #char. |
694 chid := compiler idFor: node character defaultName: #char. |
638 compiler addConstant: (Character value: node character asInteger) as: chid . |
695 compiler addConstant: (Character value: node character asInteger) as: chid . |
639 ]. |
696 ]. |
640 |
697 |
641 compiler add: '(context peek == ', chid, ')'. |
698 compiler add: '(context peek == ', chid, ')'. |
642 compiler indent. |
699 compiler indent. |
751 "Modified: / 26-05-2015 / 19:04:27 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
808 "Modified: / 26-05-2015 / 19:04:27 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
752 ! |
809 ! |
753 |
810 |
754 visitPredicateNode: node |
811 visitPredicateNode: node |
755 | pid | |
812 | pid | |
756 pid := (compiler idFor: node predicate prefixed: #predicate). |
813 pid := (compiler idFor: node predicate defaultName: #predicate). |
757 |
814 |
758 compiler addConstant: node predicate as: pid. |
815 compiler addConstant: node predicate as: pid. |
759 |
816 |
760 compiler add: '(context atEnd not and: [ ', pid , ' value: context uncheckedPeek])'. |
817 compiler add: '(context atEnd not and: [ ', pid , ' value: context uncheckedPeek])'. |
761 compiler indent. |
818 compiler indent. |
842 visitStarCharSetPredicateNode: node |
899 visitStarCharSetPredicateNode: node |
843 | classification classificationId | |
900 | classification classificationId | |
844 |
901 |
845 |
902 |
846 classification := node extendClassification: node predicate classification. |
903 classification := node extendClassification: node predicate classification. |
847 classificationId := compiler idFor: classification prefixed: #classification. |
904 classificationId := compiler idFor: classification defaultName: #classification. |
848 compiler addConstant: classification as: classificationId. |
905 compiler addConstant: classification as: classificationId. |
849 |
906 |
850 compiler codeAssign: 'OrderedCollection new.' to: self retvalVar. |
907 compiler codeAssign: 'OrderedCollection new.' to: self retvalVar. |
851 compiler add: '[ ', classificationId, ' at: context peek asInteger ] whileTrue: ['. |
908 compiler add: '[ ', classificationId, ' at: context peek asInteger ] whileTrue: ['. |
852 compiler indent. |
909 compiler indent. |
874 |
931 |
875 elementVar := compiler allocateTemporaryVariableNamed: 'element'. |
932 elementVar := compiler allocateTemporaryVariableNamed: 'element'. |
876 |
933 |
877 self addGuard: node child ifTrue: nil ifFalse: [ compiler codeReturn: '#()' ]. |
934 self addGuard: node child ifTrue: nil ifFalse: [ compiler codeReturn: '#()' ]. |
878 |
935 |
879 compiler codeAssign: 'OrderedCollection new.' to: self retvalVar. |
|
880 compiler codeAssignParsedValueOf:[ self visit:node child ] to:elementVar. |
936 compiler codeAssignParsedValueOf:[ self visit:node child ] to:elementVar. |
|
937 compiler codeIf: 'error' |
|
938 then: [ |
|
939 compiler codeClearError. |
|
940 compiler codeReturn: '#()'. |
|
941 ] else: [ |
|
942 compiler codeAssign: 'OrderedCollection new.' to: self retvalVar. |
|
943 ]. |
|
944 |
881 compiler add: '[ error ] whileFalse: ['. |
945 compiler add: '[ error ] whileFalse: ['. |
882 compiler indent. |
946 compiler indent. |
883 compiler add: self retvalVar, ' add: ', elementVar, '.'. |
947 compiler add: self retvalVar, ' add: ', elementVar, '.'. |
884 compiler codeAssignParsedValueOf:[ self visit:node child ] to:elementVar. |
948 compiler codeAssignParsedValueOf:[ self visit:node child ] to:elementVar. |
885 compiler dedent. |
949 compiler dedent. |