singrdk/base/Applications/Benchmarks/BartokH/host/Bartok.cs

1560 lines
67 KiB
C#
Raw Normal View History

2008-03-05 09:52:00 -05:00
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
#define NONONNULLTYPECHECK // required on Singularity, no affect on other Windows.
namespace Bartok {
using System;
using System.IO;
using System.Text;
using System.Collections;
using Bartok.Utility;
using Bartok.Datatype;
using Bartok.CfgUtil;
using Bartok.Ir;
using Bartok.Lir;
using Bartok.Analysis;
using Bartok.Opt.IrCleanup;
using Bartok.Opt.Ir;
using Bartok.Opt.Lir;
using Bartok.Opt;
using Bartok.Regalloc;
using Bartok.Opt.Ssa;
using Bartok.Backend;
#if ON_SINGULARITY
using Microsoft.Singularity;
#endif
//
// Bartok.cs
//
// Main entry point for compiler
// "public class Bartok {..}" breaks the namespace lookup of Bartok.*
// Is this a bug?
public class BartokClass {
public static long CHECK_COUNT = 0;
public static long CHECK_COUNT_LOWER = 0;
public static int Main(String[] args) {
#if ON_SINGULARITY
// AppRuntime.EnableGCVerify = false;
// DebugStub.WriteLine("Bartok Host: Enabled GC Verifier");
// AppRuntime.EnableGCAccounting = true;
// DebugStub.WriteLine("Bartok Host: Enabled GC Accounting");
#endif
Bartok.MSIL.MetaDataUtil.Configure(new MetaDataOutput());
try {
ProcessCmdLine(args);
if((fileNames.Count == 0) && (linkNames.Count == 0)) {
CHECK_COUNT++;
CHECK_COUNT_LOWER++;
PrintUsage();
Util.Error("\nno files to process...aborting.");
Util.Exit(-11);
}
if(StageControl.AtomicSupport) {
StageControl.TryAllSupport = true;
}
Util.Message(NoiseLevel.PerPhase,
"fileNames = "
+ new CollectionFormatter(fileNames));
Util.Message(NoiseLevel.PerPhase,
"refFileNames = "
+ new CollectionFormatter(refFileNames));
Util.Message(NoiseLevel.PerPhase,
"libDirNames = "
+ new CollectionFormatter(libDirNames));
Util.Message(NoiseLevel.PerPhase,
"outputDirName = " + outputDirName);
if (overrideNames.Count > 0) {
Util.Message(NoiseLevel.PerPhase,
"overrideNames = "
+ new CollectionFormatter(overrideNames));
}
if (entryPoints.Count > 0) {
Util.Message(NoiseLevel.PerPhase,
"entryPoints = "
+ new CollectionFormatter(entryPoints));
}
// Create helper data structures
DateTime startTime = Util.startTime;
bool fLoadDebugInfo = StageControl.SymbolicDebug;
StageControl.BartokLinkPhase = false;
if (StageControl.CompileOnly) {
// separate compilation
foreach (String fileName in fileNames) {
String outputName =
ComputeOutputName(fileName, outputDirName);
ArrayList loadFileNames = new ArrayList(1);
loadFileNames.Add(fileName);
String shortName = GetShortName(fileName).ToLower();
// we need to compile mscorlib.dll together with
// system.dll
bool fDefineOverride = shortName.Equals("mscorlib.dll");
TypeData typeData = new TypeData();
CompileFile(typeData, loadFileNames, refFileNames,
overrideNames, overrideDefNames,
fDefineOverride, outputName,
startTime, fLoadDebugInfo);
}
} else {
// Create output root name.
if (outputRootName == null) {
outputRootName = (String) fileNames[0];
}
// strip off extension, if there is one.
int dotIndex = outputRootName.LastIndexOf('.');
if (dotIndex != -1) {
String ext = outputRootName.Substring(dotIndex + 1);
if (ext.Equals("dll") || ext.Equals("obj")
|| ext.Equals("exe")) {
outputRootName =
outputRootName.Substring(0, dotIndex);
}
}
bool fDefineOverride = StageControl.WholeProgram;
TypeData typeData = new TypeData();
String objFileName =
CompileFile(typeData, fileNames, refFileNames,
overrideNames, overrideDefNames, fDefineOverride,
outputRootName, startTime, fLoadDebugInfo);
linkNames.Add(objFileName);
#if DO_LINK
StageControl.BartokLinkPhase = true;
BartokLinker bartokLinker = new BartokLinker();
typeData = StageControl.WholeProgram ? typeData : null;
bartokLinker.Link(typeData, fileNames, linkNames,
refFileNames, overrideNames, overrideDefNames,
libDirNames,
entryPoints, initializerSkips,
outputRootName);
#endif
}
} catch(AbortException) {
// Abort code already dumped the stack
Util.Exit(-1);
} catch(Exception e) {
Util.Error("Internal uncaught {0} exception", e);
Util.Exit(-1);
}
Util.Message(NoiseLevel.PerPhase,
"STATIC COUNT IS: " + CHECK_COUNT);
Util.Message(NoiseLevel.PerPhase,
"STATIC LOWER IS: " + CHECK_COUNT_LOWER);
return 0;
}
private static String CompileFile(TypeData typeData,
ArrayList fileNames,
ArrayList refFileNames,
ArrayList overrideNames,
ArrayList overrideDefNames,
bool fDefineOverride,
String outputName,
DateTime startTime,
bool fLoadDebugInfo) {
ConvertMsil2Ir(fileNames, refFileNames, overrideNames,
overrideDefNames, fDefineOverride, startTime,
fLoadDebugInfo, typeData);
CHECK_COUNT++;
CHECK_COUNT_LOWER++;
#if SELF_PROFILING
System.GC.Collect();
long memoryUsage = System.GC.GetTotalMemory(false);
Util.Message("memory usage: " + memoryUsage);
#endif
if (entryPoints.Count > 0) {
Util.Message(NoiseLevel.PerPhase,
"entryPoints = "
+ new CollectionFormatter(entryPoints));
}
if(!StageControl.CompileOnly && (entryPoints.Count == 0)) {
Util.Abort("No entry points found");
}
typeData.ComputeEntryMethod(entryPoints);
Util.Assert(typeData.EntryPoints.Count == entryPoints.Count);
// register all global analysis
AnalysisRegistry analysisRegistry = RegisterAnalysis(typeData);
// Create a series of phases that are each applied to the
// whole program.
Bartok.Ir.PhaseList phases = new Bartok.Ir.PhaseList("ir");
CHECK_COUNT--;
CHECK_COUNT_LOWER--;
AddPhases(phases, analysisRegistry, outputName, typeData);
Util.Message(phases.ComponentPhases.ToString());
if (StageControl.DumpContainers) {
phases.Add(new TypeDataPrettyPhase("After IR:"));
}
Bartok.Opt.IrCleanup.Statistics.Reset(typeData);
BartokList phaseNames = phases.ComponentPhases;
foreach(Object phaseObj in phaseNames) {
if(!(phaseObj is string)) {
Util.Warn("Not string: {0}X",
phaseObj.ToString());
continue;
}
string phaseName = (string)phaseObj;
if(phaseName.IndexOf(' ') != -1) {
Util.Warn("Phase has a space in name: {0}", phaseName);
}
}
foreach(string phaseName in StageControl.disabledPhaseNames) {
if(phaseNames.Contains(phaseName)) {
continue;
}
if(StageControl.disabledPhaseNamesFound.Contains(phaseName)) {
continue;
}
Util.Abort("Couldn't find phase: " + phaseName);
}
phases.Go(typeData);
Bartok.Opt.IrCleanup.Statistics.Summary();
#if SELF_PROFILING
memoryUsage = System.GC.GetTotalMemory(false);
Util.Message("memory usage: " + memoryUsage);
#endif
// backend phases:
Util.Message("outputRootName = " + outputName);
String objFileName = LirPhases.run(typeData, fileNames, outputName,
StageControl.GenObjFile);
System.GC.Collect();
Util.Message("End of Bartok: " + GC.GetTotalMemory(false));
return objFileName;
}
private static void ConvertMsil2Ir(ArrayList fileNames,
ArrayList refFileNames,
ArrayList overrideNames,
ArrayList overrideDefNames,
bool fDefineOverride,
DateTime startTime,
bool fLoadDebugInfo,
TypeData typeData) {
// Remove redundant fileNames
// Remove refFileNames that are redundant with fileNames
for(int i=0; i<fileNames.Count; ++i) {
#if ON_SINGULARITY
String fileI = ((String)fileNames[i]).ToLower();
#else
String fileI = Path.GetFullPath((String) fileNames[i]).ToLower();
#endif
for(int j=i+1; j<fileNames.Count; ++j) {
#if ON_SINGULARITY
String fileJ =((String) fileNames[j]).ToLower();
#else
String fileJ =
Path.GetFullPath((String) fileNames[j]).ToLower();
#endif
if(fileI == fileJ) {
Util.Warn("Removing redundant input {0} from command line",
fileNames[j]);
fileNames.RemoveAt(j);
}
}
for(int j=0; j<refFileNames.Count; ++j) {
String fileJ = MSIL.MetaDataResolver.ResolveFileName
(libDirNames, (String) refFileNames[j]);
if(fileJ == null) {
// Future failure in MetaDataResolver will have a better
// error message so move on.
continue;
}
fileJ = fileJ.ToLower();
if(fileI == fileJ) {
Util.Warn("Removing redundant reference {0} (with a code input) from command line",
refFileNames[j]);
refFileNames.RemoveAt(j);
}
}
}
// Remove redundant refFileNames (may be redundant with fileNames
// or other refFileNames)
for(int i=0; i<refFileNames.Count; ++i) {
String fileI = MSIL.MetaDataResolver.ResolveFileName
(libDirNames, (String) refFileNames[i]);
if(fileI == null) {
// Future failure in MetaDataResolver will have a better
// error message so move on.
continue;
}
fileI = fileI.ToLower();
for(int j=i+1; j<refFileNames.Count; ++j) {
String fileJ = MSIL.MetaDataResolver.ResolveFileName
(libDirNames, (String) refFileNames[j]);
if(fileJ == null) {
// Future failure in MetaDataResolver will have a better
// error message so move on.
continue;
}
fileJ = fileJ.ToLower();
if(fileI == fileJ) {
Util.Warn("Removing redundant reference {0} from command line",
refFileNames[j]);
refFileNames.RemoveAt(j);
}
}
}
bool fTranslateTryAll = StageControl.TryAllSupport;
bool fTranslateAtomic = StageControl.AtomicSupport;
bool fMsilMessages = Verbosity.level >= NoiseLevel.PerPhase;
Bartok.MSIL.MetaDataResolver libResolver =
new Bartok.MSIL.MetaDataResolver(refFileNames, libDirNames,
startTime, fLoadDebugInfo,
fMsilMessages);
Bartok.MSIL.MetaDataResolver overrideResolver;
if (fDefineOverride) {
// load code
overrideResolver =
new Bartok.MSIL.MetaDataResolver(overrideNames,
startTime,
fLoadDebugInfo,
fTranslateTryAll,
fTranslateAtomic,
fMsilMessages);
} else {
// don't load code
overrideResolver =
new Bartok.MSIL.MetaDataResolver(overrideNames,
libDirNames,
startTime, fLoadDebugInfo,
fMsilMessages);
}
Bartok.MSIL.MetaDataResolver overrideDefResolver =
new Bartok.MSIL.MetaDataResolver(overrideDefNames, startTime,
fLoadDebugInfo,
fTranslateTryAll,
fTranslateAtomic,
fMsilMessages);
Bartok.MSIL.MetaDataResolver loadResolver =
new Bartok.MSIL.MetaDataResolver(fileNames, startTime,
fLoadDebugInfo,
fTranslateTryAll,
fTranslateAtomic,
fMsilMessages);
Bartok.MSIL.MetaDataResolver[] resolvers =
new Bartok.MSIL.MetaDataResolver[] {
libResolver, overrideResolver, overrideDefResolver,
loadResolver
};
Bartok.MSIL.MetaDataResolver.ResolveCustomAttributes(resolvers);
MetaDataParser parser =
new MetaDataParser(entryPoints.Count == 0 ? entryPoints : null);
Util.TimestampMessage(NoiseLevel.PerPhase,
"translating from MSIL");
parser.Parse(loadResolver, overrideResolver,
overrideDefResolver, libResolver,
typeData, fDefineOverride, false);
Util.TimestampMessage(NoiseLevel.PerPhase,
"finished translating");
}
private static AnalysisRegistry RegisterAnalysis(TypeData typeData) {
AnalysisRegistry analysisRegistry = new AnalysisRegistry(typeData);
analysisRegistry.RegisterAnalysis(VirtualCallAnalysis.makeFactory());
return analysisRegistry;
}
private static void AddPhases(Bartok.Ir.PhaseList phases,
AnalysisRegistry analysisRegistry,
String outputName,
TypeData typeData) {
if (StageControl.PrintContainers) {
phases.Add(new TypeDataPrintPhase("After parse:"));
}
if (StageControl.DumpContainers) {
phases.Add(new TypeDataPrettyPhase("After parse:"));
}
if (StageControl.SingSharpTemplateRemover) {
phases.Add(new SingSharpTemplateRemover());
}
if (StageControl.RuntimeMods) {
phases.Add(new RuntimeMods());
}
if (StageControl.IrMultiPropSimple) {
phases.Add(new IrMultiPropSimple("System.GC"));
}
if (StageControl.IrDeadAssignmentSimple1) {
phases.Add(new IrDeadAssignmentSimplePhase("System.GC"));
}
if (StageControl.IrTreeShake) {
phases.Add(new IrTreeShake(typeData.EntryPoints,
dynamicLoads,
StageControl.WholeProgram,
analysisRegistry));
}
/*
phases.Add
(new DynamicCount
("VirtualCallsStart",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.CallVirtual,
Operator.OpCodes.InterfaceCall),
DynamicCount.Granularity.PerSite));
*/
/*
phases.Add
(new DynamicCount
("ASCstart",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.CheckArrayStore,
Operator.OpCodes.CheckVectorStore),
DynamicCount.Granularity.PerSite));
*/
if (StageControl.PtrAnalysis) {
phases.Add(PtrTypeSimpleSystem.CreateAnalysis());
phases.Add(PtrTypeHierarchySystem.CreateAnalysis());
phases.Add(PtrTypeSetSystem.CreateAnalysis());
}
// create wrapper that insert calls to leaveGCSafeState and
// enterGCSafeState.
phases.Add(new CreateEntryPointWrapper());
// trap ValueType.Equals and override it by compiler generated
// routines.
if (StageControl.IrOverrideValueTypeEquals) {
phases.Add(new Convert.ValueTypeEquals());
}
if (StageControl.LimitedReflection) {
phases.Add(new Convert.OverrideVTableInit());
}
if (StageControl.IrConvertSizeofPrimitive) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.SizeofPrimitive;
phases.Add(new Convert.ToMir(mask));
}
/* SPOONS: region related phases:
// A temporary pass that cleans up the scratch objects so that the
// DemandAnalysis is not confused by the randomness that the tree
// shaker leaves behind.
phases.Add(new CleanScratch());
// Build a "Foo_layout" for each class "Foo"; other setup required
// by DemandAnalysis.
phases.Add(new LayoutBuilder());
// Perform first- and last-use analysis; add explicit region
// variables and effects.
phases.Add(new DemandAnalysis());
// Print the code
phases.Add(new TypeDataPrettyPhase("After Demand:"));
*/
// Perform first- and last-use analysis; add explicit region
// variables and effects.
// must happen after DemandAnalysis, but before any inlining /
// rearranging basic blocks or calls.
#if !VC
if(StageControl.TryAllSupport) {
phases.Add(new Bartok.Convert.PropagateLogging(analysisRegistry));
phases.Add(new TypeDataDummyPhase());
}
#endif
if (StageControl.IrScanCallEffects) {
phases.Add(new IrScanCallEffects());
}
if(StageControl.DumpInheritance) {
phases.Add(new DumpInheritancePhase(StageControl.DumpInheritanceFile));
}
#if PHX_TODO
phases.Add(new TypeDataToPhoenix());
#endif
phases.Add(new TypeInit(initializerSkips));
if (StageControl.InstrumentCalls) {
phases.Add(new InstrumentCalls());
}
if (StageControl.IrStoreChecks) {
phases.Add(new IrStoreCheckElim());
}
if (StageControl.BuildC2Mods
&& StageControl.UnmanagedStrings) {
phases.Add(new IrUnmanagedStrings());
}
phases.Add(IrCleanup.Create());
if (StageControl.BuildC2Mods
&& StageControl.IdentifyAsMethods) {
phases.Add(new IrIdentifyAsMethods());
}
if (StageControl.WholeProgram
&& StageControl.IrDeadAssignmentSimpleFormals
&& StageControl.IrTreeShake) {
phases.Add(new IrDeadAssignmentSimpleFormalsPhase());
phases.Add(new IrTreeShake(typeData.EntryPoints,
dynamicLoads,
StageControl.WholeProgram,
analysisRegistry));
}
phases.Add(new Convert.IrInsertDelegate());
IrFieldAnalysis fieldAnalysis = null;
if (StageControl.GCType ==
StageControl.ReferenceCountingCollector &&
StageControl.RCCollectorOptRCSubsumed &&
StageControl.RCCollectorOptRCSubsumedByROFields) {
IrFieldAnalysis.FieldFilter filter =
new IrFieldAnalysis.RCAproposFieldFilter();
fieldAnalysis = new IrFieldAnalysis(true, filter);
phases.Add(fieldAnalysis);
}
if(StageControl.IrInlineConstructor) {
phases.Add(new Convert.ToMir(Convert.ToMir.Mask.Constructor));
}
// When only one class implements an interface, replace the interface
// with the class.
if (StageControl.IrInterfaceElim && StageControl.WholeProgram) {
phases.Add(new InterfaceElim());
}
if (StageControl.IrSimpleInliner) {
phases.Add(new IrSimpleInliner(new IrInline(), false, false, false));
} else if (StageControl.IrAttributeInliner) {
// inline methods that has [inline] attributes.
phases.Add(new IrSimpleInliner(new IrInline(), false, false));
}
if (StageControl.FailAfterInliner) {
phases.Add(new FailPhase());
}
if (StageControl.IrMultiPropSimple) {
phases.Add(new IrMultiPropSimple());
}
if (StageControl.IrSuppressExnEdges) {
phases.Add(new IrSuppressExnEdges());
}
if (StageControl.IrLoadStoreOpt) {
phases.Add(new IrLoadStoreOpt(analysisRegistry));
}
if (StageControl.DevirtualizeCall) {
phases.Add(new IrDevirtualizeCall(analysisRegistry));
}
if (StageControl.IrSimpleInliner &&
StageControl.IrInlinerDoIncreaseSize) {
phases.Add(new IrSimpleInliner(new IrInline(), true, false, false));
}
if (StageControl.LazyTypeInits) {
phases.Add(new TypeInit(initializerSkips, true));
}
// Eliminate unnecessary instanceOf/check casts. Only makes
// 2 passes by punting back edges.
if (StageControl.IrTypeTestElimPunt) {
phases.Add(new TypeTestElimPunt());
}
// Eliminate unnecessary instanceOf/check casts - full iterative
// analysis. More expensive than the above analysis, but yields
// little improvement in practice.
if (StageControl.IrTypeTestElim) {
phases.Add(new TypeTestElim());
}
// Deletes all CheckCasts and instanceOf IDisposable for sake of
// experimentation. Normally not enabled, as it is unsafe.
if (StageControl.IrDeleteCheckCasts) {
phases.Add(new DeleteCheckCast());
}
if (StageControl.IrConvertOpt) {
phases.Add(new IrConvertOpt());
phases.Add(new IrDeadAssignmentSimplePhase());
phases.Add(new IrReverseCopyProp());
}
// Just do thread analysis once.
IrLockedFields locks = null;
if (StageControl.ExtendThreadFieldsABCD ||
StageControl.SsaNullCheckGlobalThreaded) {
if (StageControl.IrTreeShake) {
phases.Add(new IrTreeShake(typeData.EntryPoints,
dynamicLoads,
StageControl.WholeProgram,
analysisRegistry));
}
if(StageControl.OptimisticLocking) {
locks = new ClassIrLockedFields(analysisRegistry);
} else {
locks = new IrLockedFields(analysisRegistry);
}
phases.Add(locks);
}
// Array bounds check elimination
if (StageControl.ABCD) {
phases.Add(new ABCD(analysisRegistry, locks));
}
if (StageControl.IrConvertArrayBounds) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.CheckVectorBounds;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.IrConvertInferface) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.InterfaceCall;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.IrConvertSimpleArrayAccess) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.SimpleArrayAccess;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.IrCloneLoopHeader) {
phases.Add(new IrCloneLoopHeader());
phases.Add(new IrJumpElim());
phases.Add(new IrMultiPropSimple());
}
if (StageControl.SsaOpts) {
if (StageControl.SsaNullCheckGlobalThreaded) {
phases.Add(SSAPhase.Create(analysisRegistry, locks));
} else {
phases.Add(SSAPhase.Create());
}
}
if(locks != null) {
locks = null;
}
// IrInsertStructCopy phase insert a StructCopy() method
// to each struct type, and lower struct Id operators
// to a call to StructCopy() method.
phases.Add(new Convert.IrInsertStructCopy());
#if !VC
if(StageControl.TryAllSupport) {
phases.Add(new IrInsertLogging());
}
if(StageControl.TryAllSupport &&
StageControl.AtomicSupportUpdateEnlistOptFlow) {
// without the IrLoadStoreOpt here, EnlistIndirects
// generated by [Store]StructFields can't be moved.
phases.Add(new IrLoadStoreOpt(analysisRegistry));
phases.Add(new IrInsertUpdateEnlistments());
// otherwise CSE misses things that it should be eliminating
phases.Add(new IrMultiPropSimple());
}
if (StageControl.TryAllSupport &&
StageControl.IrKeepManager) {
phases.Add(new IrKeepManager(analysisRegistry));
}
#endif
if(StageControl.IrStructVectorOperations) {
phases.Add(new IrStruct(true));
}
if (StageControl.IrLoadStoreOpt) {
phases.Add(new IrLoadStoreOpt(analysisRegistry));
}
#if !VC
if (StageControl.TryAllSupport &&
StageControl.AtomicSupportUpdateEnlistOpt) {
phases.Add(new IrSimpleAvoidUpgrade());
}
#endif
if (StageControl.IrConvertComplexArrayAccess) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.ComplexArrayAccess;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.IrConvertExpandedArrayAccess) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.ExpandedArrayAccess;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.ArraySupportOptimizePass && StageControl.SsaOpts) {
phases.Add(SSAPhase.Create());
}
#if !VC
if (StageControl.TryAllSupport &&
StageControl.TryAllSupportOptimizePass &&
StageControl.SsaOpts) {
phases.Add(SSAPhase.Create());
}
#endif
if (StageControl.IrInitStaticField) {
phases.Add(new IrInitStaticField());
}
if (StageControl.LazyTypeInits
&& StageControl.TypeInitRemoveEmptyCctors) {
phases.Add(new TypeInit(initializerSkips, true));
}
if (StageControl.GCType ==
StageControl.ReferenceCountingCollector) {
phases.Add(new IrStructRCUpdate());
}
if (StageControl.GCType ==
StageControl.DeferredReferenceCountingCollector) {
phases.Add(new IrStructDRCUpdate());
}
if (StageControl.IrTreeShake && StageControl.IrTreeShakeLate) {
phases.Add(new IrTreeShake(typeData.EntryPoints,
dynamicLoads,
StageControl.WholeProgram,
analysisRegistry));
}
if (StageControl.TypedReference) {
phases.Add(new Convert.ToMir(Convert.ToMir.Mask.Vararg1));
// All of vararg1 must finish before vararg2, so we wrap vararg2
// in a typedata phase to enforce that.
phases.Add(new TypeDataMethodPhase
(new Convert.ToMir(Convert.ToMir.Mask.Vararg2)));
}
/*
// We do not know where all of the calls will be because lowering can
// introduce calls. We make a best guess here. If we moved all
// call-generating lowering to HIR (via ToMir or equivalent), then
// this could be easily done. We are currently missing calls for the
// following:
// - pinvoke, stubs, etc
// - some arithmetic conversions
// - casts - can't add because not all are calls
// - RC, tryall, atomic
// - others?
phases.Add
(new DynamicCount
("Calls",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.Call,
Operator.OpCodes.CallIndirect,
Operator.OpCodes.CallVirtual,
Operator.OpCodes.InterfaceCall,
Operator.OpCodes.MonitorEnter,
Operator.OpCodes.MonitorExit,
Operator.OpCodes.IndirectToData,
Operator.OpCodes.CustomGetSize,
Operator.OpCodes.CheckVectorStore,
Operator.OpCodes.CheckVectorElementAddress,
Operator.OpCodes.InitVector,
Operator.OpCodes.CheckArrayStore,
Operator.OpCodes.CheckArrayElementAddress,
Operator.OpCodes.InitArray,
Operator.OpCodes.InitType,
Operator.OpCodes.GetITable,
Operator.OpCodes.NewObject,
Operator.OpCodes.NewVector,
Operator.OpCodes.NewArray),
DynamicCount.Granularity.Global));
phases.Add(new TypeDataDummyPhase());
phases.Add
(new DynamicCount
("VirtualCallsEnd",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.CallVirtual,
Operator.OpCodes.InterfaceCall),
DynamicCount.Granularity.PerSite));
phases.Add
(new DynamicCount
("ASCend",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.CheckArrayStore,
Operator.OpCodes.CheckVectorStore),
DynamicCount.Granularity.PerSite));
phases.Add(new TypeDataDummyPhase());
phases.Add
(new DynamicCount
("WB",
new DynamicCount.OpcodeFilter
(Operator.OpCodes.LocWriteBarrier),
DynamicCount.Granularity.Global));
phases.Add(new TypeDataDummyPhase());
*/
if (StageControl.WholeProgram && StageControl.OptRuntimeData) {
phases.Add(new RuntimeData());
}
if (StageControl.IrConvertArrayOpt) {
phases.Add(new IrConvertArrayOpt());
}
// insert write barrier after chooserep so we know the size of
// of objects. This is needed because we try to remove write
// barrier when we store to the young generation, however,
// big objects are in the old generation even though it is
// newly created. Therefore, we need to know object size to
// know if it is a big object.
if (StageControl.InsertWriteBarrier) {
phases.Add(new IrWriteBarrier());
phases.Add(new Convert.ToMir
(Convert.ToMir.Mask.ConvertWriteBarrier));
}
// convert type tests and sizeof effect to Mir
Convert.ToMir.Mask typeMask = Convert.ToMir.Mask.CheckCast
| Convert.ToMir.Mask.Sizeof;
if (!(StageControl.GCType ==
StageControl.ReferenceCountingCollector ||
StageControl.GCType ==
StageControl.DeferredReferenceCountingCollector)) {
typeMask |= Convert.ToMir.Mask.GetCurrentThread;
}
if (StageControl.TypedReference) {
typeMask |= Convert.ToMir.Mask.TypedRef;
}
phases.Add(new Convert.ToMir(typeMask));
if (StageControl.IrSimpleInliner) {
phases.Add(new IrSimpleInliner(new IrInline(), false, true,
true, 0, 0, 0));
}
if(StageControl.TypeInitElim) {
phases.Add(new IrTypeInitElim(analysisRegistry));
}
if (StageControl.IrRemoveDoubleCmp) {
phases.Add(new IrCmpElim());
}
if (StageControl.IrArrayBaseLength) {
phases.Add(new IrArrayBaseLength());
phases.Add(new IrDeadAssignmentSimplePhase());
}
if (StageControl.IrInitTypeInliner &&
StageControl.LazyTypeInits) {
phases.Add(new IrInitTypeInliner(typeData, new IrInline()));
}
if (StageControl.GCType ==
StageControl.ReferenceCountingCollector) {
if (StageControl.RCCollectorShowStatistics) {
String message = "Before RC Update Injection";
phases.Add(new IrBBStats(message));
}
phases.Add(new IrRCUpdate());
if (StageControl.RCCollectorShowStatistics) {
String message = "After RC Update Injection";
phases.Add(new IrBBStats(message));
}
if (StageControl.RCCollectorOptImmortals) {
phases.Add(new IrImmortalObjectRCUpdates());
}
if (StageControl.RCCollectorOptRCSubsumed) {
IrSimpleThreadEscape threadLocalObjects = null;
if (StageControl.RCCollectorOptThreadLocalAnalysis) {
IrLockedFields threadSafeFields = null;
if (StageControl.WholeProgram &&
StageControl.
RCCollectorOptRCSubsumedByTSFields) {
threadSafeFields =
new IrLockedFields(analysisRegistry);
phases.Add(threadSafeFields);
}
threadLocalObjects =
new IrSimpleThreadEscape(analysisRegistry,
threadSafeFields);
phases.Add(threadLocalObjects);
}
IrRCSubsumedRCUpdates rcSubsumption =
new IrRCSubsumedRCUpdates(analysisRegistry,
fieldAnalysis,
threadLocalObjects);
phases.Add(rcSubsumption);
}
if (StageControl.RCCollectorOptCoalescingUpdates) {
phases.Add(new IrBBLocalCoalesceRCUpdates());
}
if (StageControl.
RCCollectorOptStaticAcyclicRefTypeUpdates) {
phases.Add(new IrAcyclicRefTypeRCUpdates());
}
if (StageControl.RCCollectorOptNonNullRCUpdates) {
phases.Add(SSAPhase.NullCheckAnalysis());
}
if (StageControl.RCCollectorShowStatistics) {
String message = "After RC Optimizations";
phases.Add(new IrBBStats(message));
}
Convert.ToMir.Mask mask = Convert.ToMir.Mask.RCUpdate |
Convert.ToMir.Mask.GetCurrentThread;
phases.Add(new Convert.ToMir(mask));
if (StageControl.RCCollectorOptInlineRCUpdates &&
StageControl.IrSimpleInliner) {
phases.Add(new IrSimpleInliner(new IrInline(),
true,
false,
true));
}
phases.Add(new TypeDataDummyPhase());
}
if (StageControl.GCType ==
StageControl.DeferredReferenceCountingCollector) {
if (StageControl.RCCollectorShowStatistics) {
String message = "Before DRC Update Injection";
phases.Add(new IrBBStats(message));
}
phases.Add(new IrDRCUpdate());
if (StageControl.RCCollectorShowStatistics) {
String message = "After DRC Update Injection";
phases.Add(new IrBBStats(message));
}
if (StageControl.RCCollectorOptImmortals) {
phases.Add(new IrImmortalObjectRCUpdates());
}
if (StageControl.RCCollectorOptCoalescingUpdates) {
phases.Add(new IrBBLocalCoalesceRCUpdates());
}
if (StageControl.
RCCollectorOptStaticAcyclicRefTypeUpdates) {
phases.Add(new IrAcyclicRefTypeRCUpdates());
}
if (StageControl.RCCollectorOptNonNullRCUpdates) {
phases.Add(SSAPhase.NullCheckAnalysis());
}
if (StageControl.RCCollectorShowStatistics) {
String message = "After DRC Optimizations";
phases.Add(new IrBBStats(message));
}
Convert.ToMir.Mask mask = Convert.ToMir.Mask.RCUpdate |
Convert.ToMir.Mask.GetCurrentThread;
phases.Add(new Convert.ToMir(mask));
if (StageControl.RCCollectorOptInlineRCUpdates &&
StageControl.IrSimpleInliner) {
phases.Add(new IrSimpleInliner(new IrInline(),
true,
false,
true));
}
phases.Add(new TypeDataDummyPhase());
}
#if !VC
if(StageControl.TryAllSupport &&
StageControl.TryAllDecomposeOpt) {
phases.Add(new IrDecomposeTransMemChecks(analysisRegistry));
// IrDecomposeTransMemChecks emits GetCurrentThread ops
phases.Add(new IrLoadStoreOpt(analysisRegistry));
Convert.ToMir.Mask mask = Convert.ToMir.Mask.GetCurrentThread;
phases.Add(new Convert.ToMir(mask));
}
if (StageControl.TryAllSupport &&
StageControl.IrConvertTryAll) {
Convert.ToMir.Mask mask = Convert.ToMir.Mask.TryAll;
phases.Add(new Convert.ToMir(mask));
if (StageControl.IrSimpleInliner) {
phases.Add(new IrSimpleInliner(new IrInline(),
true,
false));
}
}
#endif
// The inliners may inline some of the methods that handle special
// MSIL opcodes, adding in instructions like Id<Struct> that we
// don't expect to see this late in the lowering. Add one more
// scan of the code to remove them.
phases.Add(new Convert.IrInsertStructCopy());
if (StageControl.IrTreeShake && StageControl.IrTreeShakeLate) {
phases.Add(new IrTreeShake(typeData.EntryPoints,
dynamicLoads,
StageControl.WholeProgram,
analysisRegistry));
}
if (StageControl.PtrAnalysis) {
phases.Add(PtrTypeSimpleSystem.CreateAnalysis());
phases.Add(PtrTypeHierarchySystem.CreateAnalysis());
phases.Add(PtrTypeSetSystem.CreateAnalysis());
}
if (StageControl.PrintContainers) {
phases.Add(new TypeDataPrintPhase("end of HIR:"));
}
}
public static ArrayList fileNames;
public static ArrayList refFileNames;
public static ArrayList libDirNames;
private static ArrayList outputDirNames;
public static String outputDirName;
public static ArrayList overrideNames;
public static ArrayList overrideDefNames;
public static String outputRootName;
public static ArrayList entryPoints;
public static ArrayList linkNames;
private static ArrayList initializerSkips;
private static ArrayList dynamicLoads;
private static bool alreadyPrintedUsage = false;
private static String StripName(String fileName) {
// strip off extension, if there is one.
int dotIndex = fileName.LastIndexOf('.');
if (dotIndex != -1) {
String ext = fileName.Substring(dotIndex + 1);
if (ext.Equals("dll") || ext.Equals("obj")
|| ext.Equals("exe")) {
fileName = fileName.Substring(0, dotIndex);
}
}
return fileName;
}
private static String GetShortName(String fileName) {
int charindex = Math.Max(fileName.LastIndexOf('/'),
fileName.LastIndexOf('\\'));
String shortName = (charindex >= 0)
? fileName.Substring(charindex + 1)
: fileName;
return shortName;
}
private static String GetDirName(String fileName) {
int charindex = Math.Max(fileName.LastIndexOf('/'),
fileName.LastIndexOf('\\'));
String dirName = (charindex >= 0)
? fileName.Substring(0, charindex + 1)
: "";
return dirName;
}
private static String ComputeOutputName(String inputFileName,
String outputDirName) {
String fileName = Path.GetFileNameWithoutExtension(inputFileName);
String outputName = outputDirName + '\\' + fileName;
return outputName;
}
private static void ProcessCmdLine(String[] args) {
fileNames = new ArrayList();
refFileNames = new ArrayList();
libDirNames = new ArrayList();
overrideNames = new ArrayList();
overrideDefNames = new ArrayList();
outputDirNames = new ArrayList();
entryPoints = new ArrayList();
initializerSkips = new ArrayList();
linkNames = new ArrayList();
dynamicLoads = new ArrayList();
int index = 0;
#if ON_SINGULARITY
index = 1;
#endif
while (index < args.Length) {
String argument = args[index];
if ((argument[0] == '-') || (argument[0] == '/')) {
String option = argument.Substring(1);
ProcessOption(argument, option, args, ref index);
} else {
index++;
fileNames.Add(argument);
}
}
switch (outputDirNames.Count) {
case 0: {
outputDirName = ".\\debug";
break;
}
case 1: {
outputDirName = (String)outputDirNames[0];
break;
}
default: {
Util.Error("Error: specified multiple output directories {0}",
new CollectionFormatter(outputDirNames));
break;
}
}
if((StageControl.GCType == StageControl.ReferenceCountingCollector)
&& StageControl.StructInheritance) {
Util.Abort("Error: RC Collector code has not been updated to "
+ "handle struct inheritance");
}
if((StageControl.GCType ==
StageControl.DeferredReferenceCountingCollector)
&& StageControl.StructInheritance) {
Util.Abort("Error: Deferred RC Collector code has not been updated to "
+ "handle struct inheritance");
}
}
private static void ProcessOption(String argument, String option,
String[] args, ref int index) {
String loweredOption = option.ToLower();
String optionValue;
if (IsOption(args, option, loweredOption, "entry:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(entryPoints, optionValue);
} else if (IsOption(args, option, loweredOption, "reference:",
ref index, out optionValue)
|| IsOption(args, option, loweredOption, "r:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(refFileNames, optionValue);
} else if (IsOption(args, option, loweredOption, "bartoklink:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(linkNames, optionValue);
} else if (IsOption(args, option, loweredOption, "override:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(overrideNames, optionValue);
} else if (IsOption(args, option, loweredOption, "overridedef:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(overrideDefNames, optionValue);
} else if (IsOption(args, option, loweredOption, "lib:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(libDirNames, optionValue);
} else if (IsOption(args, option, loweredOption, "out:",
ref index, out optionValue)) {
outputRootName = optionValue;
} else if (IsOption(args, option, loweredOption, "outdir:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(outputDirNames, optionValue);
} else if (IsOption(args, option, loweredOption, "skip:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(initializerSkips, optionValue);
} else if (IsOption(args, option, loweredOption, "substitute:",
ref index, out optionValue)) {
StageControl.substituteString = optionValue;
} else if (IsOption(args, option, loweredOption, "disable:",
ref index, out optionValue)) {
StageControl.disabledPhaseNames.Add(optionValue);
} else if (IsOption(args, option, loweredOption, "dynamicload:",
ref index, out optionValue)) {
AddSemicolonDelimitedNames(dynamicLoads, optionValue);
} else if (IsOption(args, option, loweredOption, "features:",
ref index, out optionValue)) {
StageControl.mixinConditionals =
StageControl.mixinConditionals + "," + optionValue;
} else if (IsOption(args, option, loweredOption, "noisymethod:",
ref index, out optionValue)) {
StageControl.noisyMethodNames.Add(optionValue);
//Util.Message("noisyMethodNames="
// + StageControl.noisyMethodNames);
} else if (IsOption(args, option, loweredOption, "debugmethod:",
ref index, out optionValue)) {
StageControl.debugMethodNames.Add(optionValue);
StageControl.noisyMethodNames.Add(optionValue);
//Util.Message("debugMethodNames="
// + StageControl.debugMethodNames);
} else if (IsOption(args, option, loweredOption, "verbosity:",
ref index, out optionValue)) {
Verbosity.FromString(optionValue);
} else if (IsOption(args, option, loweredOption, "marksweepgc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.MarkSweepCollector;
StageControl.GCLargeObjectSize = 2040;
StageControl.InlineSegregatedFreeList = true;
StageControl.InsertWriteBarrier = false;
} else if (IsOption(args, option, loweredOption, "semispacegc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.SemispaceCollector;
StageControl.InsertWriteBarrier = true;
} else if (IsOption(args, option, loweredOption, "slidinggc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.SlidingCollector;
StageControl.InsertWriteBarrier = true;
} else if (IsOption(args, option, loweredOption, "adaptivecopyinggc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.AdaptiveCopyingCollector;
StageControl.InsertWriteBarrier = true;
} else if (IsOption(args, option, loweredOption,
"referencecountinggc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.ReferenceCountingCollector;
StageControl.InsertWriteBarrier = false;
StageControl.GCInlineAllocations = false;
StageControl.mixinConditionals =
StageControl.mixinConditionals + ",ReferenceCountingGC";
if (StageControl.RCCollectorVerifyRefCounts) {
StageControl.UseVTableBits = true;
StageControl.mixinConditionals =
StageControl.mixinConditionals +
",ReferenceCountingGCVerification";
}
} else if (IsOption
(args, option, loweredOption, "deferredreferencecountinggc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.DeferredReferenceCountingCollector;
StageControl.InsertWriteBarrier = false;
StageControl.GCInlineAllocations = false;
StageControl.mixinConditionals =
StageControl.mixinConditionals + ",DeferredReferenceCountingGC";
if (StageControl.RCCollectorVerifyRefCounts) {
StageControl.UseVTableBits = true;
StageControl.mixinConditionals =
StageControl.mixinConditionals +
",DeferredReferenceCountingGCVerification";
}
} else if (IsOption(args, option, loweredOption, "concurrentmsgc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.ConcurrentMSCollector;
StageControl.GCLargeObjectSize = 2040;
StageControl.Wb = StageControl.WbCMS;
StageControl.GCInlineAllocations = false;
StageControl.InlineSegregatedFreeList = true;
StageControl.PreWriteBarrier = true;
StageControl.InsertWriteBarrier = true;
StageControl.GCInlineWriteBarrier = false;
StageControl.GCWriteBarrierTracksStaticFields = true;
StageControl.mixinConditionals =
StageControl.mixinConditionals + ",ConcurrentMSGC";
} else if (IsOption(args, option, loweredOption, "nullgc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.NullCollector;
StageControl.InsertWriteBarrier = false;
} else if (IsOption(args, option, loweredOption, "atomicrcgc",
ref index, out optionValue)) {
StageControl.GCType = StageControl.AtomicRCCollector;
StageControl.GCLargeObjectSize = 2040;
StageControl.Wb = StageControl.WbARC;
StageControl.GCInlineAllocations = false;
StageControl.InlineSegregatedFreeList = true;
StageControl.InsertWriteBarrier = true;
StageControl.GCInlineWriteBarrier = false;
StageControl.GCWriteBarrierTracksStaticFields = true;
} else if (IsOption(args, option, loweredOption, "minopt",
ref index, out optionValue)) {
StageControl.SsaOpts = false;
StageControl.IrInterfaceElim = false;
StageControl.DevirtualizeCall = false;
StageControl.IrTypeTestElimPunt = false;
StageControl.IrTypeTestElim = false;
StageControl.IrSimpleInliner = false;
// IR clean up optimizations
StageControl.IrDeadAssignmentSimple2 = false;
StageControl.IrCleanupStructOperations = false;
StageControl.IrShortCircuitBBlocks = false;
StageControl.IrTreeShakeLate = false;
StageControl.IrArrayLoadStoreOpt = false;
StageControl.IrConvertSimpleArrayAccess = false;
// from the backend
StageControl.RegAllocCoalesce = false;
StageControl.RegAllocSpill = StageControl.SpillOptimizeSinglePass;
StageControl.OptLirCompactify = false;
StageControl.OptLirGlobalConstantProp = false;
StageControl.OptLirLocalConstantProp = true;
StageControl.OptLirImproveCC = false;
StageControl.OptLirPeephole = false;
StageControl.OptLirReverseCSE = false;
StageControl.OptLirGlobalCopyProp = false;
StageControl.OptLirLocalCopyProp = true;
StageControl.LayoutLoopHeaderLast = false;
if (StageControl.SymbolicDebug) {
StageControl.OptimizeLocals = false;
}
} else if (IsOption(args, option, loweredOption, "nohiropt",
ref index, out optionValue)) {
StageControl.ABCD = false;
StageControl.DevirtualizeCall = false;
StageControl.IdentifyAsMethods = false;
StageControl.IrAttributeInliner = false;
StageControl.IrBBLocalCopyProp = false;
StageControl.IrCleanup = false;
StageControl.IrCleanupStructOperations = false;
StageControl.IrCloneLoopHeader = false;
StageControl.IrConvertOpt = false;
StageControl.IrDeadAssignmentSimple1 = false;
StageControl.IrDeadAssignmentSimple2 = false;
StageControl.IrInitStaticField = false;
StageControl.IrInterfaceElim = false;
StageControl.IrJumpElim = false;
StageControl.IrLoadStoreOpt = false;
StageControl.IrMultiPropSimple = false;
StageControl.IrPeepholeNull = false;
StageControl.IrRemoveDoubleCmp = false;
StageControl.IrReverseCopyProp = false;
StageControl.IrShortCircuitBBlocks = false;
StageControl.IrSimpleInliner = false;
StageControl.IrStoreChecks = false;
StageControl.IrTreeShakeLate = false;
StageControl.IrTypeTestElimPunt = false;
StageControl.SsaArraySimple = false;
StageControl.SsaDeadCode = false;
StageControl.SsaLoopInv = false;
StageControl.SsaNullCheck = false;
StageControl.SsaOpts = false;
StageControl.TypeInitRemoveEmptyCctors = false;
StageControl.UnmanagedStrings = false;
} else if (IsOption(args, option, loweredOption, "singularity",
ref index, out optionValue)) {
StageControl.SingSharpTemplateRemover = true;
StageControl.DisablePInvoke = true;
StageControl.StrictEcma = true;
StageControl.CustomAllocatorTypes = true;
StageControl.SurrogateBoxing = true;
StageControl.StructInheritance = true;
StageControl.IrTreeShakeCreatePointedToStructs = true;
StageControl.IrTreeShakeLate = false; // not tested
StageControl.TypeInitRemoveEmptyCctors = false; // not tested
StageControl.CheckNoHeapAllocation = true;
} else if (IsOption(args, option, loweredOption, "verbosehelp",
ref index, out optionValue)) {
PrintUsage();
StageControl.PrintUsage();
} else if (IsOption(args, option, loweredOption, "verbosehelpalpha",
ref index, out optionValue)) {
PrintUsage();
StageControl.PrintUsageAlpha();
} else if (IsOption(args, option, loweredOption, "x86",
ref index, out optionValue)) {
StageControl.TargetArch = StageControl.X86;
StageControl.Target64Bit = false;
} else if (IsOption(args, option, loweredOption, "x64",
ref index, out optionValue)) {
StageControl.TargetArch = StageControl.X64;
StageControl.Target64Bit = true;
} else if (IsOption(args, option, loweredOption, "help",
ref index, out optionValue)
|| IsOption(args, option, loweredOption, "?",
ref index, out optionValue)) {
PrintUsage();
} else if (IsOption
(args, option, loweredOption, "centralpt",
ref index, out optionValue)) {
StageControl.PTType = StageControl.CentralPT;
} else if (IsOption
(args, option, loweredOption, "centralpthimem",
ref index, out optionValue)) {
StageControl.PTType = StageControl.CentralPTHimem;
} else if (IsOption
(args, option, loweredOption, "flatdistributedpt",
ref index, out optionValue)) {
StageControl.PTType = StageControl.FlatDistributedPT;
} else if (IsOption
(args, option, loweredOption, "flatdistributedtestpt",
ref index, out optionValue)) {
StageControl.PTType = StageControl.FlatDistributedPTTest;
} else if (StageControl.SetOptionFromCommandLine(loweredOption)) {
index++;
} else if (loweredOption.StartsWith("stagecontrol")) {
Util.AbortUserCE("/stagecontrol no longer supported; "
+ "use the option directly");
} else {
Util.AbortUserCE("Unknown option: " + option);
}
}
private static bool IsOption(String[] args,
String option, String loweredOption,
String possibleOptionName,
ref int index, out String optionValue) {
if(possibleOptionName.EndsWith(":")) {
if(loweredOption.StartsWith(possibleOptionName)) {
index++;
if(option.Length == possibleOptionName.Length) {
// case: "/option: value"
optionValue = args[index++];
} else {
// case: "/option:value"
optionValue = option.Substring(possibleOptionName.Length);
}
return true;
}
} else {
if(loweredOption == possibleOptionName) {
index++;
optionValue = null;
return true;
}
}
optionValue = null;
return false;
}
private static void AddSemicolonDelimitedNames(ArrayList names,
String argument) {
int index = 0;
StringBuilder buf = new StringBuilder();
while (index < argument.Length) {
if (argument[index] != ';') {
buf.Append(argument[index]);
index++;
}
else {
if (buf.Length > 0) {
names.Add(buf.ToString());
buf = new StringBuilder();
}
index++;
}
}
names.Add(buf.ToString());
}
public static void PrintUsage() {
if (alreadyPrintedUsage) {
return;
}
alreadyPrintedUsage = true;
Util.Message(
@"Usage:
bartok [options] files
Bartok main options (case insensitive):
/entry: <method1>;<method2>;... specify entry points
/reference: <file1>;<file2>;... reference metadata from assembly files
/r: <file1>;<file2>;... short form of /reference:
/bartoklink: <file1>;<file2>;... reference precompiled object files
/override: <file1>;<file2>;... files overriding /r: metadata
/lib: <dir1>;<dir2>;... additional dirs to search for references
/out: <file> output file name
/outdir: <dir> dir for output .exe, asm, obj, etc.
(defaults to .\\debug)
/skip: <type1>;<type2>;... specify type initializers to disable
if building static ordering
/substitute:<oldname1>=<newname1>, rename TypeRefs before performing lookup
<oldname2>=<newname2>,...
/disable:<phasename> disable a phase
/dynamicload:<typename> make type available for dynamic loading
/features:<???> << TODO >>
/noisymethod:<methname> enable noisy output for meth
/debugmethod:<methname> enable debug+noisy output for meth
/verbosity:<noiselevel> set output level {Silence,PerPhase,
PerClass,PerMethod,PerBlock,
PerInstruction} (defaults to PerPhase)
/marksweepgc compile for mark-sweep collector
/semispacegc compile for semispace collector
/slidinggc compile for sliding collector
/adaptivecopyinggc compile for semispace-sliding hybrid
collector
/referencecountinggc compile for reference counting collector
/deferredreferencecountinggc compile for deferred reference counting collector
/concurrentmsgc compile for concurrent mark-sweep
collector
/nullgc compile for no collector
/minopt disable most optimizations
/nohiropt disable all HIR optimizations
/singularity set default Singularity options
/verbosehelp help message including stage control
options by category
/verbosehelpalpha help message including stage control
options in alphabetical order
/help or /? help message");
}
}
internal class MetaDataOutput : Bartok.MSIL.IMetaDataOutput {
public TextWriter Log { get { return Util.Log; } }
public TextWriter ErrorOut { get { return Util.ErrorOut; } }
public TextWriter WarnOut { get { return Util.WarnOut; } }
public void Error(string msg)
{
Util.Error(msg);
}
public void Error(string format, params Object[] objs)
{
Util.Error(format, objs);
}
public void ErrorDetail(string msg)
{
Util.ErrorDetail(msg);
}
public void Warn(string msg)
{
Util.Warn(msg);
}
public void Warn(string format, params Object[] objs)
{
Util.Warn(format, objs);
}
public void WarnDetail(string msg)
{
Util.WarnDetail(msg);
}
public void Message(string msg)
{
Util.Message(msg);
}
}
}