compiler/PPCCodeGenerator.st
changeset 515 b5316ef15274
parent 502 1e45d3c96ec5
child 516 3b81c9e53352
child 524 f6f68d32de73
equal deleted inserted replaced
502:1e45d3c96ec5 515:b5316ef15274
   129         falseBlock value.
   129         falseBlock value.
   130         compiler dedent.
   130         compiler dedent.
   131         compiler addOnLine: '].'.
   131         compiler addOnLine: '].'.
   132     ]."
   132     ]."
   133     
   133     
   134     guard id: (compiler idFor: guard prefixed: #guard).
   134     guard id: (compiler idFor: guard defaultName: #guard).
   135     guard compileGuard: compiler.
   135     guard compileGuard: compiler.
   136 
   136 
   137     trueBlock isNil ifFalse: [ 
   137     trueBlock isNil ifFalse: [ 
   138         compiler addOnLine: ' ifTrue: ['.
   138         compiler addOnLine: ' ifTrue: ['.
   139         compiler indent.
   139         compiler indent.
   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:[ 
   402         compiler codeReturn: 'failure'. 
   458         compiler codeReturn: 'failure'. 
   403     ] else: [
   459     ] else: [
   404         compiler code: blockBody.    
   460         compiler code: blockBody.    
   405     ]
   461     ]
   406 
   462 
   407     "Modified: / 19-06-2015 / 07:05:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   463     "Modified: / 27-07-2015 / 15:49:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   408 !
   464 !
   409 
   465 
   410 visitAndNode: node
   466 visitAndNode: node
   411     | mementoVar |
   467     | mementoVar |
   412     
   468     
   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.
   534 !
   590 !
   535 
   591 
   536 visitMappedActionNode: node
   592 visitMappedActionNode: node
   537     | child blockNode blockBody |
   593     | child blockNode blockBody |
   538 
   594 
       
   595     self checkBlockIsInlinable: node block. 
   539     child := node child.
   596     child := node child.
   540     blockNode := node block sourceNode copy.
   597     blockNode := node block sourceNode copy.
   541     blockBody := blockNode body.
   598     blockBody := blockNode body.
   542 
   599 
   543     "Block return value is return value of last statement.
   600     "Block return value is return value of last statement.
   567          In the block, replace all references to block argument to
   624          In the block, replace all references to block argument to
   568          my retvalVar. "
   625          my retvalVar. "
   569         | blockArg |
   626         | blockArg |
   570 
   627 
   571         blockArg := blockNode arguments first.
   628         blockArg := blockNode arguments first.
   572         self withAllVariableNodesOf: blockBody do:[:variableNode| 
   629         PPCASTUtilities new withAllVariableNodesOf: blockBody do:[:variableNode| 
   573             variableNode name = blockArg name ifTrue:[ 
   630             variableNode name = blockArg name ifTrue:[ 
   574                 variableNode name: self retvalVar.
   631                 variableNode name: self retvalVar.
   575             ].
   632             ].
   576         ]. 
   633         ]. 
   577     ].
   634     ].
   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.
   705     compiler codeReturn.
   762     compiler codeReturn.
   706 !
   763 !
   707 
   764 
   708 visitPluggableNode: node
   765 visitPluggableNode: node
   709     | blockId |
   766     | blockId |
   710     blockId := compiler idFor: node block prefixed: #block.
   767     blockId := compiler idFor: node block defaultName: #pluggableBlock.
   711     
   768     
   712     compiler addConstant: node block as: blockId.
   769     compiler addConstant: node block as: blockId.
   713     compiler codeReturn: blockId, ' value: context.'.
   770     compiler codeReturn: blockId, ' value: context.'.
   714 !
   771 !
   715 
   772 
   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.