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]! |
Free forum by Nabble | Edit this page |