IRTranslator.st
changeset 1 0dd36941955f
child 2 6e1de7f85d59
equal deleted inserted replaced
0:de981640a2ec 1:0dd36941955f
       
     1 "{ Package: 'stx:goodies/newcompiler' }"
       
     2 
       
     3 IRInterpreter subclass:#IRTranslator
       
     4 	instanceVariableNames:'pending gen currentInstr trailerBytes'
       
     5 	classVariableNames:''
       
     6 	poolDictionaries:''
       
     7 	category:'NewCompiler-IR'
       
     8 !
       
     9 
       
    10 IRTranslator comment:'I interpret IRMethod instructions, sending the appropriate bytecode messages to my BytecodeGenerator (gen).  I hold some messages back in pending awaiting certain sequences of them that can be consolidated into single bytecode instructions, otherwise the pending messages are executed in order as if they were executed when they first appeared.'
       
    11 !
       
    12 
       
    13 
       
    14 !IRTranslator class methodsFor:'instance creation'!
       
    15 
       
    16 new
       
    17     ^ self basicNew initialize.
       
    18 
       
    19     "Created: / 11-06-2008 / 09:24:01 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
    20 ! !
       
    21 
       
    22 !IRTranslator methodsFor:'initialization'!
       
    23 
       
    24 initialize
       
    25     "Invoked when a new instance is created."
       
    26 
       
    27     "/ please change as required (and remove this comment)
       
    28     pending := OrderedCollection new.
       
    29     gen := IRBytecodeGenerator new.
       
    30     "/ currentInstr := nil.
       
    31     "/ trailerBytes := nil.
       
    32 
       
    33     "/ super initialize.   -- commented since inherited method does nothing
       
    34 
       
    35     "Created: / 11-06-2008 / 13:46:17 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
    36 ! !
       
    37 
       
    38 !IRTranslator methodsFor:'instructions'!
       
    39 
       
    40 addLiteral: literal
       
    41 	gen addLiteral: literal.
       
    42 !
       
    43 
       
    44 blockReturnTop
       
    45 
       
    46 	self doPending.
       
    47 	gen blockReturnTop.
       
    48 !
       
    49 
       
    50 goto: seqNum
       
    51 
       
    52 	self doPending.
       
    53 	gen goto: seqNum.
       
    54 !
       
    55 
       
    56 if: bool goto: seqNum1 otherwise: seqNum2
       
    57 
       
    58 	self doPending.
       
    59 	gen if: bool goto: seqNum1 otherwise: seqNum2.
       
    60 !
       
    61 
       
    62 jumpOverBlock:  blockNum to: seqNum
       
    63 
       
    64 	self doPending.
       
    65 	gen jumpOverBlock: seqNum.
       
    66 !
       
    67 
       
    68 label: seqNum
       
    69 
       
    70         pending := OrderedCollection new.
       
    71         gen label: seqNum.
       
    72 
       
    73     "Modified: / 11-06-2008 / 10:13:28 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
    74 !
       
    75 
       
    76 popTop
       
    77 
       
    78 	"if last was storeTemp,  storeInstVar storeIntoLiteralVariable then convert to storePopTemp, storePopInstVar storePopIntoLiteralVariable"
       
    79 	#storeTemp: == self pendingSelector ifTrue: [
       
    80 		^ self pendingSelector: #storePopTemp:].
       
    81 	#storeInstVar: == self pendingSelector ifTrue: [
       
    82 		^ self pendingSelector: #storePopInstVar:].
       
    83 	#storeIntoLiteralVariable: == self pendingSelector ifTrue:[
       
    84 		^self pendingSelector: #storePopIntoLiteralVariable:].
       
    85 	"otherwise do normal pop"
       
    86 	self doPending.
       
    87 	gen popTop.
       
    88 !
       
    89 
       
    90 pushBlock: irMethod
       
    91 
       
    92 	| meth block |
       
    93 	meth _ irMethod compiledMethodWith: trailerBytes.
       
    94 	meth isBlockMethod: true.
       
    95 	block _ meth createBlock: nil.
       
    96 	self addPending: (Message selector: #pushLiteral: argument: block)
       
    97 !
       
    98 
       
    99 pushBlockMethod: irMethod
       
   100 
       
   101 	| meth |
       
   102 	meth _ irMethod compiledMethodWith: trailerBytes.
       
   103 	meth isBlockMethod: true.
       
   104 	self addPending: (Message selector: #pushLiteral: argument: meth)
       
   105 !
       
   106 
       
   107 pushDup
       
   108 
       
   109 	self doPending.
       
   110 	gen pushDup.
       
   111 !
       
   112 
       
   113 pushInstVar: index
       
   114 
       
   115 	"self doPending.
       
   116 	gen pushInstVar: index."
       
   117 	self addPending: (Message selector: #pushInstVar: argument: index)
       
   118 !
       
   119 
       
   120 pushLiteral: object
       
   121 
       
   122 	self addPending: (Message selector: #pushLiteral: argument: object)
       
   123 !
       
   124 
       
   125 pushLiteralVariable: object
       
   126 
       
   127 	self addPending: (Message selector: #pushLiteralVariable: argument: object)
       
   128 !
       
   129 
       
   130 pushTemp: index
       
   131 
       
   132 	index = 0 ifTrue: [^ self addPending: (Message selector: #pushReceiver)].
       
   133 
       
   134 	(self pendingMatches: {
       
   135 		[:m | m selector == #storePopTemp: and: [m argument = index]]}
       
   136 		) ifTrue: [^ self pendingSelector: #storeTemp:].
       
   137 
       
   138 	self doPending.
       
   139 
       
   140 	index = -2 ifTrue: [^ gen pushThisContext].
       
   141 	index = -1 ifTrue: [
       
   142 		^ gen pushThisContext;
       
   143 			pushLiteral: MethodContext myEnvFieldIndex;
       
   144 			send: #privGetInstVar:].
       
   145 
       
   146 	gen pushTemp: index.
       
   147 !
       
   148 
       
   149 remoteReturn
       
   150 
       
   151 	self doPending.
       
   152 	gen remoteReturn.
       
   153 !
       
   154 
       
   155 returnTop
       
   156 
       
   157 	#pushReceiver == self pendingSelector ifTrue: [
       
   158 		self pendingSelector: #returnReceiver.
       
   159 		^ self doPending
       
   160 	].
       
   161 	#pushLiteral: == self pendingSelector ifTrue: [
       
   162 		self pendingSelector: #returnConstant:.
       
   163 		^ self doPending
       
   164 	].
       
   165 	#pushInstVar: == self pendingSelector ifTrue: [
       
   166 		self pendingSelector: #returnInstVar:.
       
   167 		^ self doPending
       
   168 	].
       
   169 	self doPending.
       
   170 	gen returnTop.
       
   171 !
       
   172 
       
   173 send: selector
       
   174 
       
   175 	"If get/set inst var, access it directly"
       
   176 	| index |
       
   177 	
       
   178 	((#(privGetInstVar: #privStoreIn:instVar:) identityIncludes: selector) and:
       
   179 	 [self pendingMatches: {
       
   180 		[:m | m selector == #pushReceiver].
       
   181 		[:m | m selector == #pushLiteral: and: [m argument isInteger]]}]
       
   182 	) ifTrue: [
       
   183 		index _ self popPending argument.
       
   184 		self popPending.  "pop pushReceiver"
       
   185 		self addPending: (Message
       
   186 			selector: (selector == #privGetInstVar:
       
   187 				ifTrue: [#pushInstVar:] ifFalse: [#storeInstVar:])
       
   188 			argument: index).
       
   189 		(self pendingMatches: {
       
   190 			[:m | m selector == #storePopInstVar: and: [m argument = index]].
       
   191 			[:m | m selector == #pushInstVar: and: [m argument = index]]}
       
   192 		) ifTrue: [
       
   193 			self popPending.
       
   194 			self pendingSelector: #storeInstVar:.
       
   195 		].
       
   196 		^ self
       
   197 	].
       
   198 	"otherwise do normal send"
       
   199 	self doPending.
       
   200 	gen send: selector.
       
   201 !
       
   202 
       
   203 send: selector toSuperOf: behavior
       
   204 
       
   205 	self doPending.
       
   206 	gen send: selector toSuperOf: behavior.
       
   207 !
       
   208 
       
   209 storeInstVar: index 
       
   210 	"self doPending.
       
   211 	gen storeInstVar: index"
       
   212 	self addPending: (Message selector: #storeInstVar: argument: index)
       
   213 !
       
   214 
       
   215 storeIntoLiteralVariable: assoc
       
   216 
       
   217 	"self doPending.
       
   218 	gen storeIntoLiteralVariable: assoc."
       
   219 	
       
   220 	self addPending: (Message selector: #storeIntoLiteralVariable: argument: assoc)
       
   221 !
       
   222 
       
   223 storeTemp: index
       
   224 
       
   225 	index = -1 "thisEnv" ifTrue: [
       
   226 		self doPending.
       
   227 		^ gen pushThisContext;
       
   228 			pushLiteral: MethodContext myEnvFieldIndex;
       
   229 			send: #privStoreIn:instVar:].
       
   230 
       
   231 	self addPending: (Message selector: #storeTemp: argument: index)
       
   232 ! !
       
   233 
       
   234 !IRTranslator methodsFor:'interpret'!
       
   235 
       
   236 interpret: ir
       
   237 
       
   238         ir optimize.
       
   239         gen numArgs: ir numArgs.
       
   240         ir additionalLiterals do: [:lit | gen addLiteral: lit].
       
   241         super interpret: ir.
       
   242 
       
   243     "Modified: / 11-06-2008 / 13:52:20 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
   244 !
       
   245 
       
   246 interpretAll: irSequences
       
   247 
       
   248 	irSequences withIndexDo: [:seq :i | seq orderNumber: i].
       
   249 	super interpretAll: irSequences.
       
   250 !
       
   251 
       
   252 interpretInstruction: irInstruction
       
   253 
       
   254         currentInstr := irInstruction.
       
   255         super interpretInstruction: irInstruction.
       
   256 
       
   257     "Modified: / 11-06-2008 / 09:20:30 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
   258 ! !
       
   259 
       
   260 !IRTranslator methodsFor:'priv pending'!
       
   261 
       
   262 addPending: message
       
   263 
       
   264 	pending addLast: currentInstr -> message
       
   265 !
       
   266 
       
   267 doPending
       
   268 	"execute pending instructions"
       
   269 
       
   270 	| assoc |
       
   271 	[pending isEmpty] whileFalse: [
       
   272 		assoc _ pending removeFirst.
       
   273 		gen mapBytesTo: assoc key "instr".
       
   274 		assoc value "message" sendTo: gen.
       
   275 	].
       
   276 	gen mapBytesTo: currentInstr.
       
   277 !
       
   278 
       
   279 pendingMatches: blocks
       
   280 	"Return true if each message at end of pending list satisfies its corresponding block.  The number of elements tested equals the number of blocks.  If not enough elements return false"
       
   281 
       
   282 	| messages i |
       
   283 	messages _ pending collect: [:assoc | assoc value].
       
   284 	blocks size > messages size ifTrue: [^ false].
       
   285 	i _ messages size - blocks size.
       
   286 	blocks do: [:b |
       
   287 		(b value: (messages at: (i _ i + 1))) ifFalse: [^ false].
       
   288 	].
       
   289 	^ true
       
   290 !
       
   291 
       
   292 pendingSelector
       
   293 
       
   294 	pending isEmpty ifTrue: [^ nil].
       
   295 	^ pending last value "message" selector
       
   296 !
       
   297 
       
   298 pendingSelector: selector
       
   299 
       
   300 	pending last value "message" setSelector: selector
       
   301 !
       
   302 
       
   303 popPending
       
   304 
       
   305 	^ pending removeLast value "message"
       
   306 ! !
       
   307 
       
   308 !IRTranslator methodsFor:'private - literals'!
       
   309 
       
   310 indexOfLiteral: object
       
   311 
       
   312     | idx | 
       
   313     idx := literalFrame identityIndexOf: object.
       
   314     idx = 0 ifTrue:
       
   315         [literalFrame add: object.
       
   316         idx := literalFrame identityIndexOf: object].
       
   317     ^idx
       
   318 
       
   319     "Created: / 11-06-2008 / 10:56:24 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
   320 ! !
       
   321 
       
   322 !IRTranslator methodsFor:'results'!
       
   323 
       
   324 compiledMethod
       
   325 
       
   326 	^ gen compiledMethodWith: trailerBytes
       
   327 !
       
   328 
       
   329 compiledMethodUsing: aCompiledMethodClass
       
   330 
       
   331         ^ gen compiledMethodUsing: aCompiledMethodClass
       
   332 
       
   333     "Modified: / 11-06-2008 / 14:08:02 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
   334 ! !
       
   335 
       
   336 !IRTranslator class methodsFor:'documentation'!
       
   337 
       
   338 version
       
   339     ^'$Id$'
       
   340 ! !