Skip to content

Commit

Permalink
Move all logic regarding built-in pattern options away from SimpLL
Browse files Browse the repository at this point in the history
  • Loading branch information
zacikpa committed Aug 8, 2023
1 parent d651b9d commit 1471848
Show file tree
Hide file tree
Showing 17 changed files with 313 additions and 383 deletions.
4 changes: 2 additions & 2 deletions diffkemp/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,12 @@ def make_argument_parser():
compare_ap.add_argument("--enable-pattern",
action="append", default=[],
choices=BUILTIN_PATTERNS,
help="choose which built-in patterns should be"
help="choose which built-in patterns should be "
"explicitly enabled")
compare_ap.add_argument("--disable-pattern",
action="append", default=[],
choices=BUILTIN_PATTERNS,
help="choose which built-in patterns should be"
help="choose which built-in patterns should be "
"explicitly disabled")
compare_ap.add_argument("--enable-all-patterns", action="append_const",
dest="enable_pattern", const="all",
Expand Down
157 changes: 149 additions & 8 deletions diffkemp/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,154 @@
"""Configuration of the tool."""
from diffkemp.semdiff.custom_pattern_config import CustomPatternConfig
from diffkemp.snapshot import Snapshot
from diffkemp.simpll.simpll_lib import ffi
import os


class ConfigException(Exception):
pass


class BuiltinPatterns:
def __init__(
self,
struct_alignment=True,
function_splits=True,
unused_return_types=True,
kernel_prints=True,
dead_code=True,
numerical_macros=True,
relocations=True,
type_casts=False,
control_flow_only=False,
inverse_conditions=True,
):
"""
Create a configuration of built-in patterns.
:param struct_alignment: Changes in structure alignment.
:param function_splits: Splitting code into functions.
:param unused_return_types: Changing unused return values to void.
:param kernel_prints: Changes in kernel-specific printing functions:
- changes in strings printed by kernel print functions
- changes in arguments of kernel functions that are related to the
call location (file name and line number)
- changes in counter, date, time, file name, and line macros
:param dead_code: Changes in dead code.
:param numerical_macros: Changed numerical value of a macro.
:param relocations: Relocated instructions.
:param type_casts: Changes in type casts.
:param control_flow_only: Consider control-flow changes only.
:param inverse_conditions: Inverted branch conditions.
"""
self.struct_alignment = struct_alignment
self.function_splits = function_splits
self.unused_return_types = unused_return_types
self.kernel_prints = kernel_prints
self.dead_code = dead_code
self.numerical_macros = numerical_macros
self.relocations = relocations
self.type_casts = type_casts
self.control_flow_only = control_flow_only
self.inverse_conditions = inverse_conditions
self.resolve_dependencies()

def update_from_args(self, args):
"""
Update the configuration based on Diffkemp command line arguments.
:param args: Diffkemp command line arguments.
"""
if "all" in args.enable_pattern:
self.struct_alignment = True
self.function_splits = True
self.unused_return_types = True
self.kernel_prints = True
self.dead_code = True
self.numerical_macros = True
self.relocations = True
self.type_casts = True
self.control_flow_only = True
self.inverse_conditions = True

if "all" in args.disable_pattern:
self.struct_alignment = False
self.function_splits = False
self.unused_return_types = False
self.kernel_prints = False
self.dead_code = False
self.numerical_macros = False
self.relocations = False
self.type_casts = False
self.control_flow_only = False
self.inverse_conditions = False

if "struct-alignment" in args.enable_pattern:
self.struct_alignment = True
if "struct-alignment" in args.disable_pattern:
self.struct_alignment = False
if "function-splits" in args.enable_pattern:
self.function_splits = True
if "function-splits" in args.disable_pattern:
self.function_splits = False
if "unused-return-types" in args.enable_pattern:
self.unused_return_types = True
if "unused-return-types" in args.disable_pattern:
self.unused_return_types = False
if "kernel-prints" in args.enable_pattern:
self.kernel_prints = True
if "kernel-prints" in args.disable_pattern:
self.kernel_prints = False
if "dead-code" in args.enable_pattern:
self.dead_code = True
if "dead-code" in args.disable_pattern:
self.dead_code = False
if "numerical-macros" in args.enable_pattern:
self.numerical_macros = True
if "numerical-macros" in args.disable_pattern:
self.numerical_macros = False
if "relocations" in args.enable_pattern:
self.relocations = True
if "relocations" in args.disable_pattern:
self.relocations = False
if "type-casts" in args.enable_pattern:
self.type_casts = True
if "type-casts" in args.disable_pattern:
self.type_casts = False
if "control-flow-only" in args.enable_pattern:
self.control_flow_only = True
if "control-flow-only" in args.disable_pattern:
self.control_flow_only = False
if "inverse-conditions" in args.enable_pattern:
self.inverse_conditions = True
if "inverse-conditions" in args.disable_pattern:
self.inverse_conditions = False

self.resolve_dependencies()

def resolve_dependencies(self):
"""
Resolve dependencies between built-in patterns.
"""
if self.control_flow_only:
self.type_casts = True

def as_ffi_struct(self):
"""
Return the FFI representation of the built-in pattern configuration.
"""
ffi_struct = ffi.new("struct builtin_patterns *")
ffi_struct.StructAlignment = self.struct_alignment
ffi_struct.FunctionSplits = self.function_splits
ffi_struct.UnusedReturnTypes = self.unused_return_types
ffi_struct.KernelPrints = self.kernel_prints
ffi_struct.DeadCode = self.dead_code
ffi_struct.NumericalMacros = self.numerical_macros
ffi_struct.Relocations = self.relocations
ffi_struct.TypeCasts = self.type_casts
ffi_struct.ControlFlowOnly = self.control_flow_only
ffi_struct.InverseConditions = self.inverse_conditions
return ffi_struct


class Config:
def __init__(
self,
Expand All @@ -17,8 +158,7 @@ def __init__(
full_diff=False,
output_llvm_ir=False,
custom_pattern_config=None,
enabled_patterns=[],
disabled_patterns=[],
builtin_patterns=BuiltinPatterns(),
print_asm_diffs=False,
verbosity=0,
use_ffi=False,
Expand All @@ -32,8 +172,7 @@ def __init__(
:param full_diff: Evaluate semantics-preserving syntax differences too.
:param output_llvm_ir: Output each simplified module into a file.
:param custom_pattern_config: Valid custom pattern configuration.
:param enabled_patterns: List of enabled built-in patterns.
:param disabled_patterns: List of disabled built-in patterns.
:param builtin_patterns: Configuration of built-in patterns.
:param print_asm_diffs: Print assembly differences.
:param verbosity: Verbosity level (currently boolean).
:param use_ffi: Use Python FFI to call SimpLL.
Expand All @@ -46,8 +185,7 @@ def __init__(
self.full_diff = full_diff
self.output_llvm_ir = output_llvm_ir
self.custom_pattern_config = custom_pattern_config
self.enabled_patterns = enabled_patterns
self.disabled_patterns = disabled_patterns
self.builtin_patterns = builtin_patterns
self.print_asm_diffs = print_asm_diffs
self.verbosity = verbosity
self.use_ffi = use_ffi
Expand Down Expand Up @@ -76,6 +214,10 @@ def from_args(cls, args):
snapshot_first.filter([args.function])
snapshot_second.filter([args.function])

# Create the configuration of built-in patterns.
builtin_patterns = BuiltinPatterns()
builtin_patterns.update_from_args(args)

# Transform difference pattern files into an LLVM IR
# based configuration.
if args.custom_patterns:
Expand All @@ -91,8 +233,7 @@ def from_args(cls, args):
show_diff=not args.no_show_diff or args.show_diff,
full_diff=args.full_diff,
custom_pattern_config=custom_pattern_config,
enabled_patterns=args.enable_pattern,
disabled_patterns=args.disable_pattern,
builtin_patterns=builtin_patterns,
output_llvm_ir=args.output_llvm_ir,
print_asm_diffs=args.print_asm_diffs,
verbosity=args.verbose,
Expand Down
88 changes: 3 additions & 85 deletions diffkemp/simpll/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Config::Config(std::string FirstFunName,
std::string SecondOutFile,
std::string CacheDir,
std::string CustomPatternConfigPath,
builtin_pattern_args BuiltinPatternArgs,
BuiltinPatterns BIPatterns,
std::string Variable,
bool OutputLlvmIR,
bool PrintAsmDiffs,
Expand All @@ -49,8 +49,8 @@ Config::Config(std::string FirstFunName,
First(FirstModule), Second(SecondModule), FirstOutFile(FirstOutFile),
SecondOutFile(SecondOutFile), CacheDir(CacheDir),
CustomPatternConfigPath(CustomPatternConfigPath),
OutputLlvmIR(OutputLlvmIR), PrintAsmDiffs(PrintAsmDiffs),
PrintCallStacks(PrintCallStacks) {
BIPatterns(BIPatterns), OutputLlvmIR(OutputLlvmIR),
PrintAsmDiffs(PrintAsmDiffs), PrintCallStacks(PrintCallStacks) {
refreshFunctions();

if (!Variable.empty()) {
Expand All @@ -75,91 +75,9 @@ Config::Config(std::string FirstFunName,
}
}
setDebugTypes(debugTypes);

BuiltinPatterns = parseBuiltinPatternArgs(BuiltinPatternArgs);
}

void Config::refreshFunctions() {
FirstFun = First->getFunction(FirstFunName);
SecondFun = Second->getFunction(SecondFunName);
}

BuiltinPatterns parseBuiltinPatternArgs(const builtin_pattern_args &Args) {
struct BuiltinPatterns Patterns;

// Set built-in patterns to use. Priorities are as follows:
// 1. Explicit disablement of a single pattern.
// 2. Explicit enablement of a single pattern.
// 3. Explicit disablement of all patterns.
// 4. Explicit enablement of all patterns.
// 5. Default settings (see Config.h)
if (Args.EnableAll) {
Patterns.StructAlignment = true;
Patterns.FunctionSplits = true;
Patterns.UnusedReturnTypes = true;
Patterns.KernelPrints = true;
Patterns.DeadCode = true;
Patterns.NumericalMacros = true;
Patterns.Relocations = true;
Patterns.TypeCasts = true;
Patterns.ControlFlowOnly = true;
Patterns.InverseConditions = true;
}
if (Args.DisableAll) {
Patterns.StructAlignment = false;
Patterns.FunctionSplits = false;
Patterns.UnusedReturnTypes = false;
Patterns.KernelPrints = false;
Patterns.DeadCode = false;
Patterns.NumericalMacros = false;
Patterns.Relocations = false;
Patterns.TypeCasts = false;
Patterns.ControlFlowOnly = false;
Patterns.InverseConditions = false;
}
if (Args.EnableStructAlignment)
Patterns.StructAlignment = true;
if (Args.DisableStructAlignment)
Patterns.StructAlignment = false;
if (Args.EnableFunctionSplits)
Patterns.FunctionSplits = true;
if (Args.DisableFunctionSplits)
Patterns.FunctionSplits = false;
if (Args.EnableUnusedReturnTypes)
Patterns.UnusedReturnTypes = true;
if (Args.DisableUnusedReturnTypes)
Patterns.UnusedReturnTypes = false;
if (Args.EnableKernelPrints)
Patterns.KernelPrints = true;
if (Args.DisableKernelPrints)
Patterns.KernelPrints = false;
if (Args.EnableDeadCode)
Patterns.DeadCode = true;
if (Args.DisableDeadCode)
Patterns.DeadCode = false;
if (Args.EnableNumericalMacros)
Patterns.NumericalMacros = true;
if (Args.DisableNumericalMacros)
Patterns.NumericalMacros = false;
if (Args.EnableRelocations)
Patterns.Relocations = true;
if (Args.DisableRelocations)
Patterns.Relocations = false;
if (Args.EnableTypeCasts)
Patterns.TypeCasts = true;
if (Args.DisableTypeCasts)
Patterns.TypeCasts = false;
if (Args.EnableControlFlowOnly) {
Patterns.ControlFlowOnly = true;
// Turning on control-flow-only automatically turns on type casts
Patterns.TypeCasts = true;
}
if (Args.DisableControlFlowOnly)
Patterns.ControlFlowOnly = false;
if (Args.EnableInverseConditions)
Patterns.InverseConditions = true;
if (Args.DisableInverseConditions)
Patterns.InverseConditions = false;

return Patterns;
}
21 changes: 2 additions & 19 deletions diffkemp/simpll/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
#ifndef DIFFKEMP_SIMPLL_CONFIG_H
#define DIFFKEMP_SIMPLL_CONFIG_H

#include "library/FFI.h"
#include "llvm/Support/CommandLine.h"
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
Expand All @@ -28,34 +27,18 @@
using namespace llvm;

struct BuiltinPatterns {
// Changes in structure alignment
bool StructAlignment = true;
// Splitting code into functions
bool FunctionSplits = true;
// Changing unused return values to void
bool UnusedReturnTypes = true;
// Changes in kernel-specific printing functions calls. These include:
// - changes in strings printed by kernel print functions
// - changes in arguments of kernel functions that are related to the
// call location (file name and line number)
// - changes in counter, date, time, file name, and line macros
bool KernelPrints = true;
// Changes in dead code
bool DeadCode = true;
// Changed numerical value of a macro
bool NumericalMacros = true;
// Relocated instructions
bool Relocations = true;
// Changes in type casts
bool TypeCasts = false;
// Ignore all changes except those in control-flow
bool ControlFlowOnly = false;
// Inverted branch conditions
bool InverseConditions = true;
};

BuiltinPatterns parseBuiltinPatternArgs(const builtin_pattern_args &args);

/// Tool configuration parsed from CLI options.
class Config {
private:
Expand Down Expand Up @@ -86,7 +69,7 @@ class Config {

// The following structure specifies which built-in patterns
// should be treated as semantically equal.
struct BuiltinPatterns BuiltinPatterns;
struct BuiltinPatterns BIPatterns;

// Save the simplified IR of the module to a file.
bool OutputLlvmIR;
Expand All @@ -103,7 +86,7 @@ class Config {
std::string SecondOutFile,
std::string CacheDir,
std::string CustomPatternConfigPath,
builtin_pattern_args BuiltinPatternArgs,
BuiltinPatterns BIPatterns,
std::string Variable = "",
bool OutputLlvmIR = false,
bool PrintAsmDiffs = true,
Expand Down
Loading

0 comments on commit 1471848

Please sign in to comment.