Files
TheRock/rocm-libraries/shared/stinkytofu/docs/user/asm-emitter.md
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

271 lines
6.7 KiB
Markdown

# StinkyAsmEmitter User Guide
## Overview
'StinkyAsmEmitter' converts StinkyTofu IR (MLIR-style intermediate representation) into actual GPU assembly code that can be processed by assemblers and compilers.
## Basic Usage
### Simple Assembly Emission
'''cpp
#include "stinkytofu/serialization/asm/StinkyAsmEmitter.hpp"
#include "stinkytofu/core/stinkytofu.hpp"
using namespace stinkytofu;
// Assuming you have an IRList populated with instructions
IRList irlist;
// ... populate irlist ...
// Create an emitter with default options
StinkyAsmEmitter emitter;
// Emit assembly code as a string
std::string assembly = emitter.emit(irlist);
std::cout << assembly << std::endl;
'''
### Emit to Stream
'''cpp
// Emit directly to a stream (e.g., file)
std::ofstream outFile("output.s");
StinkyAsmEmitter emitter;
emitter.emit(outFile, irlist);
outFile.close();
'''
### Using the Utility Function
'''cpp
// Quick conversion using the toAssembly() utility
std::string assembly = toAssembly(irlist);
'''
## Configuration Options
The 'AsmEmitterOptions' struct allows you to customize the assembly output:
'''cpp
struct AsmEmitterOptions {
bool emitComments = true; // Include header comments
bool emitCycleInfo = true; // Emit cycle count information
int indent = 4; // Instruction indentation (spaces)
bool emitBlankLines = false; // Add blank lines between instruction groups
};
'''
### Example: Custom Configuration
'''cpp
AsmEmitterOptions options;
options.emitComments = false; // No header comments
options.emitCycleInfo = true; // Show cycle counts
options.indent = 8; // Use 8-space indentation
StinkyAsmEmitter emitter(options);
std::string assembly = emitter.emit(irlist);
'''
## Complete Example
Here's a complete example showing how to create instructions and emit them as assembly:
'''cpp
#include "stinkytofu/serialization/asm/StinkyAsmEmitter.hpp"
#include "stinkytofu/core/stinkytofu.hpp"
#include <iostream>
using namespace stinkytofu;
int main() {
// Create a PassContext (manages IR and builders)
auto ctx = PassContext::create(GfxArchID::gfx1250);
// Get the IRList and builder
IRList& irlist = ctx->getIRList();
AsmIRBuilder* builder = ctx->getIRBuilder();
// Create a label (builder must be bound to a block, e.g. via setInsertionPoint)
builder->createLabel("loop_start");
// Create a ds_read instruction
StinkyInstruction* inst1 = builder->createStinkyInstruction(
"ds_read_b128", irlist.end());
inst1->destRegs.push_back(StinkyRegister("v", 0, 4)); // v[0:3]
inst1->srcRegs.push_back(StinkyRegister("v", 40, 1)); // v[40]
inst1->issueCycles = 4;
inst1->latencyCycles = 52;
// Create another ds_read instruction
StinkyInstruction* inst2 = builder->createStinkyInstruction(
"ds_read_b128", irlist.end());
inst2->destRegs.push_back(StinkyRegister("v", 4, 4)); // v[4:7]
inst2->srcRegs.push_back(StinkyRegister("v", 40, 1)); // v[40]
inst2->issueCycles = 4;
inst2->latencyCycles = 52;
// Configure emission options
AsmEmitterOptions options;
options.emitComments = true;
options.emitCycleInfo = true;
options.indent = 4;
// Emit assembly
StinkyAsmEmitter emitter(options);
std::string assembly = emitter.emit(irlist);
// Print the result
std::cout << assembly << std::endl;
return 0;
}
'''
### Expected Output
'''assembly
// ==================================================
// StinkyTofu Assembly Output
// Instructions: 3
// ==================================================
loop_start:
ds_read_b128 v[0:3], v[40] // issue=4 latency=52
ds_read_b128 v[4:7], v[40] // issue=4 latency=52
'''
## Without Cycle Information
If you don't want cycle count comments:
'''cpp
AsmEmitterOptions options;
options.emitCycleInfo = false;
StinkyAsmEmitter emitter(options);
std::string assembly = emitter.emit(irlist);
'''
### Output
'''assembly
// ==================================================
// StinkyTofu Assembly Output
// Instructions: 3
// ==================================================
loop_start:
ds_read_b128 v[0:3], v[40]
ds_read_b128 v[4:7], v[40]
'''
## Minimal Output (No Comments)
For production assembly without any comments:
'''cpp
AsmEmitterOptions options;
options.emitComments = false;
options.emitCycleInfo = false;
StinkyAsmEmitter emitter(options);
std::string assembly = emitter.emit(irlist);
'''
### Output
'''assembly
loop_start:
ds_read_b128 v[0:3], v[40]
ds_read_b128 v[4:7], v[40]
'''
## Emitting Single Instructions
You can also emit individual instructions:
'''cpp
StinkyInstruction* inst = /* ... get instruction ... */;
AsmEmitterOptions options;
options.emitCycleInfo = true;
StinkyAsmEmitter emitter(options);
std::string assembly = emitter.emit(*inst);
// Output: " ds_read_b128 v[0:3], v[40] // issue=4 latency=52\n"
'''
## Common Use Cases
### 1. Debug Output
Use default options with comments and cycle info to understand instruction timing:
'''cpp
std::cout << toAssembly(irlist) << std::endl;
'''
### 2. Assembly File Generation
Generate clean assembly for the assembler:
'''cpp
AsmEmitterOptions options;
options.emitComments = false;
options.emitCycleInfo = false;
std::ofstream asmFile("kernel.s");
StinkyAsmEmitter emitter(options);
emitter.emit(asmFile, irlist);
asmFile.close();
'''
### 3. Annotated Assembly for Analysis
Include cycle information for performance analysis:
'''cpp
AsmEmitterOptions options;
options.emitComments = true;
options.emitCycleInfo = true;
std::ofstream annotated("kernel_annotated.s");
StinkyAsmEmitter emitter(options);
emitter.emit(annotated, irlist);
annotated.close();
'''
## Register Formats
The emitter handles different register types correctly:
| Register Type | Example | Assembly Output |
|--------------|---------|-----------------|
| Vector (single) | 'StinkyRegister("v", 5, 1)' | 'v[5]' |
| Vector (range) | 'StinkyRegister("v", 0, 4)' | 'v[0:3]' |
| Accumulator | 'StinkyRegister("acc", 0, 16)' | 'acc[0:15]' |
| Scalar | 'StinkyRegister("s", 10, 1)' | 's10' |
| Literal int | 'StinkyRegister(0)' | '0' |
## Integration with Pass Pipeline
The emitter works seamlessly with the pass manager:
'''cpp
// Create context and run optimization passes
auto ctx = PassContext::create(GfxArchID::gfx1250);
IRList& irlist = ctx->getIRList();
// ... populate irlist and run passes ...
PassManager pm;
pm.addPass(std::make_unique<SomeOptimizationPass>());
pm.run(*ctx);
// Emit optimized assembly
AsmEmitterOptions options;
options.emitComments = true;
std::string assembly = toAssembly(irlist, options);
std::cout << assembly << std::endl;
'''
## See Also
- [Error Codes](error-codes.md) - Common error codes and their meanings