FCC is a multi-language compiler collection framework written in C# (.NET 8). It packages support for multiple programming languages into a single tool, similar to GCC, Clang, or .NET's Roslyn.
By default FCC does not ship with any frontends or backends. Those are
plugged in via ICompilerBackend / ICompilerFrontend interfaces (see
Backends & Frontends).
FCC/
├── fcc/ # CLI entry point
│ └── Program.cs # fcc <input.cpp> [output.oir]
├── libs/
│ ├── ObjectIR.Core/ # Core IR library (object-oriented IR)
│ ├── CppToObjectIR/ # C++ → ObjectIR frontend
│ └── CppToObjectIR.Tests/ # C++ frontend test suite
├── ObjectIR.Programming/ # Type-system library (G#/GS project)
├── Docs/ # This documentation
├── examples/ # Sample C++ programs
├── repro/ # Repro cases / regression tests
└── FCC.sln # Visual Studio solution file
FCC is organised in layers. Each layer depends only on layers below it.
Source text (.cpp, .cs, …)
│
▼
Frontend (e.g. CppToObjectIR)
│ Lex → Parse → CodeGen
▼
ObjectIR.Core.AST
│
├──► ModuleSerializer → JSON / BSON / text
├──► ModuleComposer → merged Module
│ └──► DependencyResolver
└──► FobIrCompiler → .fob binary (compact binary format)
| Component | Language | Description |
|---|---|---|
| fcc (CLI) | C# | Entry point. Reads input, invokes the frontend, serialises the result. |
| ObjectIR.Core | C# | The shared intermediate representation. Types, methods, instructions, serialization, composition, and the fluent builder API. Published as a NuGet package. |
| CppToObjectIR | C# | C++ (subset) frontend. Lexer → Parser → IrCodeGenerator → ObjectIR Module. |
| ObjectIR.Programming | G# | Type checking and type system library for compiler manufacturers. |
fcc input.cpp output.oir
1. Read input.cpp
2. Resolve #include directives in the same directory
3. Lex + Parse C++ → AST
4. Build a member type registry from AST + headers
5. Compile AST → ObjectIR Module
6. Serialise Module → .oir (FOB binary) file
- .NET10 SDK (or later)
git clone https://git.finite.ovh/FCC
cd FCC
dotnet build FCC.slnxdotnet run --project fcc -- examples/test.cpp output.oirThis compiles a C++ file into a .oir (FOB binary) file. You can also pipe
the output through any registered backend for code generation.
fcc <input> [output] [-o <output>] [--target fob|bir|textir|json] [-I <path>] [-D <define>]
| Flag | Default | Description |
|---|---|---|
input |
— | Source file to compile |
output |
<input>.oir |
Output file path (positional or -o) |
-t / --target / --emit |
fob |
Output format |
-I |
— | Add include search path for header resolution |
-D |
— | Add preprocessor define |
Output targets:
| Target | Extension | Description |
|---|---|---|
fob |
.fobir |
FOB/IR binary format (compact, default) |
bir |
.bir |
BSON IR format |
textir |
.oir |
Human-readable IR code text |
json |
.json |
Structured JSON format |
fcc build [<project.fccproj>] [args...]
fcc <project.fccproj>
When fcc build is run without a project path, FCC scans the current directory
for a single .fccproj file. If exactly one is found, it is used automatically.
Project files use an XML format modelled after .csproj:
<Project Sdk="FCC">
<PropertyGroup>
<OutputName>MyApp</OutputName>
<OutputPath>bin</OutputPath>
<TargetFormat>fob</TargetFormat>
</PropertyGroup>
<ItemGroup>
<Compile Include="src/**/*.cpp" />
<Compile Include="src/**/*.h" />
<IncludePath Include="include" />
<Define Include="DEBUG" />
</ItemGroup>
</Project>PropertyGroup settings:
| Element | Default | Description |
|---|---|---|
OutputName |
output |
Base name of the compiled output |
OutputPath |
bin |
Directory for the compiled output |
TargetFormat |
fob |
Output format (fob, bir, textir, json) |
RootNamespace |
— | (reserved) |
ItemGroup elements:
| Element | Attribute | Description |
|---|---|---|
Compile |
Include |
Source file or glob pattern (e.g. src/**/*.cpp) |
IncludePath |
Include |
Directory to search for #include headers |
Define |
Include |
Preprocessor define |
Paths in project files are resolved relative to the project directory.
Glob patterns (*, ?) are supported in Compile Include attributes.
Exit codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Input/project error |
2 |
Compilation error |
# Compile a C++ file to FOB binary
fcc examples/test.cpp
# Compile to human-readable IR text
fcc examples/test.cpp --target textir -o output.ir.txt
# Compile with include paths
fcc examples/test.cpp -I examples/include
# Build a project
fcc build examples/sample.fccproj
# Auto-discover project in current directory
cd examples && fcc build
# Override target format for a project build
fcc build sample.fccproj --target jsonThe C++ frontend compiles a subset of C++ into ObjectIR. It lives in
libs/CppToObjectIR/ and is structured as a classic three-phase compiler:
Source text
│
▼
Lexer (libs/CppToObjectIR/Lexing/)
│ Tokenizes: keywords, identifiers, operators, literals, skips # directives
│ 56 token kinds covering C++ type keywords, control flow, OOP, and operators
▼
Parser (libs/CppToObjectIR/Parsing/)
│ Produces a C++ AST (libs/CppToObjectIR/Ast/)
│ 30+ AST node types: classes, structs, enums, namespaces, methods,
│ fields, statements (if/while/for/do-while/try-catch/throw),
│ expressions (binary, unary, call, member access, new, cast, ternary)
▼
IrCodeGenerator (libs/CppToObjectIR/CodeGen/)
│ Walks the AST and emits ObjectIR instructions
│ Handles: type mapping (C++ → IR), std::cout chains, type inference
▼
ObjectIR.Core.Module
| Feature | Status |
|---|---|
| Namespaces | Yes (emitted as static classes with free functions) |
| Classes (fields, methods, constructors) | Yes |
| Structs | Yes |
| Enums (with underlying type) | Yes |
| Inheritance | Yes (base class + interfaces) |
| Virtual / override / pure virtual | Yes |
| Access specifiers (public/private/protected) | Yes |
| Static members | Yes |
if / else |
Yes |
while, for, do-while |
Yes |
break / continue |
Yes |
try / catch / throw |
Yes |
new / delete |
Yes (new) |
std::cout << ... chaining |
Yes (maps to System.Console.Write/WriteLine) |
| Type inference for member access | Yes (via member type registry) |
Conversion methods (ToString, ToInt, etc.) |
Yes (maps to System.Convert) |
| Ternary operator | Yes |
Arrays (new int[n]) |
Yes |
| Templates | Basic (template args are mapped) |
| Preprocessor | Minimal (skips #include, #define, #ifdef, etc.) |
| Pointers / references | Parsed, treated as the base type in IR |
ObjectIR.Core is the heart of FCC — an object-oriented intermediate representation designed from the ground up for OO languages. Think LLVM IR, but for classes, interfaces, generics, and virtual dispatch.
Full documentation lives in libs/ObjectIR.Core/docs/:
| Page | Description |
|---|---|
| Architecture | Namespace layout, layer diagram, design decisions |
| Getting Started | Install, first module, what to read next |
| IR Model | Module, TypeDefinition, MethodDefinition, Instructions |
| Builder API | Fluent IRBuilder with annotated examples |
| Serialization | Text format, JSON/BSON, ModuleLoader |
| Composition | Merging modules, dependency resolution |
| FOB Format | Compact binary .fob format spec |
Module "TodoApp" version 1.0.0
interface IItem {
method GetId() -> int32
method GetDescription() -> string
}
class TodoItem : IItem {
private field id: int32
private field description: string
constructor(id: int32, description: string) {
ldarg this
ldarg id
stfld TodoItem.id
ret
}
method GetId() -> int32 implements IItem.GetId {
ldarg this
ldfld TodoItem.id
ret
}
}
Key properties:
- Stack-based IL (like CIL/bytecode)
- First-class structured control flow —
IfInstruction,WhileInstruction,ForEachInstruction,TryInstructionas IR nodes, not raw branch targets - Visitor pattern for instruction passes — implement
IInstructionVisitor - Fluent builder —
IRBuilderfor constructing modules in C# code - Cross-module composition —
ModuleComposermerges modules, resolves dependency order, detects cycles - Multiple serialisation formats — human-readable text, JSON/BSON for interop, compact FOB binary for distribution
FCC is designed as a compiler collection — one tool that can handle many
languages. Support for new languages is added through two interfaces (defined
in the ObjectIR.Programming library):
interface ICompilerBackend {
void Compile(string path); // compile one module
void CompileAll(string path, List<string> files); // batch compile
}
interface ICompilerFrontend {
// (defined in ObjectIR.Programming)
}| Interface | Purpose |
|---|---|
ICompilerBackend |
Takes an ObjectIR module and produces target code (machine code, C#, IL, JS, etc.) |
ICompilerFrontend |
Takes source code and produces an ObjectIR module |
Because FCC has no built-in understanding of ObjectIR types, the standard library,
or language-specific semantics, compiler manufacturers should use the
ObjectIR.Programming library for type checking.
Note:
ObjectIR.Programmingis a separate repository. The type checker and type system are being developed there.
- Implement
ICompilerBackend - Register it with the FCC runtime
- The
fccCLI will use it when generating final output
- Implement
ICompilerFrontend - Your frontend receives source text and returns an ObjectIR
Module - The
fccCLI dispatches to the right frontend based on file extension
The examples/ directory contains sample C++ programs:
| File | Description |
|---|---|
test.cpp |
Hello World, get_value() call |
classes.cpp |
Class with fields, methods, constructors |
playercontroller.cpp |
Unity-style player controller |
crystal.cpp |
Crystal language test |
UnityEngine.h |
Unity engine header stub |
IRRuntime.h |
IR runtime header stub |
The repro/ directory contains regression test cases:
| File | Description |
|---|---|
main.cpp |
Program calling get_value() from a C-linkage header |
repro.h |
C-linkage function declaration |
impl.c |
Implementation of get_value() |
main.oir |
Compiled output (FOB binary) |
See Docs/COMPLETE_EXAMPLE.md for a full todo-list
application written in ObjectIR text format, demonstrating:
- Class hierarchies and interface implementation
- Generic collections (
List<T>) - Constructors with parameters
- Conditional logic and loops
- String operations
- The C# Builder API equivalent
- Backend considerations (C#, JS, C++, Java)
# Restore and build everything
dotnet restore FCC.sln
dotnet build FCC.sln
# Run the C++ frontend tests
dotnet test libs/CppToObjectIR.Tests
# Compile a test file
dotnet run --project fcc -- examples/test.cpp