Skip to content

Commit

Permalink
New Go frontend
Browse files Browse the repository at this point in the history
This PR contains a complete re-write of the Go language frontend based on JNA instead of a pure Go implementation. While this has a slight performance drawback (I am working on providing some numbers), it has infinitly better debugging capabilities. The handlers and most of the frontend itself is written in Kotlin using our classes and we than use a JNA bridge to a C API wrapper around the Go `go/ast` package.
  • Loading branch information
oxisto committed Jul 26, 2023
1 parent 5b1aa00 commit caae051
Show file tree
Hide file tree
Showing 38 changed files with 3,630 additions and 3,609 deletions.
8 changes: 1 addition & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,10 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of SonarQube analysis
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: 1.18
- uses: actions/setup-java@v3
with:
distribution: "zulu"
java-version: "17"
go-version: "1.20"
- name: Build
run: |
cd cpg-language-go/src/main/golang
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ class DeclarationSequence : Declaration(), DeclarationHolder {
for (declarationChild in declaration.children) {
addIfNotContains(childEdges, declarationChild)
}
} else {
addIfNotContains(childEdges, declaration)
}
addIfNotContains(childEdges, declaration)
}

fun asList(): List<Declaration> {
Expand All @@ -62,6 +63,10 @@ class DeclarationSequence : Declaration(), DeclarationHolder {
return childEdges[0].end
}

operator fun plusAssign(declaration: Declaration) {
return addDeclaration(declaration)
}

override val declarations: List<Declaration>
get() = children
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import de.fraunhofer.aisec.cpg.helpers.Util
import de.fraunhofer.aisec.cpg.passes.order.DependsOn
import de.fraunhofer.aisec.cpg.passes.order.ReplacePass
import java.util.*
import org.slf4j.LoggerFactory

Expand Down Expand Up @@ -290,7 +291,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
pushToEOG(node)
}

protected fun handleFunctionDeclaration(node: FunctionDeclaration) {
protected open fun handleFunctionDeclaration(node: FunctionDeclaration) {
// reset EOG
currentPredecessors.clear()
var needToLeaveRecord = false
Expand Down Expand Up @@ -525,25 +526,43 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
}

protected fun handleUnaryOperator(node: UnaryOperator) {
// TODO(oxisto): These operator codes are highly language specific and might be more suited
// to be handled differently (see https://github.com/Fraunhofer-AISEC/cpg/issues/1161)
if (node.operatorCode == "throw") {
handleThrowOperator(node)
} else {
handleUnspecificUnaryOperator(node)
}
}

protected fun handleThrowOperator(node: UnaryOperator) {
val input = node.input
createEOG(input)
if (node.operatorCode == "throw") {
val catchingScope =
scopeManager.firstScopeOrNull { scope ->
scope is TryScope || scope is FunctionScope
}

val throwType = input.type
pushToEOG(node)
if (catchingScope is TryScope) {
catchingScope.catchesOrRelays[throwType] = ArrayList(currentPredecessors)
} else if (catchingScope is FunctionScope) {
catchingScope.catchesOrRelays[throwType] = ArrayList(currentPredecessors)
}
currentPredecessors.clear()
} else {
pushToEOG(node)
val catchingScope =
scopeManager.firstScopeOrNull { scope -> scope is TryScope || scope is FunctionScope }

val throwType = input.type
pushToEOG(node)
if (catchingScope is TryScope) {
catchingScope.catchesOrRelays[throwType] = ArrayList(currentPredecessors)
} else if (catchingScope is FunctionScope) {
catchingScope.catchesOrRelays[throwType] = ArrayList(currentPredecessors)
}
currentPredecessors.clear()
}

/**
* This function handles all regular unary operators that do not receive any special handling
* (such as [handleThrowOperator]). This gives language frontends a chance to override this
* function using [ReplacePass], handle specific operators on their own and delegate the rest to
* this function.
*/
protected open fun handleUnspecificUnaryOperator(node: UnaryOperator) {
val input = node.input
createEOG(input)

pushToEOG(node)
}

protected fun handleCompoundStatementExpression(node: CompoundStatementExpression) {
Expand Down
4 changes: 4 additions & 0 deletions cpg-language-go/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ publishing {
}
}

dependencies {
implementation("net.java.dev.jna:jna:5.13.0")
}

if (!project.hasProperty("skipGoBuild")) {
val compileGolang = tasks.register("compileGolang") {
doLast {
Expand Down
86 changes: 0 additions & 86 deletions cpg-language-go/src/main/golang/basic_types.go

This file was deleted.

9 changes: 1 addition & 8 deletions cpg-language-go/src/main/golang/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,9 @@ else
EXTENSION="so"
fi

if [ "$JAVA_HOME" == "" ]
then
JAVA_HOME=`/usr/libexec/java_home`
fi

export CGO_CFLAGS="-I${JAVA_HOME}/include -I/${JAVA_HOME}/include/${ARCH}"

CGO_ENABLED=1 GOARCH=amd64 go build -buildmode=c-shared -o ../resources/libcpgo-amd64.${EXTENSION} lib/cpg/main.go

if [ $ARCH == "darwin" ]
then
CGO_ENABLED=1 GOARCH=arm64 go build -buildmode=c-shared -o ../resources/libcpgo-arm64.${EXTENSION} lib/cpg/main.go
CGO_ENABLED=1 GOARCH=arm64 go build -buildmode=c-shared -o ../resources/libcpgo-arm64.${EXTENSION} lib/cpg/main.go
fi
Loading

0 comments on commit caae051

Please sign in to comment.