Skip to content

Commit

Permalink
More parallelism
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Nov 24, 2023
1 parent f7e8852 commit b7fee92
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import de.fraunhofer.aisec.cpg.graph.types.FunctionType
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.graph.types.UnknownType
import de.fraunhofer.aisec.cpg.passes.executePass
import de.fraunhofer.aisec.cpg.passes.executePassesInParallel

fun LanguageFrontend<*, *>.translationResult(
init: TranslationResult.() -> Unit
Expand All @@ -49,7 +50,13 @@ fun LanguageFrontend<*, *>.translationResult(
node.addComponent(component)
init(node)

ctx.config.registeredPasses.flatten().forEach { executePass(it, ctx, node, listOf()) }
if (ctx.config.useParallelPasses) {
for (list in ctx.config.registeredPasses) {
executePassesInParallel(list, ctx, node, listOf())
}
} else {
ctx.config.registeredPasses.flatten().forEach { executePass(it, ctx, node, listOf()) }
}

return node
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.passes.PassTarget
import java.util.*
import org.apache.commons.lang3.builder.ToStringBuilder
import org.neo4j.ogm.annotation.Relationship

/** Represents the declaration or definition of a function. */
open class FunctionDeclaration : ValueDeclaration(), DeclarationHolder, ResolutionStartHolder {
open class FunctionDeclaration :
ValueDeclaration(), DeclarationHolder, ResolutionStartHolder, PassTarget {
/** The function body. Usually a [Block]. */
@AST var body: Statement? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,13 @@ import kotlin.contracts.contract
@OptIn(ExperimentalContracts::class)
@DependsOn(EvaluationOrderGraphPass::class)
@DependsOn(DFGPass::class)
open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUnitPass(ctx) {
open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : FunctionPass(ctx) {

class Configuration(
/**
* This specifies the maximum complexity (as calculated per [Statement.cyclomaticComplexity]
* a [FunctionDeclaration] must have in order to be considered.
* This specifies the maximum complexity (as calculated per
* [Statement.cyclomaticComplexity]) a [FunctionDeclaration] must have in order to be
* considered.
*/
var maxComplexity: Int? = null
) : PassConfiguration()
Expand All @@ -59,65 +60,55 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : TranslationUni
// Nothing to do
}

override fun accept(tu: TranslationUnitDeclaration) {
tu.functions.forEach(::handle)
}

/**
* We perform the actions for each [FunctionDeclaration].
*
* @param node every node in the TranslationResult
*/
protected fun handle(node: Node) {
/** We perform the actions for each [FunctionDeclaration]. */
override fun accept(node: FunctionDeclaration) {
val max = passConfig<Configuration>()?.maxComplexity

if (node is FunctionDeclaration) {
// Skip empty functions
if (node.body == null) {
return
}
// Skip empty functions
if (node.body == null) {
return
}

// Calculate the complexity of the function and see, if it exceeds our threshold
if (max != null) {
val c = node.body?.cyclomaticComplexity ?: 0
if (c > max) {
log.info(
"Ignoring function ${node.name} because its complexity (${c}) is greater than the configured maximum (${max})"
)
return
}
// Calculate the complexity of the function and see, if it exceeds our threshold
if (max != null) {
val c = node.body?.cyclomaticComplexity ?: 0
if (c > max) {
log.info(
"Ignoring function ${node.name} because its complexity (${c}) is greater than the configured maximum (${max})"
)
return
}
}

clearFlowsOfVariableDeclarations(node)
val startState = DFGPassState<Set<Node>>()
clearFlowsOfVariableDeclarations(node)
val startState = DFGPassState<Set<Node>>()

startState.declarationsState.push(node, PowersetLattice(identitySetOf()))
val finalState =
iterateEOG(node.nextEOGEdges, startState, ::transfer) as? DFGPassState ?: return
startState.declarationsState.push(node, PowersetLattice(identitySetOf()))
val finalState =
iterateEOG(node.nextEOGEdges, startState, ::transfer) as? DFGPassState ?: return

removeUnreachableImplicitReturnStatement(
node,
finalState.returnStatements.values.flatMap {
it.elements.filterIsInstance<ReturnStatement>()
}
)
removeUnreachableImplicitReturnStatement(
node,
finalState.returnStatements.values.flatMap {
it.elements.filterIsInstance<ReturnStatement>()
}
)

for ((key, value) in finalState.generalState) {
if (key is TupleDeclaration) {
// We need a little hack for tuple statements to set the index. We have the
// outer part (i.e., the tuple) here, but we generate the DFG edges to the
// elements. We have the indices here, so it's amazing.
key.elements.forEachIndexed { i, element ->
element.addAllPrevDFG(
value.elements.filterNot { it is VariableDeclaration && key == it },
mutableMapOf(Properties.INDEX to i)
)
}
} else {
key.addAllPrevDFG(
value.elements.filterNot { it is VariableDeclaration && key == it }
for ((key, value) in finalState.generalState) {
if (key is TupleDeclaration) {
// We need a little hack for tuple statements to set the index. We have the
// outer part (i.e., the tuple) here, but we generate the DFG edges to the
// elements. We have the indices here, so it's amazing.
key.elements.forEachIndexed { i, element ->
element.addAllPrevDFG(
value.elements.filterNot { it is VariableDeclaration && key == it },
mutableMapOf(Properties.INDEX to i)
)
}
} else {
key.addAllPrevDFG(
value.elements.filterNot { it is VariableDeclaration && key == it }
)
}
}
}
Expand Down
19 changes: 18 additions & 1 deletion cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/Pass.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend
import de.fraunhofer.aisec.cpg.frontends.TranslationException
import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.helpers.Benchmark
import de.fraunhofer.aisec.cpg.passes.order.RequiredFrontend
Expand Down Expand Up @@ -59,9 +60,17 @@ abstract class ComponentPass(ctx: TranslationContext) : Pass<Component>(ctx)
*/
abstract class TranslationUnitPass(ctx: TranslationContext) : Pass<TranslationUnitDeclaration>(ctx)

/**
* A [FunctionPass] is a pass that operates on a [FunctionDeclaration]. If used with [executePass],
* one [Pass] object is instantiated for each [FunctionDeclaration] in each
* [TranslationUnitDeclaration] in each [Component].
*/
abstract class FunctionPass(ctx: TranslationContext) : Pass<FunctionDeclaration>(ctx)

/**
* A pass target is an interface for a [Node] on which a [Pass] can operate, it should only be
* implemented by [TranslationResult], [Component] and [TranslationUnitDeclaration].
* implemented by [TranslationResult], [Component], [TranslationUnitDeclaration] and
* [FunctionDeclaration].
*/
interface PassTarget

Expand Down Expand Up @@ -197,6 +206,14 @@ fun executePass(
result.components.flatMap { it.translationUnits },
executedFrontends
)
is FunctionPass -> {
consumeTargets(
(prototype as FunctionPass)::class,
ctx,
result.components.flatMap { it.translationUnits.flatMap { it.functions } },
executedFrontends
)
}
}

bench.stop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,7 @@ class GraphExamples {
config: TranslationConfiguration =
TranslationConfiguration.builder()
.defaultPasses()
.useParallelPasses(true)
.registerLanguage(TestLanguage("."))
.build()
) =
Expand Down

0 comments on commit b7fee92

Please sign in to comment.