Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dest/
.classpath

# Intellij
.run/**
.idea/**
*.iml
*.iws
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ enum class MacroExprs(val id: String, val value: (ParseContext) -> Expr<*>) {
PTHREAD_MUTEX_ERRORCHECK("PTHREAD_MUTEX_ERRORCHECK", { UnsupportedInitializer() }),
PTHREAD_RWLOCK_INITIALIZER("PTHREAD_RWLOCK_INITIALIZER", { UnsupportedInitializer() }),
NULL("NULL", { CComplexType.getSignedInt(it).nullValue }),
NULLPTR("nullptr", { CComplexType.getSignedInt(it).nullValue }),

// Integer characteristics
CHAR_BIT("CHAR_BIT", { CComplexType.getSignedInt(it).getValue("8") }),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2025 Budapest University of Technology and Economics
* Copyright 2025-2026 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2025 Budapest University of Technology and Economics
* Copyright 2025-2026 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2026 Budapest University of Technology and Economics
* Copyright 2025-2026 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -177,6 +177,13 @@ data class CFrontendConfig(
description = "Architecture (see https://unix.org/whitepapers/64bit.html)",
)
var architecture: ArchitectureConfig.ArchitectureType = ArchitectureConfig.ArchitectureType.LP64,
@Parameter(names = ["--use-cir"], description = "Use ClangIR to preprocess files")
var useCir: Boolean = false,
@Parameter(
names = ["--cir-dir", "--cir-directory"],
description = "Folder with clang and mapper binaries",
)
var cirDir: File = File("./clang/bin"),
) : SpecFrontendConfig

data class CHCFrontendConfig(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2026 Budapest University of Technology and Economics
* Copyright 2025-2026 Budapest University of Technology and Economics
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,11 +15,7 @@
*/
package hu.bme.mit.theta.xcfa.cli.utils

import com.charleskorn.kaml.Yaml
import com.charleskorn.kaml.YamlList
import com.charleskorn.kaml.YamlMap
import com.charleskorn.kaml.YamlNode
import com.charleskorn.kaml.YamlScalar
import com.charleskorn.kaml.*
import hu.bme.mit.theta.btor2.frontend.dsl.gen.Btor2Lexer
import hu.bme.mit.theta.btor2.frontend.dsl.gen.Btor2Parser
import hu.bme.mit.theta.btor2xcfa.Btor2XcfaBuilder
Expand All @@ -40,16 +36,18 @@ import hu.bme.mit.theta.xcfa.cli.params.*
import hu.bme.mit.theta.xcfa.model.*
import hu.bme.mit.theta.xcfa.passes.ChcPasses
import hu.bme.mit.theta.xcfa.passes.ProcedurePassManager
import org.antlr.v4.runtime.BailErrorStrategy
import org.antlr.v4.runtime.CharStreams
import org.antlr.v4.runtime.CommonTokenStream
import java.io.File
import java.io.FileInputStream
import java.io.FileReader
import java.util.concurrent.TimeUnit
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import kotlin.io.path.Path
import kotlin.io.path.createTempDirectory
import kotlin.jvm.optionals.getOrNull
import org.antlr.v4.runtime.BailErrorStrategy
import org.antlr.v4.runtime.CharStreams
import org.antlr.v4.runtime.CommonTokenStream

fun getXcfa(
config: XcfaConfig<*, *>,
Expand All @@ -72,6 +70,7 @@ fun getXcfa(

InputType.C -> {
parseC(
config.frontendConfig.specConfig as CFrontendConfig,
config.inputConfig.input!!,
config.inputConfig.property,
parseContext,
Expand Down Expand Up @@ -161,13 +160,14 @@ private fun CFA.toXcfa(): XCFA {
}

private fun parseC(
frontendConfig: CFrontendConfig,
input: File,
property: XcfaProperty,
parseContext: ParseContext,
logger: Logger,
uniqueWarningLogger: Logger,
): XCFA {
val input =
var input =
if (input.name.endsWith(".yml")) {
try {
val parsedYaml = Yaml.default.parseToYamlNode(input.readText())
Expand Down Expand Up @@ -199,6 +199,38 @@ private fun parseC(
} else {
input
}

input =
if (frontendConfig.useCir) {
val temp = createTempDirectory()
val copied = temp.resolve("input.c").toFile()
var curlyBraceCount = 0
input.readLines().forEach { line ->
line.forEach { c -> if (c == '{') curlyBraceCount++ else if (c == '}') curlyBraceCount-- }
val newLine =
if (curlyBraceCount == 0 && '{' !in line) {
"([^(]*)\\(\\s*\\)".toRegex().replace(line) { it.groups[1]!!.value + "(void)" }
} else {
line
}
copied.appendText(newLine)
copied.appendText(System.lineSeparator())
}
val mlir = temp.resolve("input.mlir").toFile()
val mlirFlat = temp.resolve("flat.mlir").toFile()

"./clang ${copied.absolutePath} -Xclang -emit-cir -fsyntax-only -o ${mlir.absolutePath}"
.runCommand(frontendConfig.cirDir)
"./cir-opt ${mlir.absolutePath} -cir-flatten-cfg -o ${mlirFlat.absolutePath}"
.runCommand(frontendConfig.cirDir)
val transformed = temp.resolve("input-transformed.c").toFile()
"./xcfa-mapper ${mlirFlat.absolutePath} ${transformed.absolutePath}"
.runCommand(frontendConfig.cirDir)
transformed
} else {
input
}

val xcfaFromC =
try {
val stream = FileInputStream(input)
Expand Down Expand Up @@ -282,3 +314,12 @@ private fun parseBTOR2(
logger.write(Logger.Level.VERBOSE, xcfa.toDot())
return xcfa
}

private fun String.runCommand(wd: File) {
ProcessBuilder(*split(" ").toTypedArray())
.directory(wd)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()
.waitFor(15, TimeUnit.MINUTES)
}
Loading