Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
8998bcd
Fix managed ilasm version defaults and module name fallback
jkoritzinsky Apr 17, 2026
1062377
Fix .module directive parsing order in ANTLR grammar
jkoritzinsky Apr 17, 2026
b78fcf3
Fix managed ilasm parser for hex byte blobs, native int, unsigned, ar…
jkoritzinsky Apr 17, 2026
22c51d4
Add native ilasm-style flag aliases (-DLL, -DET, -OUTPUT=, etc.)
jkoritzinsky Apr 18, 2026
2e0297e
Fix HEXBYTE token conflicts, prefix opcodes, array bounds, volatile f…
jkoritzinsky Apr 18, 2026
11786dd
Fix semantic failures: named locals/args, string escapes, floats, swi…
jkoritzinsky Apr 18, 2026
2e2467c
Fix 'il' impl attr, endfault instruction, ldc.i4.M1, and ? in identif…
jkoritzinsky Apr 18, 2026
4a9eb30
Fix preprocessor #define macro expansion to re-lex multi-token values
jkoritzinsky Apr 18, 2026
5424891
Support forward type references and fix ildasm crash known issues
jkoritzinsky Apr 18, 2026
dfaaea4
Fix metadata emission: MethodImpl, method body headers, EventMap/Prop…
jkoritzinsky Apr 18, 2026
24963e8
Fix semantic failures: enum cast, float literals, param type, propert…
jkoritzinsky Apr 18, 2026
c3355aa
Fix custom attribute array blob encoding index
jkoritzinsky Apr 18, 2026
8330d8a
Fix remaining edge cases: vararg, negative ints, wchar, abstract warning
jkoritzinsky Apr 18, 2026
e190709
Fix GenericParam sorting and method body error recovery
jkoritzinsky Apr 18, 2026
f10f7da
Fix forward-referenced type generic params, NullRef, switch(), hex, d…
jkoritzinsky Apr 18, 2026
0c23fd5
Fix array bounds parsing by requiring fractional digits in FLOAT64
jkoritzinsky Apr 18, 2026
35b9874
Two-pass generic param parsing, refany, Int64.MinValue, 128-bit hex
jkoritzinsky Apr 18, 2026
80e1145
Fix last 4 single-file failures: switch(), 65K params, resource ref
jkoritzinsky Apr 19, 2026
839dce4
Report error diagnostic for generic parameter count exceeding limit. …
jkoritzinsky Apr 20, 2026
cadbd9b
Update test name
jkoritzinsky Apr 20, 2026
deeda76
Multi-document compilation with preprocessor state transfer
jkoritzinsky Apr 20, 2026
d6a1fc5
Use collection expressions
jkoritzinsky Apr 20, 2026
2502490
Fix empty document parsing and eventAttr Aggregate on empty sequence
jkoritzinsky Apr 20, 2026
bd7709c
Fix duplicate locals, SQSTRING id quotes, and empty eventAttr
jkoritzinsky Apr 20, 2026
67a2a89
Remove multi-file #define known issue (fixed)
jkoritzinsky Apr 20, 2026
f1ba03b
Fix class visibility, hexbyte encoding, SQSTRING quoting, classAttr h…
jkoritzinsky Apr 20, 2026
b4ad818
Fix rtspecialname on methods/fields, interface implicit base type
jkoritzinsky Apr 20, 2026
b47ce07
Fix custom attr on methods, type name dot prefix, mscorlib version
jkoritzinsky Apr 20, 2026
83d6f47
Fix namespace leading dot, [in] param emission, field/extends cascading
jkoritzinsky Apr 20, 2026
f5cb7e8
Resolve MemberReferences to local MethodDef and FieldDef tokens
jkoritzinsky Apr 20, 2026
156c43a
Fix vararg MemberRef parameter count and parent resolution
jkoritzinsky Apr 20, 2026
2db4d71
Fix field constants, stackreserve, param naming, and specialname
jkoritzinsky Apr 21, 2026
f0c0d98
Fix pinvoke, leading-dot names, and NameHelpers splitting
jkoritzinsky Apr 21, 2026
043fc73
Use primitive type codes for well-known corelib types in signatures
jkoritzinsky Apr 21, 2026
e015f01
Add ANTLR parser error listener for diagnostic reporting
jkoritzinsky Apr 21, 2026
48838c4
Fix grammar rules to eliminate parser diagnostics
jkoritzinsky Apr 21, 2026
8d51381
Redirect corelib TypeRefs and resolve unqualified well-known types
jkoritzinsky Apr 21, 2026
5d3a557
Fix custom attribute emission on types and blob prolog size
jkoritzinsky Apr 21, 2026
f393a89
Fix custom attributes at top-level decl scope
jkoritzinsky Apr 21, 2026
3b6158c
Auto-add instance, specialname, and param names for compat
jkoritzinsky Apr 21, 2026
8d1c4e7
Set HasFieldRVA flag and add FieldRVA test
jkoritzinsky Apr 21, 2026
b61b726
Fix FieldRVA flag, top-level custom attr owner, and identify ildasm c…
jkoritzinsky Apr 21, 2026
730d0d1
Fix GenericParamConstraint sorting and defer DebuggableAttribute
jkoritzinsky Apr 21, 2026
d6e8b1c
Fix security attribute blob type name and ildasm crash
jkoritzinsky Apr 21, 2026
f99aa2c
Fix array shape encoding in multi-dimensional array signatures
jkoritzinsky Apr 21, 2026
e2d63d9
Fix function pointer syntax failures by writing to a separate blob (a…
jkoritzinsky Apr 21, 2026
014655f
Fix assigning generic parameters/generic parameter constraints the co…
jkoritzinsky Apr 21, 2026
d268232
Resolve TypeRef to TypeDef for local types in managed ilasm
jkoritzinsky Apr 21, 2026
57ef60b
Fix modopt/modreq signature rewriting and ClassLayout emission
jkoritzinsky Apr 21, 2026
01ee48b
Add TypeRef IL token backpatching and tests
jkoritzinsky Apr 21, 2026
8e45f33
Fix IL body corruption at BlobBuilder chunk boundary
jkoritzinsky Apr 22, 2026
37cb10b
Fix GetArrayType to emit ELEMENT_TYPE_ARRAY prefix in signature rewriter
jkoritzinsky Apr 22, 2026
1f5fef7
Build locals standalone signature from parsed .locals declarations
jkoritzinsky Apr 22, 2026
f7428c7
Defer exception region registration to emission for TypeRef resolution
jkoritzinsky Apr 22, 2026
fc4701e
Address PR feedback: fix generated paths, span length, NamedElementLi…
jkoritzinsky Apr 23, 2026
e65a6e5
Address PR feedback: fallback body headers, hexbyte validation, macro…
jkoritzinsky Apr 23, 2026
a3ea0bd
Fix custom attributes on properties and events being silently dropped
jkoritzinsky Apr 24, 2026
fbc4c53
Address Copilot review: MethodSpec header, array shape, CLI aliases, …
jkoritzinsky Apr 24, 2026
4705601
Align FieldMarshal row emission with HasFieldMarshal flag condition
jkoritzinsky Apr 24, 2026
6f69949
Update src/tools/ilasm/src/ILAssembler/DocumentCompiler.cs
jkoritzinsky Apr 24, 2026
18d7efe
ilasm: emit all TypeRef rows even when resolved to local TypeDefs
jkoritzinsky Jul 20, 2026
90b34ad
Cover other atOpt branch
jkoritzinsky Jul 22, 2026
1c90b75
Split ILAssembler DocumentCompiler tests
jkoritzinsky Jul 24, 2026
84a4cc3
Use BinaryPrimitives.Read*LittleEndian instead of BitConverter.To* in…
Copilot Jul 29, 2026
ebfccb0
Update KNOWN-ISSUES.md for features not validated in the round-trip s…
jkoritzinsky Jul 29, 2026
788b043
Remove space-delimited .language support and update tests
jkoritzinsky Jul 29, 2026
d305443
Enable publishing test results from managed ilasm to AzDO
jkoritzinsky Jul 29, 2026
c64e654
Support native ilasm option syntax
jkoritzinsky Jul 30, 2026
3687b98
Enable managed ilasm round trip testing.
jkoritzinsky Jul 27, 2026
c5f9784
Address ilasm command line review feedback
jkoritzinsky Aug 14, 2026
5971486
Remove unused usings to make copilot happy
jkoritzinsky Aug 24, 2026
3d5b332
Fix nested ilasm macro expansion
jkoritzinsky Aug 24, 2026
aabdfd1
Validate attached short ilasm option values
jkoritzinsky Aug 25, 2026
0012cf1
Fix deterministic managed ilasm output
jkoritzinsky Aug 25, 2026
2597421
Fix managed ilasm round-trip failures
jkoritzinsky Aug 26, 2026
e072112
Fix managed ilasm PE characteristics
jkoritzinsky Aug 26, 2026
2e4c59e
Harden legacy ilasm option parsing
jkoritzinsky Aug 26, 2026
ad9928c
Change weird test name case
jkoritzinsky Aug 26, 2026
3c629dd
Turn off round-trip so we can get this green
jkoritzinsky Sep 3, 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
2 changes: 2 additions & 0 deletions eng/pipelines/coreclr/ilasm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ extends:
nameSuffix: ILAsm
buildArgs: -s tools.ilasm -c $(_BuildConfig) -test
timeoutInMinutes: 120
enablePublishTestResults: true
testResultsFormat: 'xunit'
condition: and(succeeded(), ne(variables['Build.Reason'], 'Schedule'))
26 changes: 26 additions & 0 deletions src/tools/ilasm/KNOWN-ISSUES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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.

## Win32 resources

Embedding Win32 resources (in either `.obj` or `.res` format) is not
supported by managed ilasm.

## -MSV is not supported

Overriding the metadata stream version with `-MSV` is not supported by
managed ilasm.

## -OPTIMIZE is a no-op

Currently managed ilasm does not do any optimizations of the IL written by the user.

## -FOLD is a no-op

Currently managed ilasm does not fold identical IL bodies from different methods into the same blob.
9 changes: 5 additions & 4 deletions src/tools/ilasm/src/ILAssembler/BlobBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;

namespace ILAssembler
{
Expand Down Expand Up @@ -85,7 +82,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
34 changes: 34 additions & 0 deletions src/tools/ilasm/src/ILAssembler/CompilationResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;

namespace ILAssembler;

/// <summary>Represents a compiled portable executable image.</summary>
public sealed class CompilationResult
{
private readonly PEBuilder _peBuilder;
private readonly Blob _mvidFixup;

internal CompilationResult(PEBuilder peBuilder, Blob mvidFixup)
{
_peBuilder = peBuilder;
_mvidFixup = mvidFixup;
}

/// <summary>Serializes the compiled image into the specified builder.</summary>
/// <param name="builder">The builder that receives the serialized image.</param>
/// <returns>The content identifier of the serialized image.</returns>
public BlobContentId Serialize(BlobBuilder builder)
{
BlobContentId contentId = _peBuilder.Serialize(builder);
if (!_mvidFixup.IsDefault)
{
new BlobWriter(_mvidFixup).WriteGuid(contentId.Guid);
}

return contentId;
}
}
6 changes: 4 additions & 2 deletions src/tools/ilasm/src/ILAssembler/Diagnostic.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Immutable;

namespace ILAssembler;

public enum DiagnosticSeverity
Expand Down Expand Up @@ -52,6 +50,8 @@ public static class DiagnosticIds
public const string DuplicateMethod = "ILA0030";
public const string MissingExportedTypeImplementation = "ILA0031";
public const string KeyFileError = "ILA0032";
public const string TooManyGenericParameters = "ILA0033";
public const string UnsupportedTlsData = "ILA0034";
}

internal static class DiagnosticMessageTemplates
Expand Down Expand Up @@ -87,4 +87,6 @@ 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}";
public const string UnsupportedTlsData = "TLS RVA data declarations are not supported";
}
116 changes: 85 additions & 31 deletions src/tools/ilasm/src/ILAssembler/DocumentCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,77 @@
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using Antlr4.Runtime;

namespace ILAssembler;
public sealed class DocumentCompiler
{
public (ImmutableArray<Diagnostic>, PEBuilder?) Compile(SourceText document, Func<string, SourceText> includedDocumentLoader, Func<string, byte[]> resourceLocator, Options options)
public (ImmutableArray<Diagnostic>, CompilationResult?) 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>, CompilationResult?) 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 +89,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
Loading