Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e5bcdd6
Fix managed ilasm version defaults and module name fallback
jkoritzinsky Apr 17, 2026
d533ff9
Fix .module directive parsing order in ANTLR grammar
jkoritzinsky Apr 17, 2026
eb960b6
Fix managed ilasm parser for hex byte blobs, native int, unsigned, ar…
jkoritzinsky Apr 17, 2026
37c01cf
Add native ilasm-style flag aliases (-DLL, -DET, -OUTPUT=, etc.)
jkoritzinsky Apr 18, 2026
fc76cc8
Fix HEXBYTE token conflicts, prefix opcodes, array bounds, volatile f…
jkoritzinsky Apr 18, 2026
0aabe82
Fix semantic failures: named locals/args, string escapes, floats, swi…
jkoritzinsky Apr 18, 2026
df0c9f9
Fix 'il' impl attr, endfault instruction, ldc.i4.M1, and ? in identif…
jkoritzinsky Apr 18, 2026
4df5415
Fix preprocessor #define macro expansion to re-lex multi-token values
jkoritzinsky Apr 18, 2026
4edb58d
Support forward type references and fix ildasm crash known issues
jkoritzinsky Apr 18, 2026
c2eb3a9
Fix metadata emission: MethodImpl, method body headers, EventMap/Prop…
jkoritzinsky Apr 18, 2026
1fad533
Fix semantic failures: enum cast, float literals, param type, propert…
jkoritzinsky Apr 18, 2026
bf9b027
Fix custom attribute array blob encoding index
jkoritzinsky Apr 18, 2026
84d8be3
Fix remaining edge cases: vararg, negative ints, wchar, abstract warning
jkoritzinsky Apr 18, 2026
e30e8e6
Fix GenericParam sorting and method body error recovery
jkoritzinsky Apr 18, 2026
f6b8c55
Fix forward-referenced type generic params, NullRef, switch(), hex, d…
jkoritzinsky Apr 18, 2026
9eacd99
Fix array bounds parsing by requiring fractional digits in FLOAT64
jkoritzinsky Apr 18, 2026
bafede8
Two-pass generic param parsing, refany, Int64.MinValue, 128-bit hex
jkoritzinsky Apr 18, 2026
e750e29
Fix last 4 single-file failures: switch(), 65K params, resource ref
jkoritzinsky Apr 19, 2026
75618a7
Report error diagnostic for generic parameter count exceeding limit. …
jkoritzinsky Apr 20, 2026
361e564
Update test name
jkoritzinsky Apr 20, 2026
95400e4
Multi-document compilation with preprocessor state transfer
jkoritzinsky Apr 20, 2026
6d71813
Use collection expressions
jkoritzinsky Apr 20, 2026
e321125
Fix empty document parsing and eventAttr Aggregate on empty sequence
jkoritzinsky Apr 20, 2026
a1a9390
Fix duplicate locals, SQSTRING id quotes, and empty eventAttr
jkoritzinsky Apr 20, 2026
6f1fd47
Remove multi-file #define known issue (fixed)
jkoritzinsky Apr 20, 2026
1fb7d6c
Fix class visibility, hexbyte encoding, SQSTRING quoting, classAttr h…
jkoritzinsky Apr 20, 2026
bac255c
Fix rtspecialname on methods/fields, interface implicit base type
jkoritzinsky Apr 20, 2026
7e0e452
Fix custom attr on methods, type name dot prefix, mscorlib version
jkoritzinsky Apr 20, 2026
6225b70
Fix namespace leading dot, [in] param emission, field/extends cascading
jkoritzinsky Apr 20, 2026
20b7955
Resolve MemberReferences to local MethodDef and FieldDef tokens
jkoritzinsky Apr 20, 2026
12cd3ba
Fix vararg MemberRef parameter count and parent resolution
jkoritzinsky Apr 20, 2026
337347d
Fix field constants, stackreserve, param naming, and specialname
jkoritzinsky Apr 21, 2026
3a5c678
Fix pinvoke, leading-dot names, and NameHelpers splitting
jkoritzinsky Apr 21, 2026
e64b3d8
Use primitive type codes for well-known corelib types in signatures
jkoritzinsky Apr 21, 2026
db1fe42
Add ANTLR parser error listener for diagnostic reporting
jkoritzinsky Apr 21, 2026
06cb46a
Fix grammar rules to eliminate parser diagnostics
jkoritzinsky Apr 21, 2026
0b518b7
Redirect corelib TypeRefs and resolve unqualified well-known types
jkoritzinsky Apr 21, 2026
62f91f1
Fix custom attribute emission on types and blob prolog size
jkoritzinsky Apr 21, 2026
6156615
Fix custom attributes at top-level decl scope
jkoritzinsky Apr 21, 2026
6dc1576
Auto-add instance, specialname, and param names for compat
jkoritzinsky Apr 21, 2026
788a9be
Set HasFieldRVA flag and add FieldRVA test
jkoritzinsky Apr 21, 2026
48521b5
Fix FieldRVA flag, top-level custom attr owner, and identify ildasm c…
jkoritzinsky Apr 21, 2026
197cb92
Fix GenericParamConstraint sorting and defer DebuggableAttribute
jkoritzinsky Apr 21, 2026
63e5984
Fix security attribute blob type name and ildasm crash
jkoritzinsky Apr 21, 2026
9312103
Fix array shape encoding in multi-dimensional array signatures
jkoritzinsky Apr 21, 2026
9f43266
Fix function pointer syntax failures by writing to a separate blob (a…
jkoritzinsky Apr 21, 2026
381f151
Fix assigning generic parameters/generic parameter constraints the co…
jkoritzinsky Apr 21, 2026
5d9f82d
Resolve TypeRef to TypeDef for local types in managed ilasm
jkoritzinsky Apr 21, 2026
3f62c3f
Fix modopt/modreq signature rewriting and ClassLayout emission
jkoritzinsky Apr 21, 2026
02b98f1
Add TypeRef IL token backpatching and tests
jkoritzinsky Apr 21, 2026
02e1c20
Fix IL body corruption at BlobBuilder chunk boundary
jkoritzinsky Apr 22, 2026
7046fb4
Fix GetArrayType to emit ELEMENT_TYPE_ARRAY prefix in signature rewriter
jkoritzinsky Apr 22, 2026
9a3f2fb
Build locals standalone signature from parsed .locals declarations
jkoritzinsky Apr 22, 2026
defe488
Defer exception region registration to emission for TypeRef resolution
jkoritzinsky Apr 22, 2026
f2c9257
Address PR feedback: fix generated paths, span length, NamedElementLi…
jkoritzinsky Apr 23, 2026
b6e398f
Address PR feedback: fallback body headers, hexbyte validation, macro…
jkoritzinsky Apr 23, 2026
f2f52be
Fix custom attributes on properties and events being silently dropped
jkoritzinsky Apr 24, 2026
232fc75
Address Copilot review: MethodSpec header, array shape, CLI aliases, …
jkoritzinsky Apr 24, 2026
d7d2115
Align FieldMarshal row emission with HasFieldMarshal flag condition
jkoritzinsky Apr 24, 2026
880609b
Update src/tools/ilasm/src/ILAssembler/DocumentCompiler.cs
jkoritzinsky Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/tools/ilasm/KNOWN-ISSUES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Managed IL Assembler - Known Issues

## TLS RVA statics

Thread-local storage (TLS) RVA static fields (`.data tls`) are not
supported by the managed ilasm. The native ilasm emits a TLS directory
entry in the PE header for these, which the managed ilasm's PE builder
does not currently implement.


6 changes: 5 additions & 1 deletion src/tools/ilasm/src/ILAssembler/BlobBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ public static void WriteSerializedValue<T>(this BlobBuilder writer, T value)

public static void WriteTypeEntity(this BlobBuilder builder, EntityRegistry.TypeEntity entity)
{
if (entity is EntityRegistry.FakeTypeEntity fakeEntity)
if (entity is EntityRegistry.TypeReferenceEntity typeRef)
{
builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(typeRef.PseudoHandle));
}
else if (entity is EntityRegistry.FakeTypeEntity fakeEntity)
{
builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(fakeEntity.TypeSignatureHandle));
}
Expand Down
2 changes: 2 additions & 0 deletions src/tools/ilasm/src/ILAssembler/Diagnostic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static class DiagnosticIds
public const string DuplicateMethod = "ILA0030";
public const string MissingExportedTypeImplementation = "ILA0031";
public const string KeyFileError = "ILA0032";
public const string TooManyGenericParameters = "ILA0033";
}

internal static class DiagnosticMessageTemplates
Expand Down Expand Up @@ -87,4 +88,5 @@ internal static class DiagnosticMessageTemplates
public const string ParameterIndexOutOfRange = "Parameter index {0} is out of range";
public const string DuplicateMethod = "Duplicate method definition";
public const string MissingExportedTypeImplementation = "Undefined implementation in ExportedType '{0}' -- ExportedType not emitted";
public const string TooManyGenericParameters = "Generic parameter count {0} exceeds the maximum of {1}";
}
111 changes: 84 additions & 27 deletions src/tools/ilasm/src/ILAssembler/DocumentCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,70 @@ public sealed class DocumentCompiler
{
public (ImmutableArray<Diagnostic>, PEBuilder?) Compile(SourceText document, Func<string, SourceText> includedDocumentLoader, Func<string, byte[]> resourceLocator, Options options)
{
var inputSource = new AntlrInputStream(document.Text)
{
name = document.Path
};
CILLexer lexer = new(inputSource);
Dictionary<string, SourceText> loadedDocuments = new()
{
{document.Path!, document }
};
PreprocessedTokenSource preprocessor = new(lexer, path =>
return Compile([document], includedDocumentLoader, resourceLocator, options);
}

public (ImmutableArray<Diagnostic>, PEBuilder?) Compile(ImmutableArray<SourceText> documents, Func<string, SourceText> includedDocumentLoader, Func<string, byte[]> resourceLocator, Options options)
{
Dictionary<string, SourceText> loadedDocuments = new();
ImmutableArray<Diagnostic>.Builder diagnostics = ImmutableArray.CreateBuilder<Diagnostic>();

GrammarVisitor? visitor = null;
IReadOnlyDictionary<string, string?>? definedVariables = null;

foreach (var document in documents)
{
var includedDocument = includedDocumentLoader(path);
loadedDocuments[document.Path!] = document;

var includedSource = new AntlrInputStream(includedDocument.Text)
var inputSource = new AntlrInputStream(document.Text)
{
name = includedDocument.Path
name = document.Path
};
loadedDocuments.Add(includedDocument.Path, includedDocument);
return new CILLexer(includedSource);
});
CILLexer lexer = new(inputSource);
PreprocessedTokenSource preprocessor = new(lexer, path =>
{
var includedDocument = includedDocumentLoader(path);
var includedSource = new AntlrInputStream(includedDocument.Text)
{
name = includedDocument.Path
};
loadedDocuments[includedDocument.Path!] = includedDocument;
return new CILLexer(includedSource);
}, text => new CILLexer(new AntlrInputStream(text)), definedVariables);

ImmutableArray<Diagnostic>.Builder diagnostics = ImmutableArray.CreateBuilder<Diagnostic>();
preprocessor.OnPreprocessorSyntaxError += (source, start, length, msg) =>
{
diagnostics.Add(new Diagnostic("Preprocessor", DiagnosticSeverity.Error, msg, new Location(new(start, length), loadedDocuments[source])));
};
preprocessor.OnPreprocessorSyntaxError += (source, start, length, msg) =>
{
if (loadedDocuments.TryGetValue(source, out var sourceText))
{
diagnostics.Add(new Diagnostic("Preprocessor", DiagnosticSeverity.Error, msg, new Location(new(start, length), sourceText)));
}
else
{
diagnostics.Add(new Diagnostic("Preprocessor", DiagnosticSeverity.Error, msg, new Location(new(start, length), new SourceText("", source))));
}
};

CILParser parser = new(new CommonTokenStream(preprocessor));
parser.RemoveErrorListeners();
var parserDiagnostics = ImmutableArray.CreateBuilder<Diagnostic>();
parser.AddErrorListener(new ParserErrorListener(parserDiagnostics, loadedDocuments));
var result = parser.decls();

// Add parser diagnostics to the main list
diagnostics.AddRange(parserDiagnostics);

// Note: Parser must use the preprocessor token stream (not the raw lexer)
// to properly handle #include, #define, and other preprocessor directives.
CILParser parser = new(new CommonTokenStream(preprocessor));
var result = parser.decls();
GrammarVisitor visitor = new GrammarVisitor(loadedDocuments, options, resourceLocator);
_ = result.Accept(visitor);
visitor ??= new GrammarVisitor(loadedDocuments, options, resourceLocator);

_ = result.Accept(visitor);

// Transfer defined constants to the next document
definedVariables = preprocessor.DefinedVariables;
}

if (visitor is null)
{
return (diagnostics.ToImmutable(), null);
}

var image = visitor.BuildImage();

Expand All @@ -61,3 +92,29 @@ public sealed class DocumentCompiler
return (diagnostics.ToImmutable(), returnImage ? image.Image : null);
}
}

internal sealed class ParserErrorListener : Antlr4.Runtime.IAntlrErrorListener<IToken>
{
private readonly ImmutableArray<Diagnostic>.Builder _diagnostics;
private readonly Dictionary<string, SourceText> _loadedDocuments;

public ParserErrorListener(ImmutableArray<Diagnostic>.Builder diagnostics, Dictionary<string, SourceText> loadedDocuments)
{
_diagnostics = diagnostics;
_loadedDocuments = loadedDocuments;
}

public void SyntaxError(TextWriter output, IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
{
var sourceName = offendingSymbol?.TokenSource?.SourceName ?? "";
var span = new SourceSpan(offendingSymbol?.StartIndex ?? 0, offendingSymbol is null ? 0 : offendingSymbol.StopIndex - offendingSymbol.StartIndex + 1);
if (_loadedDocuments.TryGetValue(sourceName, out var sourceText))
{
_diagnostics.Add(new Diagnostic("Parser", DiagnosticSeverity.Error, $"line {line}:{charPositionInLine} {msg}", new Location(span, sourceText)));
}
else
{
_diagnostics.Add(new Diagnostic("Parser", DiagnosticSeverity.Error, $"line {line}:{charPositionInLine} {msg}", new Location(span, new SourceText("", sourceName))));
}
}
}
Loading