[Vm-dev] VM Maker: VMMaker.oscog-eem.2779.mcz
commits at source.squeak.org
commits at source.squeak.org
Sat Jul 25 20:02:47 UTC 2020
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2779.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.2779
Author: eem
Time: 25 July 2020, 1:02:37.771342 pm
UUID: 69eafb1b-0a60-46f9-ad35-00f4a863fe8a
Ancestors: VMMaker.oscog-eem.2778
Slang:
Implement and support cppIf:ifTrue:cppIf:ifTrue:ifFalse: for ARMv8 cache flushing. As a result of the changes to generateInlineCppIfElse:asArgument:on:indent: clean-up generating indents and terminating semicolons. In particular don't add a trailing semicolo to a statement list when prepending, leaving it to the sender.
Clean up generating switches, avoiding emitting a bogus newline before hand, and a newline before break jumps.
Change generateV3RemapOopIn:on:indent: to terminate the last statement with a semicolon.
=============== Diff against VMMaker.oscog-eem.2778 ===============
Item was changed:
----- Method: CCodeGenerator>>generateInlineCppIfElse:asArgument:on:indent: (in category 'C translation') -----
generateInlineCppIfElse: msgNode asArgument: asArgument on: aStream indent: level
"Generate the C code for this message onto the given stream."
+ | putStatement allAlternativesWereDeterminable expr pos |
- | expr putStatement |
"Compile-time expansion for constants set in the options dictionary,
e.g. to cut down on noise for MULTIPLEBYTECODESETS."
putStatement := asArgument
ifTrue: "emitCCodeAsArgumentOn: doesn't indent, the code needs indenting if it takes multiple lines, so post-process."
[[:node| | expansion |
expansion := String streamContents: [:s| node emitCCodeAsArgumentOn: s level: level generator: self].
aStream nextPutAll:
((expansion includes: Character cr)
ifTrue:
[(String streamContents:
[:s|
s position > 0 ifTrue: [s tab: level + 1].
node emitCCodeAsArgumentOn: s level: level generator: self])
copyReplaceAll: (String with: Character cr)
with: (String with: Character cr), (String new: level + 1 withAll: Character tab)]
ifFalse: [expansion])]]
ifFalse:
[[:node| | expansion |
expansion := String streamContents: [:s| node emitCCodeOn: s level: level generator: self].
"Remove tabs from first line to avoid indenting a second time"
expansion ifNotEmpty:
[expansion := expansion allButFirst: (expansion findFirst: [:c| c ~~ Character tab]) - 1].
aStream nextPutAll: expansion]].
+ "First attempt to expand statically..."
+ allAlternativesWereDeterminable := true.
+ 1 to: msgNode args size - 1 by: 2 do: "Deal with cppIf:ifTrue:, cppIf:ifTrue:ifFalse:, cppIf:ifTrue:cppIf:ifTrue:ifFalse:, etc"
+ [:conditionIndex|
+ (self nilOrBooleanConditionFor: (msgNode args at: conditionIndex))
+ ifNil: [allAlternativesWereDeterminable := false]
+ ifNotNil:
+ [:condition|
+ condition ifTrue:
+ [putStatement value: (msgNode args at: conditionIndex + 1).
+ ^self]]].
+ allAlternativesWereDeterminable ifTrue:
+ [msgNode args size odd ifTrue: "there is an ifFalse:"
+ [putStatement value: msgNode args last].
- (self nilOrBooleanConditionFor: msgNode args first) ifNotNil:
- [:condition|
- condition
- ifTrue:
- [putStatement value: msgNode args second]
- ifFalse:
- [msgNode args size >= 3 ifTrue:
- [putStatement value: msgNode args third]].
^self].
+ "Expand for compile-time evaluation. Full #if ... #else..."
- "Full #if ... #else..."
putStatement := asArgument
ifTrue: "emitCCodeAsArgumentOn: doesn't indent, the code needs indenting in this case, so post-process."
[[:node|
aStream nextPutAll:
((String streamContents:
[:s|
s next: level + 1 put: Character tab.
node emitCCodeAsArgumentOn: s level: level generator: self])
copyReplaceAll: (String with: Character cr)
with: (String with: Character cr), (String new: level + 1 withAll: Character tab))]]
ifFalse:
[[:node| node emitCCodeOn: aStream level: level generator: self]].
+ 1 to: msgNode args size - 1 by: 2 do: "Deal with cppIf:ifTrue:, cppIf:ifTrue:ifFalse:, cppIf:ifTrue:cppIf:ifTrue:ifFalse:, etc"
+ [:conditionIndex| | condition |
+ condition := String streamContents:
+ [:es|
+ (msgNode args at: conditionIndex)
+ emitCCodeAsArgumentOn: es
+ level: 0
+ generator: self].
+ [condition last isSeparator] whileTrue:
+ [condition := condition allButLast].
+ aStream
+ ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: (conditionIndex = 1 ifTrue: ['if '] ifFalse: ['elif ']); nextPutAll: condition; cr.
- expr := String streamContents:
- [:es|
- msgNode args first
- emitCCodeAsArgumentOn: es
- level: 0
- generator: self].
- [expr last isSeparator] whileTrue:
- [expr := expr allButLast].
- aStream
- ensureCr;
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'if '; nextPutAll: expr; cr.
+ pos := aStream position.
+ self with: (msgNode args at: conditionIndex)
+ ifAppropriateSetTo: true
+ do: [putStatement value: (msgNode args at: conditionIndex + 1)].
+ expr := (expr ifNil: [' /* '] ifNotNil: [expr, ' || ']), condition].
+ expr := expr, ' */'.
+ msgNode args size odd ifTrue: "there is an ifFalse:"
- self with: msgNode args first
- ifAppropriateSetTo: true
- do: [putStatement value: msgNode args second].
- expr := ' /* ', expr, ' */'.
- msgNode args size >= 3 ifTrue:
[aStream
ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'else'.
+ aStream position - pos >= 128 ifTrue:
+ [aStream nextPutAll: expr].
+ aStream cr.
+ pos := aStream position.
+ msgNode args size <= 3
+ ifTrue: "ifTrue:ifFalse:, so negate condition for ifFalse:"
+ [self with: msgNode args last
+ ifAppropriateSetTo: false
+ do: [putStatement value: msgNode args third]]
+ ifFalse:
+ [putStatement value: msgNode args last]].
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'else'; nextPutAll: expr;
- cr.
- self with: msgNode args first
- ifAppropriateSetTo: false
- do: [putStatement value: msgNode args third]].
aStream
ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'endif'.
+ aStream position - pos >= 128 ifTrue:
+ [aStream nextPutAll: expr].
+ aStream cr.
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'endif'; nextPutAll: expr;
- cr.
asArgument ifTrue:
[aStream next: level + 1 put: Character tab]!
Item was changed:
----- Method: CCodeGenerator>>generateToByDo:on:indent: (in category 'C translation') -----
generateToByDo: msgNode on: aStream indent: level
"Generate the C code for this message onto the given stream."
"N.B. MessageNode>>asTranslatorNodeIn: adds the limit var as a hidden fourth argument."
| blockExpr iterationVar limitExpr mayHaveSideEffects limitVar step |
blockExpr := msgNode args third.
blockExpr args size = 1 ifFalse:
[self error: 'wrong number of block arguments'].
iterationVar := blockExpr args first.
limitExpr := msgNode args first.
aStream nextPutAll: 'for (', iterationVar, ' = '.
self noteUsedVariableName: iterationVar.
self emitCExpression: msgNode receiver on: aStream.
mayHaveSideEffects := msgNode args size = 4. "See TMethod>>prepareMethodIn:"
mayHaveSideEffects ifTrue:
[limitVar := msgNode args last.
aStream nextPutAll: ', ', limitVar name, ' = '.
self emitCExpression: limitExpr on: aStream.
limitExpr := limitVar].
aStream nextPutAll: '; ', iterationVar.
step := msgNode args at: 2.
self generateToByDoLimitExpression: limitExpr
negative: (self stepExpressionIsNegative: step)
on: aStream.
aStream nextPutAll: '; ', iterationVar, ' += '.
self emitCExpression: step on: aStream.
aStream nextPutAll: ') {'; cr.
blockExpr emitCCodeOn: aStream level: level + 1 generator: self.
+ aStream tab: level; nextPut: $}!
- aStream tab: level.
- aStream nextPut: $}!
Item was changed:
----- Method: CCodeGenerator>>generateToDo:on:indent: (in category 'C translation') -----
generateToDo: msgNode on: aStream indent: level
"Generate the C code for this message onto the given stream."
| iterationVar |
(msgNode args last args size = 1) ifFalse: [
self error: 'wrong number of block arguments'.
].
iterationVar := msgNode args last args first.
aStream nextPutAll: 'for (', iterationVar, ' = '.
self emitCExpression: msgNode receiver on: aStream.
aStream nextPutAll: '; ', iterationVar.
self generateToByDoLimitExpression: msgNode args first negative: false on: aStream.
aStream nextPutAll: '; ', iterationVar, '++) {'; cr.
msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
+ aStream tab: level; nextPut: $}!
- level timesRepeat: [ aStream tab ].
- aStream nextPutAll: '}'.!
Item was changed:
----- Method: CCodeGenerator>>initializeCTranslationDictionary (in category 'C translation support') -----
initializeCTranslationDictionary
"Initialize the dictionary mapping message names to actions for C code generation."
| pairs |
translationDict := Dictionary new: 200.
pairs := #(
#& #generateAnd:on:indent:
#| #generateOr:on:indent:
#abs #generateAbs:on:indent:
#and: #generateSequentialAnd:on:indent:
#or: #generateSequentialOr:on:indent:
#not #generateNot:on:indent:
#+ #generatePlus:on:indent:
#- #generateMinus:on:indent:
#negated #generateNegated:on:indent:
#* #generateTimes:on:indent:
#/ #generateDivide:on:indent:
#// #generateDivide:on:indent:
#\\ #generateModulo:on:indent:
#<< #generateShiftLeft:on:indent:
#>> #generateShiftRight:on:indent:
#>>> #generateSignedShiftRight:on:indent:
#, #generateComma:on:indent:
#min: #generateMin:on:indent:
#max: #generateMax:on:indent:
#between:and: #generateBetweenAnd:on:indent:
#bitAnd: #generateBitAnd:on:indent:
#bitOr: #generateBitOr:on:indent:
#bitXor: #generateBitXor:on:indent:
#bitShift: #generateBitShift:on:indent:
#signedBitShift: #generateSignedBitShift:on:indent:
#bitInvert32 #generateBitInvert:on:indent:
#bitInvert64 #generateBitInvert:on:indent:
#bitClear: #generateBitClear:on:indent:
#truncateTo: #generateTruncateTo:on:indent:
#rounded #generateRounded:on:indent:
#even #generateEven:on:indent:
#odd #generateOdd:on:indent:
#byteSwap32 #generateByteSwap32:on:indent:
#byteSwap64 #generateByteSwap64:on:indent:
#byteSwapped32IfBigEndian: generateByteSwap32IfBigEndian:on:indent:
#byteSwapped64IfBigEndian: generateByteSwap64IfBigEndian:on:indent:
#< #generateLessThan:on:indent:
#<= #generateLessThanOrEqual:on:indent:
#= #generateEqual:on:indent:
#> #generateGreaterThan:on:indent:
#>= #generateGreaterThanOrEqual:on:indent:
#~= #generateNotEqual:on:indent:
#== #generateEqual:on:indent:
#~~ #generateNotEqual:on:indent:
#isNil #generateIsNil:on:indent:
#notNil #generateNotNil:on:indent:
#whileTrue: #generateWhileTrue:on:indent:
#whileFalse: #generateWhileFalse:on:indent:
#whileTrue #generateDoWhileTrue:on:indent:
#whileFalse #generateDoWhileFalse:on:indent:
#to:do: #generateToDo:on:indent:
#to:by:do: #generateToByDo:on:indent:
#repeat #generateRepeat:on:indent:
#timesRepeat: #generateTimesRepeat:on:indent:
#ifTrue: #generateIfTrue:on:indent:
#ifFalse: #generateIfFalse:on:indent:
#ifTrue:ifFalse: #generateIfTrueIfFalse:on:indent:
#ifFalse:ifTrue: #generateIfFalseIfTrue:on:indent:
#ifNotNil: #generateIfNotNil:on:indent:
#ifNil: #generateIfNil:on:indent:
#ifNotNil:ifNil: #generateIfNotNilIfNil:on:indent:
#ifNil:ifNotNil: #generateIfNilIfNotNil:on:indent:
+ #at: #generateAt:on:indent:
+ #at:put: #generateAtPut:on:indent:
- #at: #generateAt:on:indent:
- #at:put: #generateAtPut:on:indent:
#basicAt: #generateAt:on:indent:
#basicAt:put: #generateAtPut:on:indent:
#integerValueOf: #generateIntegerValueOf:on:indent:
#integerObjectOf: #generateIntegerObjectOf:on:indent:
#isIntegerObject: #generateIsIntegerObject:on:indent:
#cCode: #generateInlineCCode:on:indent:
+ #cCode:inSmalltalk: #generateInlineCCode:on:indent:
- #cCode:inSmalltalk: #generateInlineCCode:on:indent:
#cPreprocessorDirective: #generateInlineCPreprocessorDirective:on:indent:
+ #cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
+ #cppIf:ifTrue:cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
+ #cppIf:ifTrue: #generateInlineCppIfElse:on:indent:
- #cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
- #cppIf:ifTrue: #generateInlineCppIfElse:on:indent:
#cCoerce:to: #generateCCoercion:on:indent:
#cCoerceSimple:to: #generateCCoercion:on:indent:
#addressOf: #generateAddressOf:on:indent:
#addressOf:put: #generateAddressOf:on:indent:
#asAddress:put: #generateAsAddress:on:indent:
+ #signedIntFromLong64 #generateSignedIntFromLong64:on:indent:
- #signedIntFromLong64 #generateSignedIntFromLong64:on:indent:
#signedIntFromLong #generateSignedIntFromLong:on:indent:
#signedIntFromShort #generateSignedIntFromShort:on:indent:
#signedIntToLong64 #generateSignedIntToLong64:on:indent:
#signedIntToLong #generateSignedIntToLong:on:indent:
#signedIntToShort #generateSignedIntToShort:on:indent:
#preIncrement #generatePreIncrement:on:indent:
#preDecrement #generatePreDecrement:on:indent:
#inline: #generateInlineDirective:on:indent:
#asFloat #generateAsFloat:on:indent:
#asInteger #generateAsInteger:on:indent:
#asIntegerPtr #generateAsIntegerPtr:on:indent:
#asUnsignedInteger #generateAsUnsignedInteger:on:indent:
#asUnsignedIntegerPtr #generateAsUnsignedIntegerPtr:on:indent:
#asLong #generateAsLong:on:indent:
#asUnsignedLong #generateAsUnsignedLong:on:indent:
#asUnsignedLongLong #generateAsUnsignedLongLong:on:indent:
#asVoidPointer #generateAsVoidPointer:on:indent:
#asSymbol #generateAsSymbol:on:indent:
#flag: #generateFlag:on:indent:
#anyMask: #generateBitAnd:on:indent:
#allMask: #generateAllMask:on:indent:
#noMask: #generateNoMask:on:indent:
#raisedTo: #generateRaisedTo:on:indent:
+ #touch: #generateTouch:on:indent:
- #touch: #generateTouch:on:indent:
#bytesPerOop #generateBytesPerOop:on:indent:
#bytesPerWord #generateBytesPerWord:on:indent:
#wordSize #generateBytesPerWord:on:indent:
#baseHeaderSize #generateBaseHeaderSize:on:indent:
#minSmallInteger #generateSmallIntegerConstant:on:indent:
#maxSmallInteger #generateSmallIntegerConstant:on:indent:
#sharedCodeNamed:inCase: #generateSharedCodeDirective:on:indent:
#perform: #generatePerform:on:indent:
#perform:with: #generatePerform:on:indent:
+ #perform:with:with: #generatePerform:on:indent:
+ #perform:with:with:with: #generatePerform:on:indent:
- #perform:with:with: #generatePerform:on:indent:
- #perform:with:with:with: #generatePerform:on:indent:
#perform:with:with:with:with: #generatePerform:on:indent:
#perform:with:with:with:with:with: #generatePerform:on:indent:
+ #value #generateValue:on:indent:
+ #value: #generateValue:on:indent:
+ #value:value: #generateValue:on:indent:
+ #value:value:value: #generateValue:on:indent:
+ #value:value:value:value: #generateValue:on:indent:
- #value #generateValue:on:indent:
- #value: #generateValue:on:indent:
- #value:value: #generateValue:on:indent:
- #value:value:value: #generateValue:on:indent:
- #value:value:value:value: #generateValue:on:indent:
#value:value:value:value:value: #generateValue:on:indent:
#value:value:value:value:value:value: #generateValue:on:indent:
#deny: #generateDeny:on:indent:
#shouldNotImplement #generateSmalltalkMetaError:on:indent:
#shouldBeImplemented #generateSmalltalkMetaError:on:indent:
+ #subclassResponsibility #generateSmalltalkMetaError:on:indent:
- #subclassResponsibility #generateSmalltalkMetaError:on:indent:
).
1 to: pairs size by: 2 do: [:i |
translationDict at: (pairs at: i) put: (pairs at: i + 1)].
pairs := #(
+ #ifTrue: #generateIfTrueAsArgument:on:indent:
- #ifTrue: #generateIfTrueAsArgument:on:indent:
#ifFalse: #generateIfFalseAsArgument:on:indent:
#ifTrue:ifFalse: #generateIfTrueIfFalseAsArgument:on:indent:
#ifFalse:ifTrue: #generateIfFalseIfTrueAsArgument:on:indent:
#ifNotNil: #generateIfNotNilAsArgument:on:indent:
#ifNil: #generateIfNilAsArgument:on:indent:
#ifNotNil:ifNil: #generateIfNotNilIfNilAsArgument:on:indent:
#ifNil:ifNotNil: #generateIfNilIfNotNilAsArgument:on:indent:
#cCode: #generateInlineCCodeAsArgument:on:indent:
+ #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent:
- #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent:
#cppIf:ifTrue:ifFalse: #generateInlineCppIfElseAsArgument:on:indent:
#cppIf:ifTrue: #generateInlineCppIfElseAsArgument:on:indent:
#value #generateValueAsArgument:on:indent:
#value: #generateValueAsArgument:on:indent:
#value:value: #generateValueAsArgument:on:indent:
).
asArgumentTranslationDict := Dictionary new: 8.
1 to: pairs size by: 2 do: [:i |
asArgumentTranslationDict at: (pairs at: i) put: (pairs at: i + 1)].
!
Item was changed:
----- Method: TCaseStmtNode>>emitCCodeOn:addToEndOfCases:level:generator: (in category 'C code generation') -----
emitCCodeOn: aStream addToEndOfCases: aNodeOrNil level: level generator: aCodeGen
| indent |
indent := String new: level withAll: Character tab.
- aStream crtab: level.
aStream nextPutAll: 'switch ('.
expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
aStream nextPutAll: ') {'; cr.
cases withIndexDo:
[:case :i|
(firsts at: i) to: (lasts at: i) do:
[ :caseIndex |
aStream nextPutAll: indent; nextPutAll: 'case '; print: caseIndex; nextPut: $:; cr].
case emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen.
(aNodeOrNil notNil and: [aNodeOrNil isReturn]) ifFalse:
[aStream crtab: level + 1; nextPutAll: 'break;']].
aStream
crtab: level;
nextPutAll: 'default:';
crtab: level + 1;
nextPutAll: 'error("Case not found");'.
aNodeOrNil ifNotNil:
[aStream crtab: level + 1.
(aNodeOrNil copy setExpression: (TConstantNode new setValue: -1))
emitCCodeOn: aStream level: level generator: aCodeGen.
aStream nextPut: $;].
aStream
crtab: level;
nextPut: $}!
Item was changed:
----- Method: TMethod>>statementsListsForInliningIn: (in category 'inlining') -----
statementsListsForInliningIn: aCodeGen
"Answer a collection of statement list nodes that are candidates for inlining.
Currently, we cannot inline into the argument blocks of and: and or: messages.
We do not want to inline code strings within cCode:inSmalltalk: blocks (those with a
proper block for the cCode: argument are inlined in MessageNode>>asTranslatorNodeIn:).
We do not want to inline code within assert: sends (because we want the assert to read nicely)."
| stmtLists |
stmtLists := OrderedCollection new: 10.
parseTree
nodesDo:
[:node|
node isStmtList ifTrue: [stmtLists add: node]]
unless:
[:node|
node isSend
and: [node selector == #cCode:inSmalltalk:
or: [aCodeGen isAssertSelector: node selector]]].
parseTree nodesDo:
[:node|
node isSend ifTrue:
[node selector = #cCode:inSmalltalk: ifTrue:
[node nodesDo:
[:ccisNode| stmtLists remove: ccisNode ifAbsent: []]].
+ (node selector beginsWith: #cppIf:ifTrue:) ifTrue:
- (node selector = #cppIf:ifTrue:ifFalse: or: [node selector = #cppIf:ifTrue:]) ifTrue:
[node args first nodesDo:
[:inCondNode| stmtLists remove: inCondNode ifAbsent: []]].
((node selector = #and:) or: [node selector = #or:]) ifTrue:
"Note: the PP 2.3 compiler produces two arg nodes for these selectors"
[stmtLists remove: node args first ifAbsent: [].
stmtLists remove: node args last ifAbsent: []].
(#( #ifTrue: #ifFalse: #ifTrue:ifFalse: #ifFalse:ifTrue:
#ifNil: #ifNotNil: #ifNil:ifNotNil: #ifNotNil:ifNil: ) includes: node selector) ifTrue:
[stmtLists remove: node receiver ifAbsent: []].
(#(whileTrue whileTrue: whilefalse whileFalse:) includes: node selector) ifTrue:
"Allow inlining if it is a [...] whileTrue/whileFalse.
This is identified by having more than one statement in the
receiver block in which case the C code wouldn't work anyways"
[node receiver statements size = 1 ifTrue:
[stmtLists remove: node receiver ifAbsent: []]].
(node selector = #to:do:) ifTrue:
[stmtLists remove: node receiver ifAbsent: [].
stmtLists remove: node args first ifAbsent: []].
(node selector = #to:by:do:) ifTrue:
[stmtLists remove: node receiver ifAbsent: [].
stmtLists remove: node args first ifAbsent: [].
stmtLists remove: node args second ifAbsent: []]].
node isCaseStmt ifTrue: "don't inline cases"
[node cases do: [:case| stmtLists remove: case ifAbsent: []]]].
^stmtLists!
Item was changed:
----- Method: TSendNode>>isPreprocessorDirective (in category 'testing') -----
isPreprocessorDirective
+ ^#(cPreprocessorDirective: cppIf:ifTrue: cppIf:ifTrue:ifFalse: cppIf:ifTrue:cppIf:ifTrue:ifFalse:) includes: selector!
- ^#(cPreprocessorDirective: cppIf:ifTrue:ifFalse: cppIf:ifTrue:) includes: selector!
Item was changed:
----- Method: TSendNode>>needsTrailingSemicolon (in category 'testing') -----
needsTrailingSemicolon
"Answer if, when emitted as a statement (in particular in a TStmtList), the
receiver needs a trailing semicolon. Preprocessor directives and special expansions do not."
^(self isPreprocessorDirective
or: [self isValueExpansion
+ or: [self isConditionalSend
+ or: [selector == #expandDereferenceInterpreterProxyFunctionTable]]]) not!
- or: [selector == #expandDereferenceInterpreterProxyFunctionTable]]) not!
Item was changed:
----- Method: TStmtListNode>>emitCCodeOn:prependToEnd:level:generator: (in category 'C code generation') -----
emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen
| statementToElide |
self emitCCommentOn: aStream level: level generator: aCodeGen.
(aNodeOrNil notNil or: [statements isEmpty or: [statements last hasEffect]]) ifFalse:
[statementToElide := statements last].
statements withIndexDo:
+ [:s :idx| | position lastWhilePrepending |
- [:s :idx| | position |
s emitCCommentOn: aStream level: level generator: aCodeGen.
(s == statementToElide
or: [s isLeaf and: [s isLabel not and: [aNodeOrNil isNil or: [idx < statements size]]]]) ifFalse:
+ [((s isSend and: [s isPreprocessorDirective]) or: [aStream peekLast == Character tab]) ifFalse:
- [aStream peekLast ~~ Character tab ifTrue:
[aStream tab: level].
position := aStream position.
+ (lastWhilePrepending := aNodeOrNil notNil and: [idx = statements size])
+ ifTrue: [s emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen]
+ ifFalse: [s emitCCodeOn: aStream level: level generator: aCodeGen].
- (aNodeOrNil notNil
- and: [idx = statements size])
- ifTrue:
- [s emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen]
- ifFalse:
- [s emitCCodeOn: aStream level: level generator: aCodeGen].
aStream position > position ifTrue:
[(self stream: aStream endsWithAnyOf: '};') ifFalse:
[s needsTrailingSemicolon ifTrue:
[aStream nextPut: $;]].
+ (lastWhilePrepending or: [aStream peekLast == Character cr]) ifFalse:
- aStream peekLast ~~ Character cr ifTrue:
[aStream cr]]]]!
Item was changed:
----- Method: TSwitchStmtNode>>emitCCodeOn:addToEndOfCases:level:generator: (in category 'C code generation') -----
emitCCodeOn: aStream addToEndOfCases: aNodeOrNil level: level generator: aCodeGen
- aStream crtab: level.
aStream nextPutAll: 'switch ('.
expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
aStream nextPutAll: ') {'.
cases do:
[:tuple|
[:labels :case|
labels do:
[:label|
aStream
crtab: level;
nextPutAll: 'case '.
label emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen.
aStream nextPut: $:].
aStream crtab: level + 1.
case emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen]
valueWithArguments: tuple.
+ (aNodeOrNil notNil and: [aNodeOrNil isReturn])
+ ifTrue: [(self stream: aStream endsWithAnyOf: ';}') ifFalse: [aStream nextPut: $;]]
+ ifFalse: [aStream crtab: level + 1; nextPutAll: 'break;'].
+ aStream cr].
- (aNodeOrNil notNil and: [aNodeOrNil isReturn]) ifFalse:
- [aStream crtab: level + 1; nextPutAll: 'break;']].
aStream
crtab: level;
nextPutAll: 'default:';
crtab: level + 1.
otherwiseOrNil
ifNotNil: [otherwiseOrNil emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen]
+ ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause")'.
- ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause");'.
aNodeOrNil ifNotNil:
[| defaultExpr type |
+ aStream nextPut: $;; crtab: level + 1.
- aStream crtab: level + 1.
defaultExpr := TConstantNode new setValue: -1.
(aNodeOrNil isAssignment
and: [(type := aCodeGen typeFor: aNodeOrNil variable in: aCodeGen currentMethod) notNil
and: [aCodeGen isPointerCType: type]]) ifTrue:
[defaultExpr := TSendNode new
setSelector: #cCoerceSimple:to:
receiver: (TVariableNode new setName: 'self')
arguments: {defaultExpr. TConstantNode new setValue: type}].
(aNodeOrNil copy setExpression: defaultExpr)
+ emitCCodeOn: aStream level: level generator: aCodeGen]].
- emitCCodeOn: aStream level: level generator: aCodeGen.
- aStream nextPut: $;]].
aStream
+ nextPut: $;;
crtab: level;
nextPut: $}!
Item was changed:
----- Method: TSwitchStmtNode>>emitCCodeOn:level:generator: (in category 'C code generation') -----
emitCCodeOn: aStream level: level generator: aCodeGen
- aStream crtab: level.
aStream nextPutAll: 'switch ('.
expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
aStream nextPutAll: ') {'.
cases do:
[:tuple|
[:labels :case|
labels do:
[:label|
aStream
crtab: level;
nextPutAll: 'case '.
label emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen.
aStream nextPut: $:].
aStream crtab: level + 1.
case emitCCodeOn: aStream level: level + 1 generator: aCodeGen.
case endsWithReturn ifFalse:
[aStream tab: level + 1; nextPutAll: 'break;']]
valueWithArguments: tuple].
aStream
crtab: level;
nextPutAll: 'default:';
crtab: level + 1.
otherwiseOrNil
ifNotNil:
[otherwiseOrNil emitCCodeOn: aStream level: level + 1 generator: aCodeGen.
(self stream: aStream endsWithAnyOf: '};') ifFalse:
[aStream nextPut: $;]]
ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause");'].
aStream
crtab: level;
nextPut: $}!
Item was changed:
----- Method: TSwitchStmtNode>>printOn:level: (in category 'printing') -----
printOn: aStream level: level
- aStream crtab: level.
aStream nextPutAll: 'switch ('.
expression printOn: aStream level: level.
aStream nextPutAll: ') {'.
cases do:
[:tuple|
[:labels :case|
labels do:
[:label|
aStream
crtab: level;
nextPutAll: 'case '.
label printOn: aStream level: level + 1.
aStream nextPut: $:].
aStream crtab: level + 1.
case printOn: aStream level: level + 1.
aStream crtab: level + 1; nextPutAll: 'break;']
valueWithArguments: tuple].
otherwiseOrNil ifNotNil:
[aStream
crtab: level;
nextPutAll: 'default:';
crtab: level + 1.
otherwiseOrNil printOn: aStream level: level + 1].
aStream
crtab: level;
nextPut: $}!
Item was added:
+ ----- Method: VMClass>>cppIf:ifTrue:cppIf:ifTrue:ifFalse: (in category 'translation support') -----
+ cppIf: firstCondition ifTrue: firstExpression cppIf: secondCondition ifTrue: secondExpression ifFalse: falseExpression
+ <doNotGenerate>
+ ^self cppIf: firstCondition
+ ifTrue: firstExpression
+ ifFalse:
+ [self cppIf: secondCondition ifTrue: secondExpression ifFalse: falseExpression]!
Item was changed:
----- Method: VMPluginCodeGenerator>>generateV3RemapOopIn:on:indent: (in category 'C translation') -----
generateV3RemapOopIn: aNode on: aStream indent: level
"Generate call on remapOop: for the variable oopOrList (or all of the
variables in oopOrList) before evaluating aBlock, and restore them after.
This keeps the oops valid if, as V3 will, there is a GC on allocation."
| idList |
pluginFunctionsUsed add: #pushRemappableOop:; add: #popRemappableOop.
idList := aNode args first nameOrValue.
idList class == Array ifFalse: [idList := Array with: idList].
idList do:
[:each |
aStream
tab: level;
nextPutAll: 'pushRemappableOop(';
nextPutAll: each asString;
nextPutAll: ');']
separatedBy: [aStream cr].
aStream cr.
aNode args second emitCCodeOn: aStream level: level generator: self.
level timesRepeat: [aStream tab].
idList reversed do:
[:each |
+ aStream
+ tab: level;
- aStream
nextPutAll: each asString;
+ nextPutAll: ' = popRemappableOop();']
+ separatedBy: [aStream cr]!
- nextPutAll: ' = popRemappableOop()']
- separatedBy: [aStream nextPut: $;; crtab: level]!
More information about the Vm-dev
mailing list