Hi,
I've refactored the compiler and add a backend support,
right now I've only added Smalltalk (in this patch). The goal
is to add support for C/x86/Java/C#/... C and x86 are particuliary
interesting (at least for me) to add Smalltalk directly in the virtual
machine.
Cheers,
Gwen
diff --git a/packages/stinst/parser/CompilerBackend.st b/packages/stinst/parser/CompilerBackend.st
new file mode 100644
index 0000000..5f72592
--- /dev/null
+++ b/packages/stinst/parser/CompilerBackend.st
@@ -0,0 +1,221 @@
+Object subclass: CompilerBackend [
+
+ <category: 'STInST-Backend'>
+
+ CompilerBackend class [ | optimizedMessages | ]
+
+ CompilerBackend class >> optimizedMessages [
+ <category: 'optimization'>
+
+ ]
+
+ CompilerBackend class >> symbolTable: aSymbolTable stack: aStack [
+ <category: 'instance creation'>
+
+ ^ self new
+ symbolTable: aSymbolTable stack: aStack;
+ yourself
+ ]
+
+ CompilerBackend class >> symbolTable: aSymbolTable [
+ <category: 'instance creation'>
+
+ ^ self symbolTable: aSymbolTable stack: Stack new
+ ]
+
+ CompilerBackend class >> new [
+ <category: 'instance creation'>
+
+ ^ super new
+ initialize;
+ yourself
+ ]
+
+ | stack symbolTable |
+
+ initialize [
+ <category: 'initialization'>
+
+ ]
+
+ symbolTable: aSymbolTable stack: aStack [
+ <category: 'initialization'>
+
+ symbolTable := aSymbolTable.
+ stack := aStack
+ ]
+
+ stack [
+ <category: 'stack'>
+
+ ^ stack
+ ]
+
+ depthIncr [
+ <category: 'stack'>
+
+ stack depthIncr
+ ]
+
+ depthDecr [
+ <category: 'stack'>
+
+ stack depthDecr
+ ]
+
+ depthDecr: n [
+ <category: 'stack'>
+
+ stack depthDecr: n
+ ]
+
+ depthSet: n [
+ <category: 'stack'>
+
+ ^ stack depthSet: n
+ ]
+
+ maxDepth [
+ <category: 'stack'>
+
+
+ ^ stack maxDepth
+ ]
+
+ addLiteral: anObject [
+ <category: 'literals'>
+
+ ^ symbolTable addLiteral: anObject
+ ]
+
+ contents [
+ <category: 'bytecode'>
+
+ ]
+
+ nextPutAll: anArray [
+ <category: 'bytecode'>
+
+ ]
+
+ dupStackTop [
+ <category: 'instructions'>
+
+ ]
+
+ jumpBack: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ jumpTo: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ makeDirtyBlock [
+ <category: 'instructions'>
+
+ ]
+
+ popStackTop [
+ <category: 'instructions'>
+
+ ]
+
+ popStoreIntoArray: anIndex [
+ <category: 'instructions'>
+
+ ]
+
+ pushLiteralVariable: aLiteral [
+ <category: 'instructions'>
+
+ ]
+
+ pushLiteral: aLiteral [
+ <category: 'instructions'>
+
+ ]
+
+ pushInteger: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ pushNil [
+ <category: 'instructions'>
+
+ ]
+
+ pushSelf [
+ <category: 'instructions'>
+
+ ]
+
+ pushTemporaryVariable: anIndex [
+ <category: 'instructions'>
+
+ ]
+
+ pushReceiverVariable: anIndex [
+ <category: 'instructions'>
+
+ ]
+
+ pushOuterVariable: anIndex [
+ <category: 'instructions'>
+
+ ]
+
+ returnContextStackTop [
+ <category: 'instructions'>
+
+ ]
+
+ returnMethodStackTop [
+ <category: 'instructions'>
+
+ ]
+
+ send: aSelector [
+ <category: 'instructions'>
+
+ ]
+
+ sendImmediate: aSelector [
+ <category: 'instructions'>
+
+ ]
+
+ superSend: aSelector [
+ <category: 'instructions'>
+
+ ]
+
+ superSendImmediate: aSelector [
+ <category: 'instructions'>
+
+ ]
+
+ storeLiteralVariable: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ storeReceiverVariable: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ storeTemporaryVariable: anInteger [
+ <category: 'instructions'>
+
+ ]
+
+ storeOuterVariable: anInteger [
+ <category: 'instructions'>
+
+ ]
+]
+
diff --git a/packages/stinst/parser/Makefile.frag b/packages/stinst/parser/Makefile.frag
index 301849b..41858d2 100644
--- a/packages/stinst/parser/Makefile.frag
+++ b/packages/stinst/parser/Makefile.frag
@@ -1,5 +1,5 @@
Parser_FILES = \
-packages/stinst/parser/ParseTreeSearcher.st packages/stinst/parser/RBFormatter.st packages/stinst/parser/RBParseNodes.st packages/stinst/parser/RBParser.st packages/stinst/parser/RBToken.st packages/stinst/parser/OrderedSet.st packages/stinst/parser/PoolResolutionTests.st packages/stinst/parser/STCompLit.st packages/stinst/parser/STCompiler.st packages/stinst/parser/STDecompiler.st packages/stinst/parser/STLoader.st packages/stinst/parser/STLoaderObjs.st packages/stinst/parser/STSymTable.st packages/stinst/parser/RewriteTests.st packages/stinst/parser/SqueakParser.st packages/stinst/parser/STFileParser.st packages/stinst/parser/SIFParser.st packages/stinst/parser/GSTParser.st packages/stinst/parser/STEvaluationDriver.st packages/stinst/parser/Exporter.st packages/stinst/parser/NewSyntaxExporter.st packages/stinst/parser/OldSyntaxExporter.st packages/stinst/parser/SqueakExporter.st packages/stinst/parser/Extensions.st packages/stinst/parser/ChangeLog
+packages/stinst/parser/RBToken.st packages/stinst/parser/RBParseNodes.st packages/stinst/parser/RBParser.st packages/stinst/parser/ParseTreeSearcher.st packages/stinst/parser/RBFormatter.st packages/stinst/parser/OrderedSet.st packages/stinst/parser/STFileParser.st packages/stinst/parser/STCompLit.st packages/stinst/parser/STSymTable.st packages/stinst/parser/STCompiler.st packages/stinst/parser/STDecompiler.st packages/stinst/parser/STLoaderObjs.st packages/stinst/parser/STLoader.st packages/stinst/parser/SqueakParser.st packages/stinst/parser/SIFParser.st packages/stinst/parser/GSTParser.st packages/stinst/parser/STEvaluationDriver.st packages/stinst/parser/Exporter.st packages/stinst/parser/NewSyntaxExporter.st packages/stinst/parser/OldSyntaxExporter.st packages/stinst/parser/SqueakExporter.st packages/stinst/parser/Extensions.st packages/stinst/parser/Stack.st packages/stinst/parser/CompilerBackend.st packages/stinst/parser/STBackend.st packages/stinst/parser/ChangeLog packages/stinst/parser/RewriteTests.st packages/stinst/parser/PoolResolutionTests.st
$(Parser_FILES):
$(srcdir)/packages/stinst/parser/stamp-classes: $(Parser_FILES)
touch $(srcdir)/packages/stinst/parser/stamp-classes
diff --git a/packages/stinst/parser/STBackend.st b/packages/stinst/parser/STBackend.st
new file mode 100644
index 0000000..160c477
--- /dev/null
+++ b/packages/stinst/parser/STBackend.st
@@ -0,0 +1,319 @@
+CompilerBackend subclass: STBackend [
+
+ <category: 'STInST-Backend'>
+
+ <import: VMOtherConstants>
+ <import: VMByteCodeNames>
+
+ STBackend class >> optimizedMessages [
+ <category: 'optimization'>
+
+ ^ optimizedMessages ifNil: [
+ optimizedMessages := IdentityDictionary new
+ at: #whileTrue put: #compileSTWhileLoop:;
+ at: #whileFalse put: #compileSTWhileLoop:;
+ at: #whileTrue: put: #compileSTWhileLoop:;
+ at: #whileFalse: put: #compileSTWhileLoop:;
+ at: #repeat put: #compileSTRepeat:;
+ at: #timesRepeat: put: #compileSTTimesRepeat:;
+ at: #to:do: put: #compileSTLoop:;
+ at: #to:by:do: put: #compileSTLoop:;
+ at: #ifTrue: put: #compileSTIfTrue:;
+ at: #ifTrue:ifFalse: put: #compileSTIfTrueIfFalse:;
+ at: #ifFalse: put: #compileSTIfFalse:;
+ at: #ifFalse:ifTrue: put: #compileSTIfFalseIfTrue:;
+ at: #and: put: #compileSTAnd:;
+ at: #or: put: #compileSTOr:;
+ yourself ]
+ ]
+
+ | bytecodes |
+
+ initialize [
+ <category: 'initialization'>
+
+ super initialize.
+ bytecodes := WriteStream on: (ByteArray new: 240)
+ ]
+
+ selector: aSymbol numArgs: anArgsInteger numTemps: aTempsInteger attributes: anAttributesArray source: aString [
+ <category: 'generation'>
+
+ | method |
+ method := CompiledMethod
+ literals: symbolTable literals
+ numArgs: anArgsInteger
+ numTemps: aTempsInteger
+ attributes: anAttributesArray
+ bytecodes: self contents
+ depth: self maxDepth + aTempsInteger + anArgsInteger.
+ (method descriptor)
+ setSourceCode: aString;
+ methodClass: symbolTable environment;
+ selector: aSymbol.
+ ^ method
+ ]
+
+ contents [
+ <category: 'bytecode'>
+
+ ^ bytecodes contents
+ ]
+
+ nextPutAll: anArray [
+ <category: 'bytecode'>
+
+ bytecodes nextPutAll: anArray
+ ]
+
+ dupStackTop [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: DupStackTop
+ ]
+
+ jumpBack: anInteger [
+ <category: 'instructions'>
+
+ self compileByte: JumpBack arg: anInteger
+ ]
+
+ jumpTo: anInteger [
+ <category: 'instructions'>
+
+ self compileByte: Jump arg: anInteger
+ ]
+
+ makeDirtyBlock [
+ <category: 'instructions'>
+
+ self compileByte: MakeDirtyBlock
+ ]
+
+ popStackTop [
+ <category: 'instructions'>
+
+ self
+ depthDecr;
+ compileByte: PopStackTop
+ ]
+
+ popStoreIntoArray: anIndex [
+ <category: 'instructions'>
+
+ self
+ depthDecr;
+ compileByte: PopStoreIntoArray arg: anIndex
+ ]
+
+ popJumpFalse: anInteger [
+ <category: 'instructions'>
+
+ self
+ depthDecr;
+ compileByte: PopJumpFalse arg: anInteger
+ ]
+
+ popJumpTrue: anInteger [
+ <category: 'instructions'>
+
+ self
+ depthDecr;
+ compileByte: PopJumpTrue arg: anInteger
+ ]
+
+ pushLiteralConstant: aLiteral [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushLitConstant arg: aLiteral
+ ]
+
+ pushLiteralVariable: aLiteral [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushLitVariable arg: aLiteral
+ ]
+
+ pushLiteral: aLiteral [
+ <category: 'instructions'>
+
+ (aLiteral isInteger and: [aLiteral >= 0 and: [aLiteral <= 1073741823]])
+ ifTrue:
+ [^ self pushInteger: aLiteral].
+ aLiteral isNil
+ ifTrue:
+ [^ self pushNil].
+ aLiteral == true
+ ifTrue:
+ [^ self pushTrue].
+ aLiteral == false
+ ifTrue:
+ [^ self pushFalse].
+ self pushLiteralConstant: (self addLiteral: aLiteral)
+ ]
+
+ pushInteger: anInteger [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushInteger arg: anInteger
+ ]
+
+ pushNil [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushSpecial arg: NilIndex
+ ]
+
+ pushSelf [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushSelf
+ ]
+
+ pushTrue [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushSpecial arg: TrueIndex
+ ]
+
+ pushFalse [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushSpecial arg: FalseIndex
+ ]
+
+ pushTemporaryVariable: anIndex [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushTemporaryVariable arg: anIndex
+ ]
+
+ pushReceiverVariable: anIndex [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushReceiverVariable arg: anIndex
+ ]
+
+ pushOuterVariable: anIndex scope: aScope [
+ <category: 'instructions'>
+
+ self
+ depthIncr;
+ compileByte: PushOuterVariable arg: anIndex arg: aScope
+ ]
+
+ returnContextStackTop [
+ <category: 'instructions'>
+
+ self compileByte: ReturnContextStackTop
+ ]
+
+ returnMethodStackTop [
+ <category: 'instructions'>
+
+ self compileByte: ReturnMethodStackTop
+ ]
+
+ send: aSelector [
+ <category: 'instructions'>
+
+ self depthDecr: aSelector numArgs.
+ VMSpecialSelectors at: aSelector ifPresent: [ :index | ^ self sendImmediate: index ].
+ self compileByte: Send arg: (self addLiteral: aSelector) arg: aSelector numArgs
+ ]
+
+ sendImmediate: anIndex [
+ <category: 'instructions'>
+
+ anIndex <= LastImmediateSend
+ ifTrue: [ self compileByte: anIndex arg: 0 ]
+ ifFalse: [ self compileByte: SendImmediate arg: anIndex ]
+ ]
+
+ superSend: aSelector [
+ <category: 'instructions'>
+
+ self depthDecr: aSelector numArgs.
+ VMSpecialSelectors at: aSelector ifPresent: [ :index | ^ self superSendImmediate: index ].
+ self compileByte: SendSuper arg: (self addLiteral: aSelector) arg: aSelector numArgs
+ ]
+
+ superSendImmediate: anIndex [
+ <category: 'instructions'>
+
+ self compileByte: SendImmediateSuper arg: anIndex
+ ]
+
+ storeLiteralVariable: anInteger [
+ <category: 'instructions'>
+
+ self compileByte: StoreLitVariable arg: anInteger
+ ]
+
+ storeReceiverVariable: anInteger [
+ <category: 'instructions'>
+
+ self compileByte: StoreReceiverVariable arg: anInteger
+ ]
+
+ storeTemporaryVariable: anInteger [
+ <category: 'instructions'>
+
+ self compileByte: StoreTemporaryVariable arg: anInteger
+ ]
+
+ storeOuterVariable: anInteger scope: aScope [
+ <category: 'instructions'>
+
+ self
+ compileByte: StoreOuterVariable arg: anInteger arg: aScope
+ ]
+
+ compileByte: aByte [
+ <category: 'private bytecode'>
+
+ self compileByte: aByte arg: 0
+ ]
+
+ compileByte: aByte arg: arg1 arg: arg2 [
+ <category: 'private bytecode'>
+
+ self compileByte: aByte arg: (arg1 bitShift: 8) + arg2
+ ]
+
+ compileByte: aByte arg: arg [
+ <category: 'private bytecode'>
+
+ | n |
+ n := 0.
+ [ (arg bitShift: n) > 255 ] whileTrue: [ n := n - 8 ].
+ n to: -8 by: 8 do: [ :shift |
+ bytecodes
+ nextPut: ExtByte;
+ nextPut: ((arg bitShift: shift) bitAnd: 255) ].
+ bytecodes
+ nextPut: aByte;
+ nextPut: (arg bitAnd: 255)
+ ]
+]
+
diff --git a/packages/stinst/parser/STCompLit.st b/packages/stinst/parser/STCompLit.st
index 33726c0..2e9a5e0 100644
--- a/packages/stinst/parser/STCompLit.st
+++ b/packages/stinst/parser/STCompLit.st
@@ -77,44 +77,12 @@ Eval [
VMOtherConstants at: #VMSpecialSelectors put: selectorsMap.
VMOtherConstants at: #VMSpecialIdentifiers
put: ((LookupTable new: 8)
- at: 'super' put: [:c | c compileError: 'invalid occurrence of super'];
- at: 'self' put: [:c | c compileByte: VMByteCodeNames.PushSelf];
- at: 'nil'
- put:
- [:c |
- c compileByte: VMByteCodeNames.PushSpecial arg: VMOtherConstants.NilIndex];
- at: 'true'
- put:
- [:c |
- c compileByte: VMByteCodeNames.PushSpecial arg: VMOtherConstants.TrueIndex];
- at: 'false'
- put:
- [:c |
- c compileByte: VMByteCodeNames.PushSpecial arg: VMOtherConstants.FalseIndex];
- at: 'thisContext'
- put:
- [:c |
- c
- pushLiteralVariable: #{ContextPart};
- compileByte: VMByteCodeNames.SendImmediate
- arg: VMOtherConstants.ThisContextSpecial];
+ at: 'super' put: [ :c | c compileError: 'invalid occurrence of super' ];
+ at: 'self' put: [ :c | c compilePushSelf ];
+ at: 'nil' put: [ :c | c compilePushNil ];
+ at: 'true' put: [ :c | c compilePushTrue ];
+ at: 'false' put: [ :c | c compilePushFalse ];
+ at: 'thisContext' put: [ :c | c compilePushThisContext ];
yourself).
- VMOtherConstants at: #VMSpecialMethods
- put: ((IdentityDictionary new: 32)
- at: #whileTrue put: #compileWhileLoop:;
- at: #whileFalse put: #compileWhileLoop:;
- at: #whileTrue: put: #compileWhileLoop:;
- at: #whileFalse: put: #compileWhileLoop:;
- at: #repeat put: #compileRepeat:;
- at: #timesRepeat: put: #compileTimesRepeat:;
- at: #to:do: put: #compileLoop:;
- at: #to:by:do: put: #compileLoop:;
- at: #ifTrue: put: #compileBoolean:;
- at: #ifTrue:ifFalse: put: #compileBoolean:;
- at: #ifFalse: put: #compileBoolean:;
- at: #ifFalse:ifTrue: put: #compileBoolean:;
- at: #and: put: #compileBoolean:;
- at: #or: put: #compileBoolean:;
- yourself)
]
diff --git a/packages/stinst/parser/STCompiler.st b/packages/stinst/parser/STCompiler.st
index 74fc9a8..018c925 100644
--- a/packages/stinst/parser/STCompiler.st
+++ b/packages/stinst/parser/STCompiler.st
@@ -53,7 +53,6 @@ Actually, I am used when conditionally compiled code has to be skipped.'>
STFakeCompiler subclass: STCompiler [
- | node destClass symTable parser bytecodes depth maxDepth isInsideBlock |
<comment: 'Unlike my brother STFakeCompiler, I am a real worker. Give me some nodes, and
I will output a full-fledged CompiledMethod!!
@@ -87,22 +86,13 @@ indexed'' bytecode. The resulting stream is
<category: 'System-Compiler'>
OneNode := nil.
- TrueNode := nil.
- FalseNode := nil.
- NilNode := nil.
SuperVariable := nil.
- SelfVariable := nil.
- ThisContextVariable := nil.
STCompiler class >> initialize [
<category: 'initialize'>
+
OneNode := RBLiteralNode value: 1.
- TrueNode := RBLiteralNode value: true.
- FalseNode := RBLiteralNode value: false.
- NilNode := RBLiteralNode value: nil.
- SelfVariable := RBVariableNode named: 'self'.
SuperVariable := RBVariableNode named: 'super'.
- ThisContextVariable := RBVariableNode named: 'thisContext'
]
STCompiler class >> evaluate: aSequenceNode parser: aParser [
@@ -115,7 +105,8 @@ indexed'' bytecode. The resulting stream is
selector: #Doit;
source: nil;
yourself.
- cm := self
+ cm := self
+ backend: STBackend
compile: methodNode
asMethodOf: UndefinedObject
classified: nil
@@ -144,7 +135,8 @@ indexed'' bytecode. The resulting stream is
STCompiler class >> compile: methodNode asMethodOf: aBehavior classified: aString parser: aParser [
<category: 'compilation'>
- ^self
+ ^self
+ backend: STBackend
compile: methodNode
asMethodOf: aBehavior
classified: aString
@@ -152,23 +144,26 @@ indexed'' bytecode. The resulting stream is
environment: nil
]
- STCompiler class >> compile: methodNode asMethodOf: aBehavior classified: aString parser: aParser environment: aNamespace [
+ STCompiler class >> backend: aCompilerBackend compile: methodNode asMethodOf: aBehavior classified: aString parser: aParser environment: aNamespace [
<category: 'compilation'>
| compiler method |
compiler := self new.
- compiler class: aBehavior parser: aParser.
+ compiler class: aBehavior parser: aParser backend: aCompilerBackend.
aNamespace isNil ifFalse: [compiler addPool: aNamespace].
method := compiler visitNode: methodNode.
aString isNil ifFalse: [ method methodCategory: aString ].
^method
]
- class: aBehavior parser: aParser [
- <category: 'private'>
+ | backend node destClass symTable parser bytecodes depth maxDepth isInsideBlock |
+
+ class: aBehavior parser: aParser backend: aCompilerBackend [
+ <category: 'initialization'>
+
destClass := aBehavior.
symTable := STSymbolTable new.
+ backend := aCompilerBackend symbolTable: symTable.
parser := aParser.
- bytecodes := WriteStream on: (ByteArray new: 240).
isInsideBlock := 0.
symTable declareEnvironment: aBehavior
]
@@ -190,15 +185,15 @@ indexed'' bytecode. The resulting stream is
bytecodesFor: aBlockNode atEndDo: aBlock [
<category: 'accessing'>
- | saveBytecodes result |
- saveBytecodes := bytecodes.
- bytecodes := WriteStream on: (ByteArray new: 240).
+ | saveBackend result |
+ saveBackend := backend.
+ backend := STBackend symbolTable: symTable stack: backend stack.
self declareArgumentsAndTemporaries: aBlockNode.
self compileStatements: aBlockNode body.
self undeclareArgumentsAndTemporaries: aBlockNode.
aBlock value.
- result := bytecodes contents.
- bytecodes := saveBytecodes.
+ result := backend contents.
+ backend := saveBackend.
^result
]
@@ -219,7 +214,7 @@ indexed'' bytecode. The resulting stream is
jumpLen := displacement + 2.
jumpLen := displacement + (self sizeOfJump: jumpLen).
jumpLen := displacement + (self sizeOfJump: jumpLen).
- self compileByte: JumpBack arg: jumpLen
+ backend jumpBack: jumpLen
]
compileJump: displacement if: jmpCondition [
@@ -229,10 +224,9 @@ indexed'' bytecode. The resulting stream is
["Should not happen"
^self error: 'Cannot compile backwards conditional jumps'].
- self depthDecr: 1.
jmpCondition
- ifFalse: [self compileByte: PopJumpFalse arg: displacement]
- ifTrue: [self compileByte: PopJumpTrue arg: displacement]
+ ifFalse: [ backend popJumpFalse: displacement]
+ ifTrue: [ backend popJumpTrue: displacement]
]
compileWarning: aString [
@@ -261,40 +255,6 @@ indexed'' bytecode. The resulting stream is
self declareTemporaries: node body
]
- maxDepth [
- <category: 'accessing'>
- ^maxDepth
- ]
-
- depthDecr: n [
- <category: 'accessing'>
- depth := depth - n
- ]
-
- depthIncr [
- <category: 'accessing'>
- depth = maxDepth
- ifTrue:
- [depth := depth + 1.
- maxDepth := maxDepth + 1]
- ifFalse: [depth := depth + 1]
- ]
-
- depthSet: n [
- "n can be an integer, or a previously returned value (in which case the
- exact status at the moment of the previous call is remembered)"
-
- <category: 'accessing'>
- | oldDepth |
- oldDepth := n -> maxDepth.
- n isInteger
- ifTrue: [depth := maxDepth := n]
- ifFalse:
- [depth := n key.
- maxDepth := n value].
- ^oldDepth
- ]
-
literals [
<category: 'accessing'>
^symTable literals
@@ -314,38 +274,6 @@ indexed'' bytecode. The resulting stream is
^definition
]
- compileByte: aByte [
- <category: 'accessing'>
- self compileByte: aByte arg: 0
- ]
-
- compileByte: aByte arg: arg [
- <category: 'accessing'>
- | n |
- n := 0.
- [(arg bitShift: n) > 255] whileTrue: [n := n - 8].
- n to: -8
- by: 8
- do:
- [:shift |
- bytecodes
- nextPut: ExtByte;
- nextPut: ((arg bitShift: shift) bitAnd: 255)].
- bytecodes
- nextPut: aByte;
- nextPut: (arg bitAnd: 255)
- ]
-
- compileByte: aByte arg: arg1 arg: arg2 [
- <category: 'accessing'>
- self compileByte: aByte arg: (arg1 bitShift: 8) + arg2
- ]
-
- nextPutAll: aByteArray [
- <category: 'accessing'>
- bytecodes nextPutAll: aByteArray
- ]
-
isInsideBlock [
<category: 'accessing'>
^isInsideBlock > 0
@@ -353,32 +281,28 @@ indexed'' bytecode. The resulting stream is
pushLiteral: value [
<category: 'accessing'>
- | definition |
(value isInteger and: [value >= 0 and: [value <= 1073741823]])
ifTrue:
- [self compileByte: PushInteger arg: value.
+ [backend pushInteger: value.
^self].
value isNil
ifTrue:
- [self compileByte: PushSpecial arg: NilIndex.
+ [backend pushNil.
^self].
value == true
ifTrue:
- [self compileByte: PushSpecial arg: TrueIndex.
+ [backend pushTrue.
^self].
value == false
ifTrue:
- [self compileByte: PushSpecial arg: FalseIndex.
+ [backend pushFalse.
^self].
- definition := self addLiteral: value.
- self compileByte: PushLitConstant arg: definition
+ backend pushLitConstant: value
]
pushLiteralVariable: value [
<category: 'accessing'>
- | definition |
- definition := self addLiteral: value.
- self compileByte: PushLitVariable arg: definition
+ backend pushLitVariable: value
]
sizeOfJump: distance [
@@ -469,17 +393,12 @@ indexed'' bytecode. The resulting stream is
self undeclareArgumentsAndTemporaries: node.
symTable finish.
attributes := self compileMethodAttributes: node primitiveSources.
- method := CompiledMethod
- literals: symTable literals
- numArgs: node arguments size
- numTemps: node body temporaries size
- attributes: attributes
- bytecodes: bytecodes contents
- depth: maxDepth + node body temporaries size + node arguments size.
- (method descriptor)
- setSourceCode: node source asSourceCode;
- methodClass: symTable environment;
- selector: node selector.
+ method := backend
+ selector: node selector
+ numArgs: node arguments size
+ numTemps: node body temporaries size
+ attributes: attributes
+ source: node source asSourceCode.
method attributesDo:
[:ann |
| handler error |
@@ -499,19 +418,15 @@ indexed'' bytecode. The resulting stream is
instead of a simple pop."
<category: 'visiting RBArrayConstructorNodes'>
- self
- depthIncr;
- pushLiteralVariable: (Smalltalk associationAt: #Array);
- depthIncr;
- compileByte: PushInteger arg: aNode body statements size;
- depthDecr: 1;
- compileByte: SendImmediate arg: NewColonSpecial.
+ backend
+ pushLiteralVariable: (backend addLiteral: (Smalltalk associationAt: #Array));
+ pushInteger: aNode body statements size;
+ sendImmediate: NewColonSpecial.
aNode body statements keysAndValuesDo:
- [:index :each |
+ [ :index :each |
each acceptVisitor: self.
- self
- depthDecr: 1;
- compileByte: PopStoreIntoArray arg: index - 1]
+ backend
+ popStoreIntoArray: index - 1 ]
]
acceptBlockNode: aNode [
@@ -530,45 +445,32 @@ indexed'' bytecode. The resulting stream is
<category: 'visiting RBBlockNodes'>
| bc depth block clean |
- depth := self depthSet: aNode arguments size + aNode body temporaries size.
- aNode body statements isEmpty
- ifTrue: [aNode body addNode: (RBLiteralNode value: nil)].
- bc := self insideNewScopeDo:
- [self bytecodesFor: aNode
- atEndDo:
- [aNode body lastIsReturn ifFalse: [self compileByte: ReturnContextStackTop]]].
+ depth := backend depthSet: aNode arguments size + aNode body temporaries size.
+ aNode body statements isEmpty ifTrue: [aNode body addNode: (RBLiteralNode value: nil)].
+ bc := self insideNewScopeDo: [ self bytecodesFor: aNode atEndDo: [ aNode body lastIsReturn ifFalse: [ backend returnContextStackTop ] ] ].
block := CompiledBlock
numArgs: aNode arguments size
numTemps: aNode body temporaries size
bytecodes: bc
- depth: self maxDepth
+ depth: backend maxDepth
literals: self literals.
- self depthSet: depth.
+ backend depthSet: depth.
clean := block flags.
clean == 0
ifTrue:
- [self
- pushLiteral: (BlockClosure block: block receiver: symTable environment).
- ^aNode].
- self pushLiteral: block.
- self compileByte: MakeDirtyBlock
+ [ ^ backend pushLiteral: (BlockClosure block: block receiver: symTable environment) ].
+ backend
+ pushLiteral: block;
+ makeDirtyBlock
]
compileStatements: aNode [
<category: 'visiting RBBlockNodes'>
aNode statements keysAndValuesDo:
[:index :each |
- index = 1
- ifFalse:
- [self
- depthDecr: 1;
- compileByte: PopStackTop].
- each acceptVisitor: self].
- aNode statements isEmpty
- ifTrue:
- [self
- depthIncr;
- compileByte: PushSpecial arg: NilIndex]
+ index = 1 ifFalse: [ backend popStackTop ].
+ each acceptVisitor: self ].
+ aNode statements isEmpty ifTrue: [ backend pushNil ]
]
acceptCascadeNode: aNode [
@@ -580,36 +482,29 @@ indexed'' bytecode. The resulting stream is
first := messages at: 1.
first receiver = SuperVariable
ifTrue:
- [aNode messages do: [:each | self compileSendToSuper: each]
- separatedBy:
- [self
- depthDecr: 1;
- compileByte: PopStackTop].
- ^aNode].
+ [ aNode messages do: [:each | self compileSendToSuper: each]
+ separatedBy: [ backend popStackTop ].
+ ^ aNode ].
first receiver acceptVisitor: self.
- self
- depthIncr;
- compileByte: DupStackTop.
+ backend dupStackTop.
self compileMessage: first.
messages
from: 2
to: messages size - 1
do:
- [:each |
- self
- compileByte: PopStackTop;
- compileByte: DupStackTop.
+ [:each |
+ backend
+ popStackTop;
+ dupStackTop.
self compileMessage: each].
- self
- depthDecr: 1;
- compileByte: PopStackTop.
+ backend popStackTop.
self compileMessage: messages last
]
acceptOptimizedNode: aNode [
<category: 'visiting RBOptimizedNodes'>
- self depthIncr.
- self pushLiteral: (self class evaluate: aNode body parser: parser)
+
+ backend pushLiteral: (self class evaluate: aNode body parser: parser)
]
acceptLiteralNode: aNode [
@@ -617,9 +512,9 @@ indexed'' bytecode. The resulting stream is
it represents."
<category: 'visiting RBLiteralNodes'>
- self depthIncr.
+
aNode compiler: self.
- self pushLiteral: aNode value
+ backend pushLiteral: aNode value
]
acceptAssignmentNode: aNode [
@@ -633,18 +528,11 @@ indexed'' bytecode. The resulting stream is
]
acceptMessageNode: aNode [
- "RBMessageNode contains a message send. Its instance variable are
- a receiver, selector, and arguments."
-
<category: 'compiling'>
- | specialSelector |
- aNode receiver = SuperVariable
- ifTrue:
- [self compileSendToSuper: aNode.
- ^true].
- specialSelector := VMSpecialMethods at: aNode selector ifAbsent: [nil].
- specialSelector isNil
- ifFalse: [(self perform: specialSelector with: aNode) ifTrue: [^false]].
+
+ aNode receiver = SuperVariable ifTrue: [ ^ self compileSendToSuper: aNode ].
+ backend class optimizedMessages at: aNode selector ifPresent: [ :aSymbol |
+ (self perform: aSymbol with: aNode) ifTrue: [ ^ self ] ].
aNode receiver acceptVisitor: self.
self compileMessage: aNode
]
@@ -657,241 +545,26 @@ indexed'' bytecode. The resulting stream is
<category: 'compiling'>
| args litIndex |
aNode arguments do: [:each | each acceptVisitor: self].
- VMSpecialSelectors at: aNode selector
- ifPresent:
- [:idx |
- idx <= LastImmediateSend
- ifTrue: [self compileByte: idx arg: 0]
- ifFalse: [self compileByte: SendImmediate arg: idx].
- ^aNode].
- args := aNode arguments size.
- litIndex := self addLiteral: aNode selector.
- self
- compileByte: Send
- arg: litIndex
- arg: args
- ]
-
- compileRepeat: aNode [
- "Answer whether the loop can be optimized (that is,
- whether the only parameter is a STBlockNode)"
-
- <category: 'compiling'>
- | whileBytecodes |
- aNode receiver isBlock ifFalse: [^false].
- (aNode receiver arguments isEmpty
- and: [aNode receiver body temporaries isEmpty]) ifFalse: [^false].
- whileBytecodes := self bytecodesFor: aNode receiver
- atEndDo:
- [self
- compileByte: PopStackTop;
- depthDecr: 1].
- self nextPutAll: whileBytecodes.
- self compileBackJump: whileBytecodes size.
-
- "The optimizer might like to see the return value of #repeat."
- self
- depthIncr;
- compileByte: PushSpecial arg: NilIndex.
- ^true
- ]
-
- compileWhileLoop: aNode [
- "Answer whether the while loop can be optimized (that is,
- whether the only parameter is a STBlockNode)"
-
- <category: 'compiling'>
- | whileBytecodes argBytecodes jumpOffsets |
- aNode receiver isBlock ifFalse: [^false].
- (aNode receiver arguments isEmpty
- and: [aNode receiver body temporaries isEmpty]) ifFalse: [^false].
- argBytecodes := #().
- aNode arguments do:
- [:onlyArgument |
- onlyArgument isBlock ifFalse: [^false].
- (onlyArgument arguments isEmpty
- and: [onlyArgument body temporaries isEmpty]) ifFalse: [^false].
- argBytecodes := self bytecodesFor: onlyArgument
- atEndDo:
- [self
- compileByte: PopStackTop;
- depthDecr: 1]].
- whileBytecodes := self bytecodesFor: aNode receiver.
- self nextPutAll: whileBytecodes.
- jumpOffsets := self displacementsToJumpAround: argBytecodes size
- and: whileBytecodes size + 2. "for jump around jump"
-
- "The if: clause means: if selector is whileFalse:, compile
- a 'pop/jump if true'; else compile a 'pop/jump if false'"
- self compileJump: (self sizeOfJump: jumpOffsets value)
- if: (aNode selector == #whileTrue or: [aNode selector == #whileTrue:]).
- self compileByte: Jump arg: jumpOffsets value.
- argBytecodes isNil ifFalse: [self nextPutAll: argBytecodes].
- self compileByte: JumpBack arg: jumpOffsets key.
-
- "Somebody might want to use the return value of #whileTrue:
- and #whileFalse:"
- self
- depthIncr;
- compileByte: PushSpecial arg: NilIndex.
- ^true
+ backend send: aNode selector
]
compileSendToSuper: aNode [
<category: 'compiling'>
| litIndex args |
- self
- depthIncr;
- compileByte: PushSelf.
+ backend pushSelf.
aNode arguments do: [:each | each acceptVisitor: self].
- self pushLiteral: destClass superclass.
- VMSpecialSelectors at: aNode selector
- ifPresent:
- [:idx |
- self compileByte: SendImmediateSuper arg: idx.
- ^aNode].
+ backend pushLiteral: destClass superclass.
litIndex := self addLiteral: aNode selector.
args := aNode arguments size.
- self
- compileByte: SendSuper
- arg: litIndex
- arg: args.
- self depthDecr: aNode arguments size
- ]
-
- compileTimesRepeat: aNode [
- <category: 'compiling'>
- "aNode receiver acceptVisitor: self."
-
- | block |
- block := aNode arguments first.
- (block arguments isEmpty and: [block body temporaries isEmpty])
- ifFalse: [^false].
- ^false
- ]
-
- compileLoop: aNode [
- <category: 'compiling'>
- "aNode receiver acceptVisitor: self."
-
- | stop step block |
- aNode arguments do:
- [:each |
- stop := step. "to:"
- step := block. "by:"
- block := each "do:"].
- block isBlock ifFalse: [^false].
- (block arguments size = 1 and: [block body temporaries isEmpty])
- ifFalse: [^false].
- stop isNil
- ifTrue:
- [stop := step.
- step := OneNode "#to:do:"]
- ifFalse: [step isImmediate ifFalse: [^false]].
- ^false
- ]
-
- compileBoolean: aNode [
- <category: 'compiling'>
- | bc1 ret1 bc2 selector |
- aNode arguments do:
- [:each |
- each isBlock ifFalse: [^false].
- (each arguments isEmpty and: [each body temporaries isEmpty])
- ifFalse: [^false].
- bc1 isNil
- ifTrue:
- [bc1 := self bytecodesFor: each.
- ret1 := each body lastIsReturn]
- ifFalse: [bc2 := self bytecodesFor: each]].
- aNode receiver acceptVisitor: self.
- selector := aNode selector.
- bc2 isNil
- ifTrue:
- ["Transform everything into #ifTrue:ifFalse: or #ifFalse:ifTrue:"
-
- selector == #ifTrue:
- ifTrue:
- [selector := #ifTrue:ifFalse:.
- bc2 := NilIndex "Push nil"].
- selector == #ifFalse:
- ifTrue:
- [selector := #ifFalse:ifTrue:.
- bc2 := NilIndex "Push nil"].
- selector == #and:
- ifTrue:
- [selector := #ifTrue:ifFalse:.
- bc2 := FalseIndex "Push false"].
- selector == #or:
- ifTrue:
- [selector := #ifFalse:ifTrue:.
- bc2 := TrueIndex "Push true"].
- bc2 :=
- {PushSpecial.
- bc2}.
- ^self
- compileBoolean: aNode
- longBranch: bc1
- returns: ret1
- shortBranch: bc2
- longIfTrue: selector == #ifTrue:ifFalse:].
- selector == #ifTrue:ifFalse:
- ifTrue:
- [^self
- compileIfTrue: bc1
- returns: ret1
- ifFalse: bc2].
- selector == #ifFalse:ifTrue:
- ifTrue:
- [^self
- compileIfFalse: bc1
- returns: ret1
- ifTrue: bc2].
- ^self error: 'bad boolean message selector'
- ]
-
- compileBoolean: aNode longBranch: bc1 returns: ret1 shortBranch: bc2 longIfTrue: longIfTrue [
- <category: 'compiling'>
- self compileJump: bc1 size + (ret1 ifTrue: [0] ifFalse: [2])
- if: longIfTrue not.
- self nextPutAll: bc1.
- ret1 ifFalse: [self compileByte: Jump arg: bc2 size].
- self nextPutAll: bc2.
- ^true
- ]
-
- compileIfTrue: bcTrue returns: bcTrueReturns ifFalse: bcFalse [
- <category: 'compiling'>
- | trueSize |
- trueSize := bcTrueReturns
- ifTrue: [bcTrue size]
- ifFalse: [bcTrue size + (self sizeOfJump: bcFalse size)].
- self compileJump: trueSize if: false.
- self nextPutAll: bcTrue.
- bcTrueReturns ifFalse: [self compileByte: Jump arg: bcFalse size].
- self nextPutAll: bcFalse.
- ^true
- ]
-
- compileIfFalse: bcFalse returns: bcFalseReturns ifTrue: bcTrue [
- <category: 'compiling'>
- | falseSize |
- falseSize := bcFalseReturns
- ifTrue: [bcFalse size]
- ifFalse: [bcFalse size + (self sizeOfJump: bcTrue size)].
- self compileJump: falseSize if: true.
- self nextPutAll: bcFalse.
- bcFalseReturns ifFalse: [self compileByte: Jump arg: bcTrue size].
- self nextPutAll: bcTrue.
- ^true
+ backend superSend: aNode selector
]
acceptReturnNode: aNode [
<category: 'compiling'>
aNode value acceptVisitor: self.
self isInsideBlock
- ifTrue: [self compileByte: ReturnMethodStackTop]
- ifFalse: [self compileByte: ReturnContextStackTop]
+ ifTrue: [ backend returnMethodStackTop ]
+ ifFalse: [ backend returnContextStackTop ]
]
compileAssignmentFor: aNode [
@@ -907,55 +580,289 @@ indexed'' bytecode. The resulting stream is
[^self compileStoreTemporary: definition
scopes: (symTable outerScopes: aNode name)].
(symTable isReceiver: aNode name)
- ifTrue: [^self compileByte: StoreReceiverVariable arg: definition].
- self compileByte: StoreLitVariable arg: definition.
- self compileByte: PopStackTop.
- self compileByte: PushLitVariable arg: definition
+ ifTrue: [^backend storeReceiverVariable: definition].
+ backend storeLiteralVariable: definition.
+ backend popStackTop.
+ backend pushLiteralVariable: definition
]
acceptVariableNode: aNode [
<category: 'visiting RBVariableNodes'>
| locationType definition |
- self depthIncr.
- VMSpecialIdentifiers at: aNode name
- ifPresent:
- [:block |
- block value: self.
- ^aNode].
+ VMSpecialIdentifiers at: aNode name ifPresent: [:block | ^ block value: self ].
definition := self lookupName: aNode name.
(symTable isTemporary: aNode name)
ifTrue:
- [^self compilePushTemporary: definition
- scopes: (symTable outerScopes: aNode name)].
+ [^self compilePushTemporary: definition scopes: (symTable outerScopes: aNode name)].
(symTable isReceiver: aNode name)
ifTrue:
- [self compileByte: PushReceiverVariable arg: definition.
- ^aNode].
- self compileByte: PushLitVariable arg: definition
+ [ ^ backend pushReceiverVariable: definition ].
+ backend pushLiteralVariable: definition
]
compilePushTemporary: number scopes: outerScopes [
<category: 'visiting RBVariableNodes'>
outerScopes = 0
ifFalse:
- [self
- compileByte: PushOuterVariable
- arg: number
- arg: outerScopes.
- ^self].
- self compileByte: PushTemporaryVariable arg: number
+ [ ^ backend pushOuterVariable: number scope: outerScopes ].
+ backend pushTemporaryVariable: number
+ ]
+
+ compilePushSelf [
+
+ backend pushSelf
+ ]
+
+ compilePushTrue [
+
+ backend pushTrue
+ ]
+
+ compilePushFalse [
+
+ backend pushFalse
+ ]
+
+ compilePushNil [
+
+ backend pushNil
+ ]
+
+ compilePushThisContext [
+
+ backend
+ pushLiteralVariable: (backend addLiteral: #{ContextPart});
+ send: #thisContext
]
compileStoreTemporary: number scopes: outerScopes [
<category: 'visiting RBVariableNodes'>
- outerScopes = 0
- ifFalse:
- [self
- compileByte: StoreOuterVariable
- arg: number
- arg: outerScopes.
- ^self].
- self compileByte: StoreTemporaryVariable arg: number
+ outerScopes = 0 ifFalse: [ ^ backend storeOuterVariable: number scope: outerScopes ].
+ backend storeTemporaryVariable: number
+ ]
+
+ checkCompileSTWhileLoop: aNode [
+ <category: '*STInST-Backend'>
+
+ aNode receiver isBlock ifFalse: [ ^ false ].
+ (aNode receiver arguments isEmpty and: [ aNode receiver body temporaries isEmpty ]) ifFalse: [ ^ false ].
+ aNode arguments do: [ :block |
+ block isBlock ifFalse: [ ^ false ].
+ (block arguments isEmpty and: [ block body temporaries isEmpty ]) ifFalse: [ ^ false ] ].
+ ^ true
+ ]
+
+ compileSTWhileLoop: aNode [
+ <category: '*STInST-Backend'>
+
+ | whileBytecodes argBytecodes jumpOffsets |
+ (self checkCompileSTWhileLoop: aNode) ifFalse: [ ^ false ].
+ argBytecodes := aNode arguments isEmpty ifTrue: [ #() ] ifFalse: [ self bytecodesFor: aNode arguments first atEndDo: [ backend popStackTop ] ].
+ whileBytecodes := self bytecodesFor: aNode receiver.
+ backend nextPutAll: whileBytecodes.
+ jumpOffsets := self displacementsToJumpAround: argBytecodes size and: whileBytecodes size + 2.
+ self compileJump: (self sizeOfJump: jumpOffsets value) if: (aNode selector == #whileTrue or: [ aNode selector == #whileTrue: ]).
+ backend jumpTo: jumpOffsets value.
+ backend nextPutAll: argBytecodes.
+ backend jumpBack: jumpOffsets key.
+ backend pushNil.
+ ^ true
+ ]
+
+ checkCompileSTBoolean: aNode [
+ <category: '*STInST-Backend'>
+
+ aNode arguments do: [ :each |
+ each isBlock ifFalse: [ ^ false ].
+ (each arguments isEmpty and: [each body temporaries isEmpty]) ifFalse: [ ^ false ] ].
+ ^ true
+ ]
+
+ compileSTAnd: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := { PushSpecial. FalseIndex }.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileBoolean: aNode
+ longBranch: bc1
+ returns: ret1
+ shortBranch: bc2
+ longIfTrue: true
+ ]
+
+ compileSTOr: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := { PushSpecial. TrueIndex }.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileBoolean: aNode
+ longBranch: bc1
+ returns: ret1
+ shortBranch: bc2
+ longIfTrue: false
+ ]
+
+ compileSTIfTrue: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := { PushSpecial. NilIndex }.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileBoolean: aNode
+ longBranch: bc1
+ returns: ret1
+ shortBranch: bc2
+ longIfTrue: true
+ ]
+
+ compileSTIfFalse: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := { PushSpecial. NilIndex }.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileBoolean: aNode
+ longBranch: bc1
+ returns: ret1
+ shortBranch: bc2
+ longIfTrue: false
+ ]
+
+ compileSTIfTrueIfFalse: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := self bytecodesFor: aNode arguments second.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileIfTrue: bc1
+ returns: ret1
+ ifFalse: bc2
+ ]
+
+ compileSTIfFalseIfTrue: aNode [
+ <category: '*STInST-Backend'>
+
+ | bc1 bc2 ret1 selector |
+ (self checkCompileSTBoolean: aNode) ifFalse: [ ^ false ].
+ bc1 := self bytecodesFor: aNode arguments first.
+ ret1 := aNode arguments first body lastIsReturn.
+ bc2 := self bytecodesFor: aNode arguments second.
+ aNode receiver acceptVisitor: self.
+ selector := aNode selector.
+ ^ self
+ compileIfFalse: bc1
+ returns: ret1
+ ifTrue: bc2
+ ]
+
+ compileBoolean: aNode longBranch: bc1 returns: ret1 shortBranch: bc2 longIfTrue: longIfTrue [
+ <category: '*STInST-Backend'>
+
+ self compileJump: bc1 size + (ret1 ifTrue: [0] ifFalse: [2])
+ if: longIfTrue not.
+ backend nextPutAll: bc1.
+ ret1 ifFalse: [backend jumpTo: bc2 size].
+ backend nextPutAll: bc2.
+ ^true
+ ]
+
+ compileIfTrue: bcTrue returns: bcTrueReturns ifFalse: bcFalse [
+ <category: '*STInST-Backend'>
+
+ | trueSize |
+ trueSize := bcTrueReturns
+ ifTrue: [bcTrue size]
+ ifFalse: [bcTrue size + (self sizeOfJump: bcFalse size)].
+ self compileJump: trueSize if: false.
+ backend nextPutAll: bcTrue.
+ bcTrueReturns ifFalse: [ backend jumpTo: bcFalse size ].
+ backend nextPutAll: bcFalse.
+ ^true
+ ]
+
+ compileIfFalse: bcFalse returns: bcFalseReturns ifTrue: bcTrue [
+ <category: '*STInST-Backend'>
+
+ | falseSize |
+ falseSize := bcFalseReturns
+ ifTrue: [bcFalse size]
+ ifFalse: [bcFalse size + (self sizeOfJump: bcTrue size)].
+ self compileJump: falseSize if: true.
+ backend nextPutAll: bcFalse.
+ bcFalseReturns ifFalse: [backend jumpTo: bcTrue size].
+ backend nextPutAll: bcTrue.
+ ^true
+ ]
+
+ compileSTRepeat: aNode [
+ <category: '*STInST-Backend'>
+
+ | whileBytecodes |
+ aNode receiver isBlock ifFalse: [^false].
+ (aNode receiver arguments isEmpty and: [aNode receiver body temporaries isEmpty]) ifFalse: [^false].
+ whileBytecodes := self bytecodesFor: aNode receiver atEndDo: [ backend popStackTop ].
+ backend nextPutAll: whileBytecodes.
+ self compileBackJump: whileBytecodes size.
+ "The optimizer might like to see the return value of #repeat."
+ backend pushNil.
+ ^ true
+ ]
+
+ compileSTLoop: aNode [
+ <category: '*STInST-Backend'>
+
+ | stop step block |
+ aNode arguments do:
+ [:each |
+ stop := step. "to:"
+ step := block. "by:"
+ block := each "do:"].
+ block isBlock ifFalse: [^false].
+ (block arguments size = 1 and: [block body temporaries isEmpty])
+ ifFalse: [^false].
+ stop isNil
+ ifTrue:
+ [stop := step.
+ step := OneNode "#to:do:"]
+ ifFalse: [step isImmediate ifFalse: [^false]].
+ ^false
+ ]
+
+ compileSTTimesRepeat: aNode [
+ <category: '*STInST-Backend'>
+
+ | block |
+ block := aNode arguments first.
+ (block arguments isEmpty and: [block body temporaries isEmpty])
+ ifFalse: [^false].
+ ^false
]
compileMethodAttributes: attributes [
diff --git a/packages/stinst/parser/Stack.st b/packages/stinst/parser/Stack.st
new file mode 100644
index 0000000..d6d51af
--- /dev/null
+++ b/packages/stinst/parser/Stack.st
@@ -0,0 +1,62 @@
+Object subclass: Stack [
+
+ Stack class >> new [
+ <category: 'instance creation'>
+
+ ^ super new
+ initialize;
+ yourself
+ ]
+
+ | depth maxDepth |
+
+ initialize [
+ <category: 'initialization'>
+
+ depth := maxDepth := 0.
+ ]
+
+ depthIncr [
+ <category: 'stack'>
+
+ depth = maxDepth
+ ifTrue: [ depth := depth + 1.
+ maxDepth := maxDepth + 1 ]
+ ifFalse: [ depth := depth + 1 ]
+ ]
+
+ depthDecr [
+ <category: 'stack'>
+
+ depth := depth - 1
+ ]
+
+ depthDecr: n [
+ <category: 'stack'>
+
+ depth := depth - n
+ ]
+
+ depthSet: n [
+ "n can be an integer, or a previously returned value (in which case the
+ exact status at the moment of the previous call is remembered)"
+
+ <category: 'stack'>
+
+ | oldDepth |
+ oldDepth := n -> maxDepth.
+ n isInteger
+ ifTrue: [depth := maxDepth := n]
+ ifFalse:
+ [depth := n key.
+ maxDepth := n value].
+ ^oldDepth
+ ]
+
+ maxDepth [
+ <category: 'stack'>
+
+ ^ maxDepth
+ ]
+]
+
diff --git a/packages/stinst/parser/package.xml b/packages/stinst/parser/package.xml
index 1c9f2c7..de99a3c 100644
--- a/packages/stinst/parser/package.xml
+++ b/packages/stinst/parser/package.xml
@@ -24,6 +24,9 @@
<filein>OldSyntaxExporter.st</filein>
<filein>SqueakExporter.st</filein>
<filein>Extensions.st</filein>
+ <filein>Stack.st</filein>
+ <filein>CompilerBackend.st</filein>
+ <filein>STBackend.st</filein>
<test>
<namespace>STInST.Tests</namespace>
_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk