internal CompilationVerifier CompileAndVerify( string[] sources, IEnumerable<MetadataReference> additionalRefs = null, IEnumerable<ModuleData> dependencies = null, Action<IModuleSymbol> sourceSymbolValidator = null, Action<PEAssembly> assemblyValidator = null, Action<IModuleSymbol> symbolValidator = null, SignatureDescription[] expectedSignatures = null, string expectedOutput = null, CompilationOptions options = null, ParseOptions parseOptions = null, EmitOptions emitOptions = null, bool verify = true) { if (options == null) { options = CompilationOptionsReleaseDll.WithOutputKind((expectedOutput != null) ? OutputKind.ConsoleApplication : OutputKind.DynamicallyLinkedLibrary); } var compilation = GetCompilationForEmit(sources, additionalRefs, options, parseOptions); return this.CompileAndVerify( compilation, null, dependencies, sourceSymbolValidator, assemblyValidator, symbolValidator, expectedSignatures, expectedOutput, emitOptions, verify); }
internal CompilationVerifier CompileAndVerify( string source, IEnumerable<MetadataReference> additionalRefs = null, IEnumerable<ModuleData> dependencies = null, Action<IModuleSymbol> sourceSymbolValidator = null, Action<PEAssembly> assemblyValidator = null, Action<IModuleSymbol> symbolValidator = null, SignatureDescription[] expectedSignatures = null, string expectedOutput = null, CompilationOptions options = null, ParseOptions parseOptions = null, EmitOptions emitOptions = null, bool verify = true) { return CompileAndVerify( sources: new string[] { source }, additionalRefs: additionalRefs, dependencies: dependencies, sourceSymbolValidator: sourceSymbolValidator, assemblyValidator: assemblyValidator, symbolValidator: symbolValidator, expectedSignatures: expectedSignatures, expectedOutput: expectedOutput, options: options, parseOptions: parseOptions, emitOptions: emitOptions, verify: verify); }
public EEAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, ImmutableArray<MethodSymbol> methods, ModulePropertiesForSerialization serializationProperties, ImmutableArray<NamedTypeSymbol> additionalTypes, NamedTypeSymbol dynamicOperationContextType, CompilationTestData testData) : base( sourceAssembly, emitOptions, outputKind: OutputKind.DynamicallyLinkedLibrary, serializationProperties: serializationProperties, manifestResources: SpecializedCollections.EmptyEnumerable<ResourceDescription>(), additionalTypes: additionalTypes) { Methods = ImmutableHashSet.CreateRange(methods); _dynamicOperationContextType = dynamicOperationContextType; if (testData != null) { this.SetMethodTestData(testData.Methods); testData.Module = this; } }
private CompilationVerifier CompileAndVerify(string source, string expectedOutput, IEnumerable<MetadataReference> references = null, EmitOptions emitOptions = EmitOptions.All, CSharpCompilationOptions compOptions = null) { SynchronizationContext.SetSynchronizationContext(null); var compilation = this.CreateCompilation(source, references: references, compOptions: compOptions); return base.CompileAndVerify(compilation, expectedOutput: expectedOutput, emitOptions: emitOptions); }
internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); MemoryStream pdbStream = (compilation.Options.OptimizationLevel == OptimizationLevel.Debug) && !CLRHelpers.IsRunningOnMono() ? new MemoryStream() : null; var emitResult = compilation.Emit( peStream: stream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: null, options: options, testData: testData, getHostDiagnostics: null, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return stream.ToImmutable(); }
internal PENetModuleBuilder( SourceModuleSymbol sourceModule, EmitOptions emitOptions, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources) : base(sourceModule, emitOptions, OutputKind.NetModule, serializationProperties, manifestResources) { }
internal PENetModuleBuilder( PhpCompilation compilation, IModuleSymbol sourceModule, EmitOptions emitOptions, Microsoft.Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources) : base(compilation, (Symbols.SourceModuleSymbol)sourceModule, serializationProperties, manifestResources, OutputKind.NetModule, emitOptions) { }
public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources, EmitBaseline previousGeneration, IEnumerable<SemanticEdit> edits, Func<ISymbol, bool> isAddedSymbol) : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, additionalTypes: ImmutableArray<NamedTypeSymbol>.Empty) { var initialBaseline = previousGeneration.InitialBaseline; var context = new EmitContext(this, null, new DiagnosticBag()); // Hydrate symbols from initial metadata. Once we do so it is important to reuse these symbols across all generations, // in order for the symbol matcher to be able to use reference equality once it maps symbols to initial metadata. var metadataSymbols = GetOrCreateMetadataSymbols(initialBaseline, sourceAssembly.DeclaringCompilation); var metadataDecoder = (MetadataDecoder)metadataSymbols.MetadataDecoder; var metadataAssembly = (PEAssemblySymbol)metadataDecoder.ModuleSymbol.ContainingAssembly; var matchToMetadata = new CSharpSymbolMatcher(metadataSymbols.AnonymousTypes, sourceAssembly, context, metadataAssembly); CSharpSymbolMatcher matchToPrevious = null; if (previousGeneration.Ordinal > 0) { var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var previousContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()); matchToPrevious = new CSharpSymbolMatcher( previousGeneration.AnonymousTypeMap, sourceAssembly: sourceAssembly, sourceContext: context, otherAssembly: previousAssembly, otherContext: previousContext, otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers); } _previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious); _previousGeneration = previousGeneration; _changes = new SymbolChanges(_previousDefinitions, edits, isAddedSymbol); // Workaround for https://github.com/dotnet/roslyn/issues/3192. // When compiling state machine we stash types of awaiters and state-machine hoisted variables, // so that next generation can look variables up and reuse their slots if possible. // // When we are about to allocate a slot for a lifted variable while compiling the next generation // we map its type to the previous generation and then check the slot types that we stashed earlier. // If the variable type matches we reuse it. In order to compare the previous variable type with the current one // both need to be completely lowered (translated). Standard translation only goes one level deep. // Generic arguments are not translated until they are needed by metadata writer. // // In order to get the fully lowered form we run the type symbols of stashed variables thru a deep translator // that translates the symbol recursively. _deepTranslator = new CSharpSymbolMatcher.DeepTranslator(sourceAssembly.GetSpecialType(SpecialType.System_Object)); }
public PEAssemblyBuilder( SourceAssemblySymbol sourceAssembly, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources, OutputKind outputKind, EmitOptions emitOptions) :base(sourceAssembly.DeclaringCompilation, (SourceModuleSymbol)sourceAssembly.Modules[0], serializationProperties, manifestResources, outputKind, emitOptions) { _sourceAssembly = sourceAssembly; _metadataName = (emitOptions.OutputNameOverride == null) ? sourceAssembly.MetadataName : FileNameUtilities.ChangeExtension(emitOptions.OutputNameOverride, extension: null); AssemblyOrModuleSymbolToModuleRefMap.Add(sourceAssembly, this); }
public static MemoryStream EmitToStream(this Compilation compilation, EmitOptions options = null, DiagnosticDescription[] expectedWarnings = null) { var stream = new MemoryStream(); var emitResult = compilation.Emit(stream, options: options); Assert.True(emitResult.Success, "Diagnostics: " + string.Join(", ", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } stream.Position = 0; return stream; }
public static MetadataReference EmitToImageReference( this Compilation comp, EmitOptions options = null, bool embedInteropTypes = false, ImmutableArray<string> aliases = default(ImmutableArray<string>), DiagnosticDescription[] expectedWarnings = null) { var image = comp.EmitToArray(options, expectedWarnings: expectedWarnings); if (comp.Options.OutputKind == OutputKind.NetModule) { return ModuleMetadata.CreateFromImage(image).GetReference(display: comp.MakeSourceModuleName()); } else { return AssemblyMetadata.CreateFromImage(image).GetReference(aliases: aliases, embedInteropTypes: embedInteropTypes, display: comp.MakeSourceAssemblySimpleName()); } }
public PEAssemblyBuilderBase( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources, ImmutableArray<NamedTypeSymbol> additionalTypes) : base((SourceModuleSymbol)sourceAssembly.Modules[0], emitOptions, outputKind, serializationProperties, manifestResources) { Debug.Assert((object)sourceAssembly != null); _sourceAssembly = sourceAssembly; _additionalTypes = additionalTypes.NullToEmpty(); _metadataName = (emitOptions.OutputNameOverride == null) ? sourceAssembly.MetadataName : FileNameUtilities.ChangeExtension(emitOptions.OutputNameOverride, extension: null); AssemblyOrModuleSymbolToModuleRefMap.Add(sourceAssembly, this); }
internal static ImmutableArray<byte> EmitToArray( this Compilation compilation, EmitOptions options = null, CompilationTestData testData = null, DiagnosticDescription[] expectedWarnings = null, Stream pdbStream = null, IMethodSymbol debugEntryPoint = null, Stream sourceLinkStream = null, IEnumerable<EmbeddedText> embeddedTexts = null) { var peStream = new MemoryStream(); if (pdbStream == null && compilation.Options.OptimizationLevel == OptimizationLevel.Debug && options?.DebugInformationFormat != DebugInformationFormat.Embedded) { if (MonoHelpers.IsRunningOnMono()) { options = (options ?? EmitOptions.Default).WithDebugInformationFormat(DebugInformationFormat.PortablePdb); } pdbStream = new MemoryStream(); } var emitResult = compilation.Emit( peStream: peStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: null, options: options, debugEntryPoint: debugEntryPoint, sourceLinkStream: sourceLinkStream, embeddedTexts: embeddedTexts, testData: testData, cancellationToken: default(CancellationToken)); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString()))); if (expectedWarnings != null) { emitResult.Diagnostics.Verify(expectedWarnings); } return peStream.ToImmutable(); }
protected override Assembly Load(AssemblyName assemblyName) { Assembly assembly; if (_assemblies.TryGetValue(assemblyName.Name, out assembly)) { return assembly; } try { System.Console.WriteLine($"Load({assemblyName})"); ProjectId projectId; if (_projects.TryGetValue(assemblyName.Name, out projectId)) { var project = _workspace.CurrentSolution.GetProject(projectId); System.Console.WriteLine($"Found project {project.AssemblyName}({(project.Id)})"); using (var assemblySymbols = new MemoryStream()) using (var assemblyStream = new MemoryStream()) { var emitOptions = new EmitOptions().WithDebugInformationFormat(DebugInformationFormat.PortablePdb); var compilation = project.GetCompilationAsync().GetAwaiter().GetResult(); var emitResult = compilation.Emit(assemblyStream, assemblySymbols, options: emitOptions); if (emitResult.Success) { assemblyStream.Position = 0; assemblySymbols.Position = 0; return LoadFromStream(assemblyStream, assemblySymbols); } } } } catch { return Default.LoadFromAssemblyName(assemblyName); } return null; }
public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources, EmitBaseline previousGeneration, IEnumerable<SemanticEdit> edits, Func<ISymbol, bool> isAddedSymbol) : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, assemblySymbolMapper: null, additionalTypes: ImmutableArray<NamedTypeSymbol>.Empty) { var context = new EmitContext(this, null, new DiagnosticBag()); var module = previousGeneration.OriginalMetadata; var compilation = sourceAssembly.DeclaringCompilation; var metadataAssembly = compilation.GetBoundReferenceManager().CreatePEAssemblyForAssemblyMetadata(AssemblyMetadata.Create(module), MetadataImportOptions.All); var metadataDecoder = new Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.MetadataDecoder(metadataAssembly.PrimaryModule); previousGeneration = EnsureInitialized(previousGeneration, metadataDecoder); var matchToMetadata = new CSharpSymbolMatcher(previousGeneration.AnonymousTypeMap, sourceAssembly, context, metadataAssembly); CSharpSymbolMatcher matchToPrevious = null; if (previousGeneration.Ordinal > 0) { var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var previousContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()); matchToPrevious = new CSharpSymbolMatcher( previousGeneration.AnonymousTypeMap, sourceAssembly: sourceAssembly, sourceContext: context, otherAssembly: previousAssembly, otherContext: previousContext, otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers); } _previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious); _previousGeneration = previousGeneration; _changes = new SymbolChanges(_previousDefinitions, edits, isAddedSymbol); }
protected PEModuleBuilder( PhpCompilation compilation, SourceModuleSymbol sourceModule, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources, OutputKind outputKind, EmitOptions emitOptions) { Debug.Assert(sourceModule != null); Debug.Assert(serializationProperties != null); _compilation = compilation; _sourceModule = sourceModule; _serializationProperties = serializationProperties; this.ManifestResources = manifestResources; _outputKind = outputKind; _emitOptions = emitOptions; this.CompilationState = new CommonModuleCompilationState(); _debugDocuments = new ConcurrentDictionary<string, Cci.DebugSourceDocument>(compilation.IsCaseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); _synthesized = new SynthesizedManager(this); AssemblyOrModuleSymbolToModuleRefMap.Add(sourceModule, this); }
public static EmitResult EmitWithMdb(this Compilation compilation, Stream peStream, Stream pdbStream = null, Stream xmlDocumentationStream = null, Stream win32Resources = null, IEnumerable<ResourceDescription> manifestResources = null, EmitOptions options = null, IMethodSymbol debugEntryPoint = null, CancellationToken cancellationToken = default(CancellationToken)) { if (peStream == null) { throw new ArgumentNullException(nameof(peStream)); } if (!peStream.CanWrite) { throw new ArgumentException(CodeAnalysisResources.StreamMustSupportWrite, nameof(peStream)); } if (pdbStream != null && !pdbStream.CanWrite) { throw new ArgumentException(CodeAnalysisResources.StreamMustSupportWrite, nameof(pdbStream)); } var testData = new CompilationTestData { SymWriterFactory = () => new MdbWriter() }; return compilation.Emit( peStream, pdbStream, xmlDocumentationStream, win32Resources, manifestResources, options, debugEntryPoint, testData, null, cancellationToken); }
public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> manifestResources, EmitOptions emitOptions, bool usePdbForDebugging = false) { _testData.Methods.Clear(); var diagnostics = DiagnosticBag.GetInstance(); var dependencies = new List<ModuleData>(); var mainOutput = RuntimeUtilities.EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, _testData, emitOptions); if (mainOutput.HasValue) { _diagnostics = diagnostics.ToReadOnly(); _mainImage = mainOutput.Value.Assembly; _pdb = mainOutput.Value.Pdb; } else { _mainImage = default(ImmutableArray<byte>); _pdb = default(ImmutableArray<byte>); _diagnostics = default(ImmutableArray<Diagnostic>); string dumpDir; DumpAssemblyData(dependencies, out dumpDir); throw new EmitException(diagnostics.ToReadOnly(), dumpDir); } }
public CompilerInstruction(Compiler compiler, InstructionCode code, Operand[] operands) : base(compiler) { Contract.Requires(compiler != null); Contract.Requires(operands != null); _code = code; _emitOptions = compiler.EmitOptions; // Each created instruction takes emit options and clears it. compiler.EmitOptions = EmitOptions.None; _operands = operands; _memoryOperand = null; _variables = null; for (int i = 0; i < operands.Length; i++) { if (operands[i].IsMem) { _memoryOperand = (Mem)operands[i]; break; } } InstructionDescription id = InstructionDescription.FromInstruction(_code); _isSpecial = id.IsSpecial; _isFPU = id.IsFPU; _isGPBHiUsed = false; _isGPBLoUsed = false; if (_isSpecial) { // ${SPECIAL_INSTRUCTION_HANDLING_BEGIN} switch (_code) { case InstructionCode.Cpuid: // Special... break; case InstructionCode.Cbw: case InstructionCode.Cdqe: case InstructionCode.Cwde: // Special... break; case InstructionCode.Cdq: case InstructionCode.Cqo: case InstructionCode.Cwd: // Special... break; case InstructionCode.Cmpxchg: case InstructionCode.Cmpxchg8b: case InstructionCode.Cmpxchg16b: // Special... if (_code == InstructionCode.Cmpxchg16b && !Util.IsX64) throw new NotSupportedException(string.Format("The '{0}' instruction is only supported on X64.", _code)); break; case InstructionCode.Daa: case InstructionCode.Das: // Special... if (!Util.IsX86) throw new NotSupportedException(string.Format("The '{0}' instruction is only supported on X86.", _code)); break; case InstructionCode.Imul: switch (operands.Length) { case 2: // IMUL dst, src is not special instruction. _isSpecial = false; break; case 3: if (!(_operands[0].IsVar && _operands[1].IsVar && _operands[2].IsVarMem)) { // Only IMUL dst_hi, dst_lo, reg/mem is special, all others don't. _isSpecial = false; } break; } break; case InstructionCode.Mul: case InstructionCode.Idiv: case InstructionCode.Div: // Special... break; case InstructionCode.MovPtr: // Special... break; case InstructionCode.Lahf: case InstructionCode.Sahf: // Special... break; case InstructionCode.Maskmovdqu: case InstructionCode.Maskmovq: // Special... break; case InstructionCode.Enter: case InstructionCode.Leave: // Special... break; case InstructionCode.Ret: // Special... break; case InstructionCode.Monitor: case InstructionCode.Mwait: // Special... break; case InstructionCode.Pop: case InstructionCode.Popad: case InstructionCode.Popfd: case InstructionCode.Popfq: // Special... break; case InstructionCode.Push: case InstructionCode.Pushad: case InstructionCode.Pushfd: case InstructionCode.Pushfq: // Special... break; case InstructionCode.Rcl: case InstructionCode.Rcr: case InstructionCode.Rol: case InstructionCode.Ror: case InstructionCode.Sal: case InstructionCode.Sar: case InstructionCode.Shl: case InstructionCode.Shr: // Rot instruction is special only if last operand is variable (register). _isSpecial = _operands[1].IsVar; break; case InstructionCode.Shld: case InstructionCode.Shrd: // Shld/Shrd instruction is special only if last operand is variable (register). _isSpecial = _operands[2].IsVar; break; case InstructionCode.Rdtsc: case InstructionCode.Rdtscp: // Special... break; case InstructionCode.RepLodsb: case InstructionCode.RepLodsd: case InstructionCode.RepLodsq: case InstructionCode.RepLodsw: case InstructionCode.RepMovsb: case InstructionCode.RepMovsd: case InstructionCode.RepMovsq: case InstructionCode.RepMovsw: case InstructionCode.RepStosb: case InstructionCode.RepStosd: case InstructionCode.RepStosq: case InstructionCode.RepStosw: case InstructionCode.RepeCmpsb: case InstructionCode.RepeCmpsd: case InstructionCode.RepeCmpsq: case InstructionCode.RepeCmpsw: case InstructionCode.RepeScasb: case InstructionCode.RepeScasd: case InstructionCode.RepeScasq: case InstructionCode.RepeScasw: case InstructionCode.RepneCmpsb: case InstructionCode.RepneCmpsd: case InstructionCode.RepneCmpsq: case InstructionCode.RepneCmpsw: case InstructionCode.RepneScasb: case InstructionCode.RepneScasd: case InstructionCode.RepneScasq: case InstructionCode.RepneScasw: // Special... break; default: throw new CompilerException("Instruction is marked as special but handling for it is not present."); } // ${SPECIAL_INSTRUCTION_HANDLING_END} } }
public void PlatformMismatch_08() { var emitOptions = new EmitOptions(runtimeMetadataVersion: "v1234"); string refSource = @" public interface ITestPlatform {} "; var refCompilation = CreateCompilation(refSource, options: TestOptions.ReleaseModule.WithPlatform(Platform.Itanium), assemblyName: "PlatformMismatch"); refCompilation.VerifyEmitDiagnostics(emitOptions); var imageRef = refCompilation.EmitToImageReference(); string useSource = @" public interface IUsePlatform { ITestPlatform M(); } "; var useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions); }
public void PlatformMismatch_04() { var emitOptions = new EmitOptions(runtimeMetadataVersion: "v1234"); string refSource = @" public interface ITestPlatform {} "; var refCompilation = CreateCompilation(refSource, options: TestOptions.ReleaseModule.WithPlatform(Platform.X86), assemblyName: "PlatformMismatch"); refCompilation.VerifyEmitDiagnostics(emitOptions); var imageRef = refCompilation.EmitToImageReference(); string useSource = @" public interface IUsePlatform { ITestPlatform M(); } "; var useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions, // error CS8011: Assembly and module 'PlatformMismatch.netmodule' cannot target different processors. Diagnostic(ErrorCode.ERR_ConflictingMachineModule).WithArguments("PlatformMismatch.netmodule")); }
public void PlatformMismatch_03() { var emitOptions = new EmitOptions(runtimeMetadataVersion: "v1234"); string refSource = @" public interface ITestPlatform {} "; var refCompilation = CreateCompilation(refSource, options: TestOptions.ReleaseDll.WithPlatform(Platform.X86), assemblyName: "PlatformMismatch"); refCompilation.VerifyEmitDiagnostics(emitOptions); var compRef = new CSharpCompilationReference(refCompilation); var imageRef = refCompilation.EmitToImageReference(); string useSource = @" public interface IUsePlatform { ITestPlatform M(); } "; var useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.Itanium)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); }
public void PlatformMismatch_01() { var emitOptions = new EmitOptions(runtimeMetadataVersion: "v1234"); string refSource = @" public interface ITestPlatform {} "; var refCompilation = CreateCompilation(refSource, options: TestOptions.ReleaseDll.WithPlatform(Platform.Itanium), assemblyName: "PlatformMismatch"); refCompilation.VerifyEmitDiagnostics(emitOptions); var compRef = new CSharpCompilationReference(refCompilation); var imageRef = refCompilation.EmitToImageReference(); string useSource = @" public interface IUsePlatform { ITestPlatform M(); } "; var useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.AnyCpu)); useCompilation.VerifyEmitDiagnostics(emitOptions); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.AnyCpu)); useCompilation.VerifyEmitDiagnostics(emitOptions); useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.AnyCpu)); useCompilation.VerifyEmitDiagnostics(emitOptions); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.AnyCpu)); useCompilation.VerifyEmitDiagnostics(emitOptions); useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.X86)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseDll.WithPlatform(Platform.X86)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { compRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.X86)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); useCompilation = CreateCompilation(useSource, new MetadataReference[] { imageRef }, options: TestOptions.ReleaseModule.WithPlatform(Platform.X86)); useCompilation.VerifyEmitDiagnostics(emitOptions, // warning CS8012: Referenced assembly 'PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor. Diagnostic(ErrorCode.WRN_ConflictingMachineAssembly).WithArguments("PlatformMismatch, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")); // Confirm that suppressing the old alink warning 1607 shuts off WRN_ConflictingMachineAssembly var warnings = new System.Collections.Generic.Dictionary<string, ReportDiagnostic>(); warnings.Add(MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_ALinkWarn), ReportDiagnostic.Suppress); useCompilation = useCompilation.WithOptions(useCompilation.Options.WithSpecificDiagnosticOptions(warnings)); useCompilation.VerifyEmitDiagnostics(emitOptions); }
private static EEAssemblyBuilder CreateModuleBuilder( CSharpCompilation compilation, ImmutableArray<MethodSymbol> methods, ImmutableArray<NamedTypeSymbol> additionalTypes, EENamedTypeSymbol synthesizedType, Microsoft.CodeAnalysis.CodeGen.CompilationTestData testData, DiagnosticBag diagnostics) { // Each assembly must have a unique name. var emitOptions = new EmitOptions(outputNameOverride: ExpressionCompilerUtilities.GenerateUniqueName()); var dynamicOperationContextType = GetNonDisplayClassContainer(synthesizedType.SubstitutedSourceType); string runtimeMetadataVersion = compilation.GetRuntimeMetadataVersion(emitOptions, diagnostics); var serializationProperties = compilation.ConstructModuleSerializationProperties(emitOptions, runtimeMetadataVersion); return new EEAssemblyBuilder(compilation.SourceAssembly, emitOptions, methods, serializationProperties, additionalTypes, dynamicOperationContextType, testData); }
internal static EmitOutput? EmitCompilationCore( Compilation compilation, IEnumerable<ResourceDescription> manifestResources, DiagnosticBag diagnostics, CompilationTestData testData, EmitOptions emitOptions ) { using (var executableStream = new MemoryStream()) { var pdb = default(ImmutableArray<byte>); var assembly = default(ImmutableArray<byte>); var pdbStream = MonoHelpers.IsRunningOnMono() ? null : new MemoryStream(); EmitResult result; try { result = compilation.Emit( executableStream, pdbStream: pdbStream, xmlDocumentationStream: null, win32Resources: null, manifestResources: manifestResources, options: emitOptions ?? EmitOptions.Default, debugEntryPoint: null, sourceLinkStream: null, testData: testData, cancellationToken: default(CancellationToken)); } finally { if (pdbStream != null) { pdb = pdbStream.ToImmutable(); pdbStream.Dispose(); } } diagnostics.AddRange(result.Diagnostics); assembly = executableStream.ToImmutable(); if (result.Success) { return new EmitOutput(assembly, pdb); } return null; } }
public void EmitOptionsDiagnostics() { var c = CreateCompilationWithMscorlib("class C {}"); var stream = new MemoryStream(); var options = new EmitOptions( debugInformationFormat: (DebugInformationFormat)(-1), outputNameOverride: " ", fileAlignment: 513, subsystemVersion: SubsystemVersion.Create(1000000, -1000000)); EmitResult result = c.Emit(stream, options: options); result.Diagnostics.Verify( // error CS2042: Invalid debug information format: -1 Diagnostic(ErrorCode.ERR_InvalidDebugInformationFormat).WithArguments("-1"), // error CS2041: Invalid output name: Name cannot start with whitespace. Diagnostic(ErrorCode.ERR_InvalidOutputName).WithArguments(CodeAnalysisResources.NameCannotStartWithWhitespace), // error CS2024: Invalid file section alignment '513' Diagnostic(ErrorCode.ERR_InvalidFileAlignment).WithArguments("513"), // error CS1773: Invalid version 1000000.-1000000 for /subsystemversion. The version must be 6.02 or greater for ARM or AppContainerExe, and 4.00 or greater otherwise Diagnostic(ErrorCode.ERR_InvalidSubsystemVersion).WithArguments("1000000.-1000000")); Assert.False(result.Success); }
public PEAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable<ResourceDescription> manifestResources) : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, ImmutableArray<NamedTypeSymbol>.Empty) { }
public IDiagnosticResult EmitAssembly(string outputPath) { IList<ResourceDescription> resources = CompilationContext.Resources; var assemblyPath = Path.Combine(outputPath, Name + ".dll"); var pdbPath = Path.Combine(outputPath, Name + ".pdb"); var xmlDocPath = Path.Combine(outputPath, Name + ".xml"); // REVIEW: Memory bloat? using (var xmlDocStream = new MemoryStream()) using (var pdbStream = new MemoryStream()) using (var assemblyStream = new MemoryStream()) using (var win32resStream = CompilationContext.Compilation.CreateDefaultWin32Resources( versionResource: true, noManifest: false, manifestContents: null, iconInIcoFormat: null)) { // The default win32resStream extracted from compilation represents a Win32 applicaiton manifest. // It enables the assmebly information to be viewed in Windows Explorer. Logger.TraceInformation("[{0}]: Emitting assembly for {1}", GetType().Name, Name); var sw = Stopwatch.StartNew(); EmitResult emitResult = null; if (_supportsPdbGeneration.Value) { var options = new EmitOptions(pdbFilePath: pdbPath); emitResult = CompilationContext.Compilation.Emit( assemblyStream, pdbStream: pdbStream, xmlDocumentationStream: xmlDocStream, win32Resources: win32resStream, manifestResources: resources, options: options); } else { Logger.TraceWarning("PDB generation is not supported on this platform"); emitResult = CompilationContext.Compilation.Emit( assemblyStream, xmlDocumentationStream: xmlDocStream, manifestResources: resources, win32Resources: win32resStream); } sw.Stop(); Logger.TraceInformation("[{0}]: Emitted {1} in {2}ms", GetType().Name, Name, sw.ElapsedMilliseconds); var afterCompileContext = new AfterCompileContext(CompilationContext, emitResult.Diagnostics) { AssemblyStream = assemblyStream, SymbolStream = pdbStream, XmlDocStream = xmlDocStream }; foreach (var m in CompilationContext.Modules) { m.AfterCompile(afterCompileContext); } if (!emitResult.Success || afterCompileContext.Diagnostics.Any(RoslynDiagnosticUtilities.IsError)) { return CreateDiagnosticResult(emitResult.Success, afterCompileContext.Diagnostics); } // Ensure there's an output directory Directory.CreateDirectory(outputPath); if (afterCompileContext.AssemblyStream != null) { afterCompileContext.AssemblyStream.Position = 0; using (var assemblyFileStream = File.Create(assemblyPath)) { afterCompileContext.AssemblyStream.CopyTo(assemblyFileStream); } } if (afterCompileContext.XmlDocStream != null) { afterCompileContext.XmlDocStream.Position = 0; using (var xmlDocFileStream = File.Create(xmlDocPath)) { afterCompileContext.XmlDocStream.CopyTo(xmlDocFileStream); } } if (_supportsPdbGeneration.Value) { if (afterCompileContext.SymbolStream != null) { afterCompileContext.SymbolStream.Position = 0; using (var pdbFileStream = File.Create(pdbPath)) { afterCompileContext.SymbolStream.CopyTo(pdbFileStream); } } } return CreateDiagnosticResult(emitResult.Success, afterCompileContext.Diagnostics); } }
/// <summary> /// Parses a command line. /// </summary> /// <param name="args">A collection of strings representing the command line arguments.</param> /// <param name="baseDirectory">The base directory used for qualifying file locations.</param> /// <param name="sdkDirectory">The directory to search for mscorlib.</param> /// <param name="additionalReferenceDirectories">A string representing additional reference paths.</param> /// <returns>a commandlinearguments object representing the parsed command line.</returns> public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string baseDirectory, string sdkDirectory, string additionalReferenceDirectories = null) { List<Diagnostic> diagnostics = new List<Diagnostic>(); List<string> flattenedArgs = new List<string>(); List<string> scriptArgs = IsInteractive ? new List<string>() : null; FlattenArgs(args, diagnostics, flattenedArgs, scriptArgs, baseDirectory); string appConfigPath = null; bool displayLogo = true; bool displayHelp = false; bool optimize = false; bool checkOverflow = false; bool allowUnsafe = false; bool concurrentBuild = true; bool emitPdb = false; string pdbPath = null; bool noStdLib = false; string outputDirectory = baseDirectory; string outputFileName = null; string documentationPath = null; string errorLogPath = null; bool parseDocumentationComments = false; //Don't just null check documentationFileName because we want to do this even if the file name is invalid. bool utf8output = false; OutputKind outputKind = OutputKind.ConsoleApplication; SubsystemVersion subsystemVersion = SubsystemVersion.None; LanguageVersion languageVersion = CSharpParseOptions.Default.LanguageVersion; string mainTypeName = null; string win32ManifestFile = null; string win32ResourceFile = null; string win32IconFile = null; bool noWin32Manifest = false; Platform platform = Platform.AnyCpu; ulong baseAddress = 0; int fileAlignment = 0; bool? delaySignSetting = null; string keyFileSetting = null; string keyContainerSetting = null; List<ResourceDescription> managedResources = new List<ResourceDescription>(); List<CommandLineSourceFile> sourceFiles = new List<CommandLineSourceFile>(); List<CommandLineSourceFile> additionalFiles = new List<CommandLineSourceFile>(); bool sourceFilesSpecified = false; bool resourcesOrModulesSpecified = false; Encoding codepage = null; var checksumAlgorithm = SourceHashAlgorithm.Sha1; var defines = ArrayBuilder<string>.GetInstance(); List<CommandLineReference> metadataReferences = new List<CommandLineReference>(); List<CommandLineAnalyzerReference> analyzers = new List<CommandLineAnalyzerReference>(); List<string> libPaths = new List<string>(); List<string> keyFileSearchPaths = new List<string>(); List<string> usings = new List<string>(); var generalDiagnosticOption = ReportDiagnostic.Default; var diagnosticOptions = new Dictionary<string, ReportDiagnostic>(); var noWarns = new Dictionary<string, ReportDiagnostic>(); var warnAsErrors = new Dictionary<string, ReportDiagnostic>(); int warningLevel = 4; bool highEntropyVA = false; bool printFullPaths = false; string moduleAssemblyName = null; string moduleName = null; List<string> features = new List<string>(); string runtimeMetadataVersion = null; bool errorEndLocation = false; bool reportAnalyzer = false; CultureInfo preferredUILang = null; string touchedFilesPath = null; var sqmSessionGuid = Guid.Empty; // Process ruleset files first so that diagnostic severity settings specified on the command line via // /nowarn and /warnaserror can override diagnostic severity settings specified in the ruleset file. if (!IsInteractive) { foreach (string arg in flattenedArgs) { string name, value; if (TryParseOption(arg, out name, out value) && (name == "ruleset")) { var unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); } else { generalDiagnosticOption = GetDiagnosticOptionsFromRulesetFile(diagnosticOptions, diagnostics, unquoted, baseDirectory); } } } } foreach (string arg in flattenedArgs) { Debug.Assert(!arg.StartsWith("@", StringComparison.Ordinal)); string name, value; if (!TryParseOption(arg, out name, out value)) { sourceFiles.AddRange(ParseFileArgument(arg, baseDirectory, diagnostics)); sourceFilesSpecified = true; continue; } switch (name) { case "?": case "help": displayHelp = true; continue; case "r": case "reference": metadataReferences.AddRange(ParseAssemblyReferences(arg, value, diagnostics, embedInteropTypes: false)); continue; case "a": case "analyzer": analyzers.AddRange(ParseAnalyzers(arg, value, diagnostics)); continue; case "d": case "define": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", arg); continue; } IEnumerable<Diagnostic> defineDiagnostics; defines.AddRange(ParseConditionalCompilationSymbols(value, out defineDiagnostics)); diagnostics.AddRange(defineDiagnostics); continue; case "codepage": if (value == null) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); continue; } var encoding = TryParseEncodingName(value); if (encoding == null) { AddDiagnostic(diagnostics, ErrorCode.FTL_BadCodepage, value); continue; } codepage = encoding; continue; case "checksumalgorithm": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); continue; } var newChecksumAlgorithm = TryParseHashAlgorithmName(value); if (newChecksumAlgorithm == SourceHashAlgorithm.None) { AddDiagnostic(diagnostics, ErrorCode.FTL_BadChecksumAlgorithm, value); continue; } checksumAlgorithm = newChecksumAlgorithm; continue; case "checked": case "checked+": if (value != null) { break; } checkOverflow = true; continue; case "checked-": if (value != null) break; checkOverflow = false; continue; case "features": if (value == null) { features.Clear(); } else { features.Add(value); } continue; case "noconfig": // It is already handled (see CommonCommandLineCompiler.cs). continue; case "sqmsessionguid": if (value == null) { AddDiagnostic(diagnostics, ErrorCode.ERR_MissingGuidForOption, "<text>", name); } else { if (!Guid.TryParse(value, out sqmSessionGuid)) { AddDiagnostic(diagnostics, ErrorCode.ERR_InvalidFormatForGuidForOption, value, name); } } continue; case "preferreduilang": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", arg); continue; } try { preferredUILang = new CultureInfo(value); if (CorLightup.Desktop.IsUserCustomCulture(preferredUILang) ?? false) { // Do not use user custom cultures. preferredUILang = null; } } catch (CultureNotFoundException) { } if (preferredUILang == null) { AddDiagnostic(diagnostics, ErrorCode.WRN_BadUILang, value); } continue; #if DEBUG case "attachdebugger": Debugger.Launch(); continue; #endif } if (IsInteractive) { switch (name) { // interactive: case "rp": case "referencepath": // TODO: should it really go to libPaths? ParseAndResolveReferencePaths(name, value, baseDirectory, libPaths, MessageID.IDS_REFERENCEPATH_OPTION, diagnostics); continue; case "u": case "using": usings.AddRange(ParseUsings(arg, value, diagnostics)); continue; } } else { switch (name) { case "out": if (string.IsNullOrWhiteSpace(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); } else { ParseOutputFile(value, diagnostics, baseDirectory, out outputFileName, out outputDirectory); } continue; case "t": case "target": if (value == null) { break; // force 'unrecognized option' } if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.FTL_InvalidTarget); } else { outputKind = ParseTarget(value, diagnostics); } continue; case "moduleassemblyname": value = value != null ? value.Unquote() : null; if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", arg); } else if (!MetadataHelpers.IsValidAssemblyOrModuleName(value)) { // Dev11 C# doesn't check the name (VB does) AddDiagnostic(diagnostics, ErrorCode.ERR_InvalidAssemblyName, "<text>", arg); } else { moduleAssemblyName = value; } continue; case "modulename": var unquotedModuleName = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquotedModuleName)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "modulename"); continue; } else { moduleName = unquotedModuleName; } continue; case "platform": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<string>", arg); } else { platform = ParsePlatform(value, diagnostics); } continue; case "recurse": if (value == null) { break; // force 'unrecognized option' } else if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); } else { int before = sourceFiles.Count; sourceFiles.AddRange(ParseRecurseArgument(value, baseDirectory, diagnostics)); if (sourceFiles.Count > before) { sourceFilesSpecified = true; } } continue; case "doc": parseDocumentationComments = true; if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), arg); continue; } string unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { // CONSIDER: This diagnostic exactly matches dev11, but it would be simpler (and more consistent with /out) // if we just let the next case handle /doc:"". AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "/doc:"); // Different argument. } else { documentationPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory); } continue; case "addmodule": if (value == null) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "/addmodule:"); } else if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); } else { // NOTE(tomat): Dev10 used to report CS1541: ERR_CantIncludeDirectory if the path was a directory. // Since we now support /referencePaths option we would need to search them to see if the resolved path is a directory. // An error will be reported by the assembly manager anyways. metadataReferences.AddRange(ParseSeparatedPaths(value).Select(path => new CommandLineReference(path, MetadataReferenceProperties.Module))); resourcesOrModulesSpecified = true; } continue; case "l": case "link": metadataReferences.AddRange(ParseAssemblyReferences(arg, value, diagnostics, embedInteropTypes: true)); continue; case "win32res": win32ResourceFile = GetWin32Setting(arg, value, diagnostics); continue; case "win32icon": win32IconFile = GetWin32Setting(arg, value, diagnostics); continue; case "win32manifest": win32ManifestFile = GetWin32Setting(arg, value, diagnostics); noWin32Manifest = false; continue; case "nowin32manifest": noWin32Manifest = true; win32ManifestFile = null; continue; case "res": case "resource": if (value == null) { break; // Dev11 reports unrecognized option } var embeddedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: true); if (embeddedResource != null) { managedResources.Add(embeddedResource); resourcesOrModulesSpecified = true; } continue; case "linkres": case "linkresource": if (value == null) { break; // Dev11 reports unrecognized option } var linkedResource = ParseResourceDescription(arg, value, baseDirectory, diagnostics, embedded: false); if (linkedResource != null) { managedResources.Add(linkedResource); resourcesOrModulesSpecified = true; } continue; case "debug": emitPdb = true; // unused, parsed for backward compat only if (value != null) { if (value.IsEmpty()) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), name); } else if (!string.Equals(value, "full", StringComparison.OrdinalIgnoreCase) && !string.Equals(value, "pdbonly", StringComparison.OrdinalIgnoreCase)) { AddDiagnostic(diagnostics, ErrorCode.ERR_BadDebugType, value); } } continue; case "debug+": //guard against "debug+:xx" if (value != null) break; emitPdb = true; continue; case "debug-": if (value != null) break; emitPdb = false; continue; case "o": case "optimize": case "o+": case "optimize+": if (value != null) break; optimize = true; continue; case "o-": case "optimize-": if (value != null) break; optimize = false; continue; case "p": case "parallel": case "p+": case "parallel+": if (value != null) break; concurrentBuild = true; continue; case "p-": case "parallel-": if (value != null) break; concurrentBuild = false; continue; case "warnaserror": case "warnaserror+": if (value == null) { generalDiagnosticOption = ReportDiagnostic.Error; // Reset specific warnaserror options (since last /warnaserror flag on the command line always wins), // and bump warnings to errors. warnAsErrors.Clear(); foreach (var key in diagnosticOptions.Keys) { if (diagnosticOptions[key] == ReportDiagnostic.Warn) { warnAsErrors[key] = ReportDiagnostic.Error; } } continue; } if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else { AddWarnings(warnAsErrors, ReportDiagnostic.Error, ParseWarnings(value)); } continue; case "warnaserror-": if (value == null) { generalDiagnosticOption = ReportDiagnostic.Default; // Clear specific warnaserror options (since last /warnaserror flag on the command line always wins). warnAsErrors.Clear(); continue; } if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else { foreach (var id in ParseWarnings(value)) { ReportDiagnostic ruleSetValue; if (diagnosticOptions.TryGetValue(id, out ruleSetValue)) { warnAsErrors[id] = ruleSetValue; } else { warnAsErrors[id] = ReportDiagnostic.Default; } } } continue; case "w": case "warn": if (value == null) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); continue; } int newWarningLevel; if (string.IsNullOrEmpty(value) || !int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out newWarningLevel)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else if (newWarningLevel < 0 || newWarningLevel > 4) { AddDiagnostic(diagnostics, ErrorCode.ERR_BadWarningLevel, name); } else { warningLevel = newWarningLevel; } continue; case "nowarn": if (value == null) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); continue; } if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else { AddWarnings(noWarns, ReportDiagnostic.Suppress, ParseWarnings(value)); } continue; case "unsafe": case "unsafe+": if (value != null) break; allowUnsafe = true; continue; case "unsafe-": if (value != null) break; allowUnsafe = false; continue; case "langversion": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "/langversion:"); } else if (!TryParseLanguageVersion(value, CSharpParseOptions.Default.LanguageVersion, out languageVersion)) { AddDiagnostic(diagnostics, ErrorCode.ERR_BadCompatMode, value); } continue; case "delaysign": case "delaysign+": if (value != null) { break; } delaySignSetting = true; continue; case "delaysign-": if (value != null) { break; } delaySignSetting = false; continue; case "keyfile": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, "keyfile"); } else { keyFileSetting = RemoveAllQuotes(value); } // NOTE: Dev11/VB also clears "keycontainer", see also: // // MSDN: In case both /keyfile and /keycontainer are specified (either by command line option or by // MSDN: custom attribute) in the same compilation, the compiler will first try the key container. // MSDN: If that succeeds, then the assembly is signed with the information in the key container. // MSDN: If the compiler does not find the key container, it will try the file specified with /keyfile. // MSDN: If that succeeds, the assembly is signed with the information in the key file and the key // MSDN: information will be installed in the key container (similar to sn -i) so that on the next // MSDN: compilation, the key container will be valid. continue; case "keycontainer": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "keycontainer"); } else { keyContainerSetting = value; } // NOTE: Dev11/VB also clears "keyfile", see also: // // MSDN: In case both /keyfile and /keycontainer are specified (either by command line option or by // MSDN: custom attribute) in the same compilation, the compiler will first try the key container. // MSDN: If that succeeds, then the assembly is signed with the information in the key container. // MSDN: If the compiler does not find the key container, it will try the file specified with /keyfile. // MSDN: If that succeeds, the assembly is signed with the information in the key file and the key // MSDN: information will be installed in the key container (similar to sn -i) so that on the next // MSDN: compilation, the key container will be valid. continue; case "highentropyva": case "highentropyva+": if (value != null) break; highEntropyVA = true; continue; case "highentropyva-": if (value != null) break; highEntropyVA = false; continue; case "nologo": displayLogo = false; continue; case "baseaddress": ulong newBaseAddress; if (string.IsNullOrEmpty(value) || !TryParseUInt64(value, out newBaseAddress)) { if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else { AddDiagnostic(diagnostics, ErrorCode.ERR_BadBaseNumber, value); } } else { baseAddress = newBaseAddress; } continue; case "subsystemversion": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "subsystemversion"); continue; } // It seems VS 2012 just silently corrects invalid values and suppresses the error message SubsystemVersion version = SubsystemVersion.None; if (SubsystemVersion.TryParse(value, out version)) { subsystemVersion = version; } else { AddDiagnostic(diagnostics, ErrorCode.ERR_InvalidSubsystemVersion, value); } continue; case "touchedfiles": unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "touchedfiles"); continue; } else { touchedFilesPath = unquoted; } continue; case "bugreport": UnimplementedSwitch(diagnostics, name); continue; case "utf8output": if (value != null) break; utf8output = true; continue; case "m": case "main": // Remove any quotes for consistent behaviour as MSBuild can return quoted or // unquoted main. unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); continue; } mainTypeName = unquoted; continue; case "fullpaths": if (value != null) break; printFullPaths = true; continue; case "filealign": ushort newAlignment; if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsNumber, name); } else if (!TryParseUInt16(value, out newAlignment)) { AddDiagnostic(diagnostics, ErrorCode.ERR_InvalidFileAlignment, value); } else if (!CompilationOptions.IsValidFileAlignment(newAlignment)) { AddDiagnostic(diagnostics, ErrorCode.ERR_InvalidFileAlignment, value); } else { fileAlignment = newAlignment; } continue; case "pdb": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_NoFileSpec, arg); } else { pdbPath = ParsePdbPath(value, diagnostics, baseDirectory); } continue; case "errorendlocation": errorEndLocation = true; continue; case "reportanalyzer": reportAnalyzer = true; continue; case "nostdlib": case "nostdlib+": if (value != null) break; noStdLib = true; continue; case "lib": ParseAndResolveReferencePaths(name, value, baseDirectory, libPaths, MessageID.IDS_LIB_OPTION, diagnostics); continue; case "nostdlib-": if (value != null) break; noStdLib = false; continue; case "errorreport": continue; case "errorlog": unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, ":<file>", RemoveAllQuotes(arg)); } else { errorLogPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory); } continue; case "appconfig": unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, ":<text>", RemoveAllQuotes(arg)); } else { appConfigPath = ParseGenericPathToFile(unquoted, diagnostics, baseDirectory); } continue; case "runtimemetadataversion": unquoted = RemoveAllQuotes(value); if (string.IsNullOrEmpty(unquoted)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<text>", name); continue; } runtimeMetadataVersion = unquoted; continue; case "ruleset": // The ruleset arg has already been processed in a separate pass above. continue; case "additionalfile": if (string.IsNullOrEmpty(value)) { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, "<file list>", name); continue; } additionalFiles.AddRange(ParseAdditionalFileArgument(value, baseDirectory, diagnostics)); continue; } } AddDiagnostic(diagnostics, ErrorCode.ERR_BadSwitch, arg); } foreach (var o in warnAsErrors) { diagnosticOptions[o.Key] = o.Value; } // Specific nowarn options always override specific warnaserror options. foreach (var o in noWarns) { diagnosticOptions[o.Key] = o.Value; } if (!IsInteractive && !sourceFilesSpecified && (outputKind.IsNetModule() || !resourcesOrModulesSpecified)) { AddDiagnostic(diagnostics, diagnosticOptions, ErrorCode.WRN_NoSources); } if (!noStdLib) { metadataReferences.Insert(0, new CommandLineReference(Path.Combine(sdkDirectory, "mscorlib.dll"), MetadataReferenceProperties.Assembly)); } if (!platform.Requires64Bit()) { if (baseAddress > uint.MaxValue - 0x8000) { AddDiagnostic(diagnostics, ErrorCode.ERR_BadBaseNumber, string.Format("0x{0:X}", baseAddress)); baseAddress = 0; } } // add additional reference paths if specified if (!string.IsNullOrWhiteSpace(additionalReferenceDirectories)) { ParseAndResolveReferencePaths(null, additionalReferenceDirectories, baseDirectory, libPaths, MessageID.IDS_LIB_ENV, diagnostics); } ImmutableArray<string> referencePaths = BuildSearchPaths(sdkDirectory, libPaths); ValidateWin32Settings(win32ResourceFile, win32IconFile, win32ManifestFile, outputKind, diagnostics); // Dev11 searches for the key file in the current directory and assembly output directory. // We always look to base directory and then examine the search paths. keyFileSearchPaths.Add(baseDirectory); if (baseDirectory != outputDirectory) { keyFileSearchPaths.Add(outputDirectory); } if (!emitPdb) { if (pdbPath != null) { // Can't give a PDB file name and turn off debug information AddDiagnostic(diagnostics, ErrorCode.ERR_MissingDebugSwitch); } } string compilationName; GetCompilationAndModuleNames(diagnostics, outputKind, sourceFiles, sourceFilesSpecified, moduleAssemblyName, ref outputFileName, ref moduleName, out compilationName); var parseOptions = new CSharpParseOptions ( languageVersion: languageVersion, preprocessorSymbols: defines.ToImmutableAndFree(), documentationMode: parseDocumentationComments ? DocumentationMode.Diagnose : DocumentationMode.None, kind: SourceCodeKind.Regular, features: CompilerOptionParseUtilities.ParseFeatures(features) ); var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script); var options = new CSharpCompilationOptions ( outputKind: outputKind, moduleName: moduleName, mainTypeName: mainTypeName, scriptClassName: WellKnownMemberNames.DefaultScriptClassName, usings: usings, optimizationLevel: optimize ? OptimizationLevel.Release : OptimizationLevel.Debug, checkOverflow: checkOverflow, allowUnsafe: allowUnsafe, concurrentBuild: concurrentBuild, cryptoKeyContainer: keyContainerSetting, cryptoKeyFile: keyFileSetting, delaySign: delaySignSetting, platform: platform, generalDiagnosticOption: generalDiagnosticOption, warningLevel: warningLevel, specificDiagnosticOptions: diagnosticOptions ); var emitOptions = new EmitOptions ( metadataOnly: false, debugInformationFormat: DebugInformationFormat.Pdb, pdbFilePath: null, // to be determined later outputNameOverride: null, // to be determined later baseAddress: baseAddress, highEntropyVirtualAddressSpace: highEntropyVA, fileAlignment: fileAlignment, subsystemVersion: subsystemVersion, runtimeMetadataVersion: runtimeMetadataVersion ); // add option incompatibility errors if any diagnostics.AddRange(options.Errors); return new CSharpCommandLineArguments { IsInteractive = IsInteractive, BaseDirectory = baseDirectory, Errors = diagnostics.AsImmutable(), Utf8Output = utf8output, CompilationName = compilationName, OutputFileName = outputFileName, PdbPath = pdbPath, EmitPdb = emitPdb, OutputDirectory = outputDirectory, DocumentationPath = documentationPath, ErrorLogPath = errorLogPath, AppConfigPath = appConfigPath, SourceFiles = sourceFiles.AsImmutable(), Encoding = codepage, ChecksumAlgorithm = checksumAlgorithm, MetadataReferences = metadataReferences.AsImmutable(), AnalyzerReferences = analyzers.AsImmutable(), AdditionalFiles = additionalFiles.AsImmutable(), ReferencePaths = referencePaths, KeyFileSearchPaths = keyFileSearchPaths.AsImmutable(), Win32ResourceFile = win32ResourceFile, Win32Icon = win32IconFile, Win32Manifest = win32ManifestFile, NoWin32Manifest = noWin32Manifest, DisplayLogo = displayLogo, DisplayHelp = displayHelp, ManifestResources = managedResources.AsImmutable(), CompilationOptions = options, ParseOptions = IsInteractive ? scriptParseOptions : parseOptions, EmitOptions = emitOptions, ScriptArguments = scriptArgs.AsImmutableOrEmpty(), TouchedFilesPath = touchedFilesPath, PrintFullPaths = printFullPaths, ShouldIncludeErrorEndLocation = errorEndLocation, PreferredUILang = preferredUILang, SqmSessionGuid = sqmSessionGuid, ReportAnalyzer = reportAnalyzer }; }
internal static EmitOutput? EmitCompilation( Compilation compilation, IEnumerable<ResourceDescription> manifestResources, List<ModuleData> dependencies, DiagnosticBag diagnostics, CompilationTestData testData, EmitOptions emitOptions ) { // A Compilation can appear multiple times in a depnedency graph as both a Compilation and as a MetadataReference // value. Iterate the Compilations eagerly so they are always emitted directly and later references can re-use // the value. This gives better, and consistent, diagostic information. var referencedCompilations = FindReferencedCompilations(compilation); var fullNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (var referencedCompilation in referencedCompilations) { var emitData = EmitCompilationCore(referencedCompilation, null, diagnostics, null, emitOptions); if (emitData.HasValue) { var moduleData = new ModuleData(referencedCompilation.Assembly.Identity, OutputKind.DynamicallyLinkedLibrary, emitData.Value.Assembly, pdb: default(ImmutableArray<byte>), inMemoryModule: true); fullNameSet.Add(moduleData.Id.FullName); dependencies.Add(moduleData); } } // Now that the Compilation values have been emitted, emit the non-compilation references foreach (var current in (new[] { compilation }).Concat(referencedCompilations)) { EmitReferences(current, fullNameSet, dependencies, diagnostics); } return EmitCompilationCore(compilation, manifestResources, diagnostics, testData, emitOptions); }