Emit Walkthrough
Lowering is not the end of the story.
Many package features also need a backend emitter that turns a package-owned semantic family into concrete runtime or backend host operations.
The Graphics package has a strong real-world example.
Manifest Side
A backend emit route in feature.toml can look like this:
provider_id = "provider.core.host_llvm"
route_id = "host.llvm"
artifact_kind = "host.llvm_value"
required_extensions = ["llvm.runtime_import.v1"]
required_runtime_families = ["graphics"]
source = "backend/routes/host.llvm/Emit.cpp"
component_class = "graphics.cmd.draw.backend.hostllvm"
This says:
- the route targets the
host.llvmbackend host via a concrete provider - the backend host must expose runtime import support
- the graphics runtime family must exist
- the emitter lives in a package-owned
Emit.cpp
Real Emit Pattern
From morphs/Graphics/backend/routes/host.llvm/Emit.cpp:
bool emitStandardRuntimeRoute(MorphMorphBackendRouteContext *context,
const MorphMorphBackendOperationView *op,
std::string_view runtimeSymbol,
std::string *outError) {
BackendRouteApi api(*context);
std::vector<MorphMorphBackendValueHandle> arguments;
if (!materializeAllOperands(api, op, &arguments, outError)) {
return false;
}
MorphMorphBackendValueHandle result{};
const bool expectsResult = hasBindableResult(op);
if (!api.callRuntime(graphics_ids::kRuntimeFamily, runtimeSymbol, arguments,
expectsResult ? std::string_view(op->result_name)
: std::string_view{},
expectsResult ? &result : nullptr, outError)) {
return false;
}
return !expectsResult || bindIfNamed(api, op, result, outError);
}
This is a real package emitter:
- materialize operands
- call into the backend route API
- route through a package-owned runtime family
- bind the result if needed
A More Specialized Emit Case
The same file handles special behavior for material creation:
bool emitMaterialCreateRoute(MorphMorphBackendRouteContext *context,
const MorphMorphBackendOperationView *op,
std::string *outError) {
...
const std::string shaderName = rawShaderName != nullptr ? rawShaderName : "";
if (shaderName.empty()) {
if (outError != nullptr) {
*outError = "graphics.material.create received an empty shader name";
}
return false;
}
BackendRouteApi api(*context);
MorphMorphBackendValueHandle descriptor{};
if (!api.namedArtifactDescriptor("graphics", shaderName, &descriptor,
outError)) {
return false;
}
...
if (!api.callRuntime(graphics_ids::kRuntimeFamily,
graphics_ids::kRuntimeSymbolMaterialCreate, {descriptor},
expectsResult ? std::string_view(op->result_name)
: std::string_view{},
expectsResult ? &result : nullptr, outError)) {
return false;
}
...
}
Now the emitter is doing more than a raw runtime call:
- reading operation operands
- resolving a named artifact descriptor
- calling a package runtime symbol with a descriptor payload
This is exactly the kind of advanced behavior that still belongs in package space.
One Emit File, Many Semantic Families
The same Graphics emitter dispatches over many semantic families:
extern "C" int morph_graphics_backend_hostllvm_emit(
MorphMorphBackendRouteContext *context,
const MorphMorphBackendOperationView *op, const char **out_error) {
...
const std::string_view semanticFamily =
op->semantic_family_id != nullptr ? op->semantic_family_id : "";
const RouteDef *route = findRouteDef(semanticFamily);
if (route == nullptr) {
morph::morph::exportBackendRouteFailure(
"graphics backend route received an unknown semantic family", out_error);
return 0;
}
...
}
This is still package-owned because the semantic families and route table belong to Graphics.
What Emit Means In Practice
For Morph authors, an emit file is where a backend route:
- reads lowered operations
- validates route-specific assumptions
- materializes operands
- calls backend host APIs
- binds results
- maps semantic families to runtime or backend behavior
It is not a generic dumping ground in core codegen.
Next Steps
- LLVM Route Signatures - how to declare what an emit file requires
- Validation And Testing - how to test emitters and route declarations