Skip to content

ltcmelo/psychec

Repository files navigation

Note (unrelated to Psyche-C)
C language draft proposal: Enabling Generic Functions and Parametric Types in C (prototype).


Psyche-C

Psyche-C is a platform for implementing static analysis of C programs. At its core, it includes a C compiler frontend that performs both syntactic and semantic analysis. Yet, as opposed to actual C compilers, Psyche-C doesn't build a symbol table during parsing. Despite this, even with zero setup or in broken build setups, Psyche-C still offers accurate syntax analysis (through syntax disambiguation) and partial semantic analysis.

Bellow are the main characteristics of Psyche-C:

  • Clean separation between the syntactic and semantic compiler phases.
  • Algorithmic and heuristic syntax disambiguation.
  • Optional type inference as a recovery mechanism from #include failures (not yet in master).
  • API inspired by that of the Roslyn .NET compiler and LLVM's Clang.

Driver

Psyche-C is written as a C++ library, but it comes with a builtin driver: cnippet. You can use it by passing to it either the typical command line arguments of an actual compiler or the actual compiler's whole invocation as a subcommand.

Example with cnippet only:

cnip -analysis /path/to/analysis.dylib -I/path/to/whatever file.c

Example with compiler's invocation as a subcommand:

cnip -analysis /path/to/analysis.dylib -- gcc -I/path/to/whatever file.c

See psychec-analysis for a trivial example of how to implement an analysis.

Type Inference

Psyche-C began as a type inference tool for C, aimed at enabling static analysis of incomplete programs. However, the compiler frontend at its core wasn't good enough, so I decided to rewrite it pretty much from scratch. I used this rewrite also as an opportunity to extend Psyche-C into a platform for static analysis in general. The result of this work is what exists today in the master branch, but that doesn't yet include a port of the type inference from the original branch.

With type inference enabled, if you "compile" the snippet below with cnippet, Psyche-C will infer T and synthesize a declaration for it.

void f()
{
    T v = 0;
    v->value = 42;
    v->next = v;
}

Synthesized declaration for T.

typedef struct TYPE_2__ TYPE_1__;
struct TYPE_2__ 
{
    int value;
    struct TYPE_2__* next;
} ;
typedef TYPE_1__* T;

You might want to use this functionality to:

  • Enable, on incomplete programs, analyses that depend on complete programs.
  • Generate test-input/mocks to validate functions in isolation.
  • Prototype an algorithm while only sketching its data-structures
  • Compile a snippet for inspection of static properties of its object code.

Documentation and Resources

Building and Testing

To build:

cmake CMakeLists.txt && make -j 4

To run the tests:

./test-suite

Related Publications

Of Psyche-C itself:

That use Psyche-C: