Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Migration From bic

This chapter documents how to migrate downstream consumers from bic’s frontend extraction to parc’s SourcePackage contract.

Why migrate

parc now owns source-level declaration extraction. bic’s extract.rs was the legacy location for this logic. The canonical path is now:

C headers  ->  parc::scan / parc::extract  ->  SourcePackage  ->  downstream

bic should consume parc::ir::SourcePackage instead of owning its own extraction.

Type mapping

bic typeparc typeNotes
BindingPackageSourcePackageparc has no layouts, link, or bic_version
BindingItemSourceItemSame variant set
BindingTypeSourceTypePointer model differs (see below)
FunctionBindingSourceFunctionIdentical structure
ParameterBindingSourceParameterIdentical structure
RecordBindingSourceRecordNo representation or abi_confidence
FieldBindingSourceFieldNo layout field
EnumBindingSourceEnumIdentical structure
TypeAliasBindingSourceTypeAliasNo canonical_resolution
VariableBindingSourceVariableIdentical structure
UnsupportedItemSourceUnsupportedIdentical structure
CallingConventionCallingConventionparc version includes Unknown(String)
TypeQualifiersTypeQualifiersIdentical structure
BindingTargetSourceTargetIdentical structure
BindingInputsSourceInputsIdentical structure
BindingDefineSourceDefineIdentical structure
MacroBindingSourceMacroparc drops function_like and category
DeclarationProvenanceDeclarationProvenanceIdentical structure
MacroProvenanceMacroProvenanceIdentical structure

Pointer model difference

bic:

#![allow(unused)]
fn main() {
Pointer {
    pointee: Box<BindingType>,
    const_pointee: bool,      // whether pointee is const
    qualifiers: TypeQualifiers, // qualifiers on the pointer itself
}
}

parc:

#![allow(unused)]
fn main() {
Pointer {
    pointee: Box<SourceType>,
    qualifiers: TypeQualifiers, // is_const means pointee is const
}
}

In parc, qualifiers.is_const on a Pointer indicates that the pointee is const-qualified. Use SourceType::const_ptr(inner) and SourceType::ptr(inner) as constructors.

Missing fields in parc

These bic fields are intentionally absent from parc because they belong to the link/ABI layer:

  • FieldBinding.layout (field offset) — use LINC probing
  • RecordBinding.representation — use LINC probing
  • RecordBinding.abi_confidence — use LINC validation
  • TypeAliasBinding.canonical_resolution — parc preserves TypedefRef chains
  • BindingPackage.layouts — use LINC probing
  • BindingPackage.link — use LINC link surface
  • BindingPackage.effective_macro_environment — use LINC macro analysis

Migration steps

Step 1: Replace extraction call

Before:

#![allow(unused)]
fn main() {
use bic::extract::Extractor;
use bic::ir::BindingPackage;

let extractor = Extractor::new();
let (items, diagnostics) = extractor.extract(&unit);
let mut pkg = BindingPackage::new();
pkg.items = items;
}

After:

#![allow(unused)]
fn main() {
use parc::extract;
use parc::ir::SourcePackage;

let pkg = extract::extract_from_translation_unit(&unit, Some("header.h".into()));
}

Or for end-to-end scanning:

#![allow(unused)]
fn main() {
use parc::scan::{ScanConfig, scan_headers};

let config = ScanConfig::new()
    .entry_header("header.h")
    .with_builtin_preprocessor();
let result = scan_headers(&config).unwrap();
let pkg: &SourcePackage = &result.package;
}

Step 2: Update type references

Replace all uses of BindingType with SourceType, BindingItem with SourceItem, etc. The variant names are identical.

Step 3: Handle pointer model

Replace const_pointee checks:

#![allow(unused)]
fn main() {
// Before (bic)
if let BindingType::Pointer { const_pointee: true, .. } = ty { ... }

// After (parc)
if let SourceType::Pointer { qualifiers, .. } = ty {
    if qualifiers.is_const { ... }
}
}

Step 4: Remove ABI fields

Any code that reads FieldBinding.layout, RecordBinding.representation, or RecordBinding.abi_confidence should be moved to LINC’s domain.

Step 5: Use builder for programmatic construction

#![allow(unused)]
fn main() {
use parc::ir::{SourcePackageBuilder, SourceItem, SourceFunction, ...};

let pkg = SourcePackageBuilder::new()
    .source_path("api.h")
    .item(SourceItem::Function(func))
    .item(SourceItem::Record(rec))
    .build();
}

API reference

Key public APIs for downstream consumers:

  • parc::extract::extract_from_source(src) — parse and extract
  • parc::extract::extract_from_translation_unit(unit, path) — extract from AST
  • parc::extract::parse_and_extract(src, flavor) — with flavor control
  • parc::extract::parse_and_extract_resilient(src, flavor) — with error recovery
  • parc::scan::scan_headers(config) — end-to-end header scanning
  • parc::ir::SourcePackage — the contract type
  • parc::ir::SourcePackageBuilder — programmatic construction
  • SourcePackage::retain_items(pred) — filter items
  • SourcePackage::merge(other) — combine packages