public IActionCode LdMatcherBuffer() { emit .Do(ldCursor) .Ldfld((ScanCursor c) => c.Buffer); return(this); }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; Ref <Labels> END = emit.Labels.Generate().GetRef(); Ref <Labels>[] labels = new Ref <Labels> [rows]; for (int i = 0; i != rows; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(labels) .Ldc_I4(-1) .Br(END) ; var columnRange = new IntInterval(0, columns - 1); var columnFrequency = new UniformIntFrequency(columnRange); for (int i = 0; i != rows; ++i) { var switchEmitter = SwitchGenerator.Sparse(table.GetRow(i), columnRange, columnFrequency); emit.Label(labels[i].Def); switchEmitter.Build(emit, LdCol, SwitchGenerator.LdValueAction(END)); } return(emit.Label(END.Def)); }
private IActionCode LdActionArgument(int index) { emit = emit .Do(LdRuleArgs) .Do(LdArgsStart); // Optmization for "+ 0". if (index != 0) { emit .Ldc_I4(index) .Add(); } if (typeof(Msg).IsValueType) { emit = emit .Ldelema(emit.Types.Import(typeof(Msg))); } else { emit = emit .Ldelem_Ref(); } emit = emit .Ldfld((Msg msg) => msg.Value) ; return(this); }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; Ref<Labels> END = emit.Labels.Generate().GetRef(); Ref<Labels>[] labels = new Ref<Labels>[rows]; for (int i = 0; i != rows; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(labels) .Ldc_I4(-1) .Br(END) ; var columnRange = new IntInterval(0, columns - 1); var columnFrequency = new UniformIntFrequency(columnRange); for (int i = 0; i != rows; ++i) { var switchEmitter = SwitchGenerator.Sparse(table.GetRow(i), columnRange, columnFrequency); emit.Label(labels[i].Def); switchEmitter.Build(emit, LdCol, SwitchGenerator.LdValueAction(END)); } return emit .Label(END.Def); }
protected override void DoBuild(EmitSyntax emit, Pipe<EmitSyntax> ldvalue, SwitchGeneratorAction action) { var labels = new Ref<Labels>[map.Length]; for (int i = 0; i != labels.Length; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(ldvalue) .Switch(labels) ; action(emit, defaultValue); for (int i = 0; i != labels.Length; ++i) { emit.Label(labels[i].Def); action(emit, map[i]); } }
protected override void DoBuild(EmitSyntax emit, Pipe <EmitSyntax> ldvalue, SwitchGeneratorAction action) { var labels = new Ref <Labels> [map.Length]; for (int i = 0; i != labels.Length; ++i) { labels[i] = emit.Labels.Generate().GetRef(); } emit .Do(ldvalue) .Switch(labels) ; action(emit, defaultValue); for (int i = 0; i != labels.Length; ++i) { emit.Label(labels[i].Def); action(emit, map[i]); } }
public ILNfaCompiler(AstNode node, EmitSyntax emit, ILCompilerSettings settings) { this.Scanner = new StemScanner(); this.emit = emit; this.settings = settings; var labels = emit.Labels; NEXT_THREAD = labels.Generate(); RESUME_ALL = labels.Generate(); NEXT_INPUT = labels.Generate(); THREAD_SUSPEND = labels.Generate(); THREAD_DISPATCH = labels.Generate(); var LABEL0 = labels.Generate(); var LABEL1 = labels.Generate(); var POSTCOMPILEINIT = labels.Generate(); var POSTCOMPILEINIT_BACK = labels.Generate(); var locals = emit.Locals; slots = locals.Generate(); labelIndexToLocation = locals.Generate(); intTmp = locals.Generate(); threadTmp = locals.Generate(); INfaVM code = this; this.inputPump = new ArrayLoopGenerator( valueType: emit.Types.Int32, ldarray: settings.LdInput, body: il => il .Do(matchedStack.Clear) .Br(RESUME_ALL.GetRef()) ); this.runningStack = new StackGenerator(emit, typeof(Thread)); this.suspendedStack = new StackGenerator(emit, typeof(Thread)); this.matchedStack = new StackGenerator(emit, typeof(Thread)); this.tmpStack = new StackGenerator(emit, typeof(Thread), nullContainer: true); emit .Local(intTmp, emit.Types.Int32) .Local(slots, emit.Types.Import(typeof(int[]))) .Local(labelIndexToLocation, emit.Types.Import(typeof(int[]))) .Br(POSTCOMPILEINIT.GetRef()) .Label(POSTCOMPILEINIT_BACK) .Local(threadTmp, emit.Types.Import(typeof(Thread))) .Ldloca(threadTmp.GetRef()) .Initobj(emit.Types.Import(typeof(Thread))) .Do(inputPump.EmitInitialization) ; new RegularNfaVMCompiler().Compile(node, code); int LabelCount = Math.Max(1, indexToLabel.Count); this.runningStack.SetSize(LabelCount); this.suspendedStack.SetSize(LabelCount); this.matchedStack.SetSize(LabelCount); this.tmpStack.SetSize(LabelCount); emit .Label(POSTCOMPILEINIT) .Do(runningStack.Init) .Do(suspendedStack.Init) .Do(matchedStack.Init) .Do(tmpStack.Init) .Ldc_I4(slotCount) .Newarr(emit.Types.Int32) .Stloc(slots.GetRef()) .Ldc_I4(LabelCount) .Newarr(emit.Types.Int32) .Stloc(labelIndexToLocation.GetRef()) // Fill labelIndexToLocation with -1 : .Ldc_I4(LabelCount).Stloc(intTmp.GetRef()) .Label(LABEL1) .Ldloc(intTmp.GetRef()) .Ldc_I4_0() .Beq(LABEL0.GetRef()) .Ldloc(intTmp.GetRef()) .Ldc_I4(1) .Sub() .Stloc(intTmp.GetRef()) .Ldloc(labelIndexToLocation.GetRef()) .Ldloc(intTmp.GetRef()) .Ldc_I4(int.MinValue) .Stelem_I4() .Br(LABEL1.GetRef()) .Label(LABEL0) .Br(POSTCOMPILEINIT_BACK.GetRef()); // Save thread as suspended (stack should already contain label index to suspend) emit.Label(THREAD_SUSPEND); StThreadValueByRuntimeLabelIndex(); emit // Don't add thread if same thread (same label index // with current input location) already exists in a list. .Ldloc(labelIndexToLocation.GetRef()) .Ldloca(threadTmp.GetRef()) .Ldfld(LabelIndexField) .Ldelem_I4() .Ldloc(inputPump.Index.GetRef()) .Beq(NEXT_THREAD.GetRef()) // Mark label index as visited .Ldloc(labelIndexToLocation.GetRef()) .Ldloca(threadTmp.GetRef()) .Ldfld(LabelIndexField) .Ldloc(inputPump.Index.GetRef()) .Stelem_I4() ; suspendedStack.PushFrom(emit, threadTmp); emit .Br(NEXT_THREAD.GetRef()) .Label(RESUME_ALL) .Swap(suspendedStack.Stack, runningStack.Stack, tmpStack.Stack) .Swap(suspendedStack.Index, runningStack.Index, tmpStack.Index) .Label(NEXT_THREAD) ; runningStack .StackLoop( emit, (emit2, thread) => { emit2 .Ldloca(thread.GetRef()) .Ldfld(LabelIndexField) .Label(THREAD_DISPATCH) .Switch(indexToLabel.Select(def => def.GetRef()).ToArray()) .Br(settings.FAILURE.GetRef()); }) ; emit .Br(NEXT_INPUT.GetRef()) ; emit .Label(NEXT_INPUT) ; inputPump.EmitLoopPass(emit, false); emit // Check if there are matched threads: .Do(matchedStack.LdCount) .Ldc_I4_0() .Beq(settings.FAILURE.GetRef()) .Br(settings.SUCCESS.GetRef()); }
public void Build( EmitSyntax emit, Pipe <EmitSyntax> ldCursor, Pipe <EmitSyntax> ldTokenPtr) { var labels = emit.Labels; var locals = emit.Locals; var RETURN = labels.Generate(); var valueTmp = locals.Generate(); var tokenId = locals.Generate(); emit .Local(valueTmp, emit.Types.Object) .Ldnull() .Stloc(valueTmp.GetRef()) .Local(tokenId, emit.Types.Int32) .Ldc_I4(-1) .Stloc(tokenId.GetRef()) ; int ruleCount = data.Grammar.Conditions.Sum(cond => cond.Matchers.Count); var action = new Ref <Labels> [ruleCount]; for (int i = 0; i != ruleCount; ++i) { action[i] = labels.Generate().GetRef(); } emit .Do(ldCursor) .Ldfld((ScanCursor c) => c.CurrentActionId) .Switch(action) ; foreach (var cond in data.Grammar.Conditions) { var contextResolver = new ContextCode( emit, il => il .Do(ldCursor) .Ldfld((ScanCursor c) => c.RootContext), null, data, cond.ContextProvider); IActionCode code = new MatcherCode( emit, contextResolver, ldCursor, declaringType, data.Grammar.Conditions, RETURN.GetRef()); foreach (var matcher in cond.Matchers) { emit .Label(action[matcher.Index].Def) .Ldc_I4(matcher.Outcome == null ? -1 : matcher.Outcome.Index) .Stloc(tokenId.GetRef()) ; var productionBinding = matcher.Joint.The <CilMatcher>(); code = code .Do(productionBinding.Context.Load) .Do(productionBinding.ActionBuilder); } } // Load null value for incorrectly implemented actions emit.Ldnull(); emit .Label(RETURN) .Stloc(valueTmp.GetRef()) .Do(ldTokenPtr) .Ldloc(valueTmp.GetRef()) .Stind_Ref() .Ldloc(tokenId.GetRef()) .Ret() ; }
public void BuildBody( EmitSyntax emit, LanguageData data, Ref <Args> ruleId, Ref <Args> ruleArgs, Ref <Args> argsStart, Ref <Args> ctx, Ref <Args> lookbackStart) { Def <Labels> returnLabel = emit.Labels.Generate(); var contextCode = new ContextCode( emit, il => il.Ldarg(ctx), il => il.Ldarg(lookbackStart), data, data.Grammar.GlobalContextProvider, data.LocalParseContexts); IActionCode code = new ProductionCode( emit, contextCode, ldRuleArgs: il => il.Ldarg(ruleArgs), ldArgsStart: il => il.Ldarg(argsStart), returnLabel: returnLabel); var defaultLabel = emit.Labels.Generate(); var endWithSingleResultLabel = emit.Labels.Generate(); var jumpTable = new Ref <Labels> [data.Grammar.Productions.Count]; for (int i = 0; i != jumpTable.Length; ++i) { jumpTable[i] = emit.Labels.Generate().GetRef(); } emit .Do(il => il.Ldarg(ruleId)) .Switch(jumpTable) .Br(defaultLabel.GetRef()); foreach (var prod in data.Grammar.Productions) { emit.Label(jumpTable[prod.Index].Def); if (0 == prod.Actions.Count) { // Augumented start rule has null action and should never be invoked. // Also it is possible that for some platforms production may have default // action. emit.Ldnull(); } else { foreach (var action in prod.Actions) { code = GenerateActionCode(code, action); } } emit.Br(endWithSingleResultLabel.GetRef()); } emit .Label(defaultLabel) .Ldnull() .Label(endWithSingleResultLabel) .Label(returnLabel) .Ret(); }
public IActionCode Emit(Pipe <EmitSyntax> pipe) { emit = emit.Do(pipe); return(this); }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; // Dispatch info index Ref<Labels> DISP_INFO = emit.Labels.Generate().GetRef(); // Return no-data result Ref<Labels> RET_NONE = emit.Labels.Generate().GetRef(); // Exit Ref<Labels> END = emit.Labels.Generate().GetRef(); Ref<Labels>[] rowLabels = new Ref<Labels>[rows]; for (int i = 0; i != rows; ++i) { rowLabels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(rowLabels) .Br(RET_NONE) ; for (int i = 0; i != rows; ++i) { emit .Label(rowLabels[i].Def) .Ldc_I4(table.RowToOffset[i]) .Br(DISP_INFO); } int infoCount = table.Info.Count; var infoLabels = new Ref<Labels>[infoCount]; for (int i = 0; i != infoCount; ++i) { infoLabels[i] = emit.Labels.Generate().GetRef(); } emit .Label(DISP_INFO.Def) // Row offset should already be in stack .Do(LdCol) .Add() .Switch(infoLabels) .Br(RET_NONE); for (int i = 0; i != infoCount; ++i) { emit .Label(infoLabels[i].Def) .Do(LdRow) .Ldc_I4(table.Check[i]) .Bne_Un(RET_NONE) .Ldc_I4(table.Info[i]) .Br(END) ; } emit .Label(RET_NONE.Def) .Ldc_I4(0) ; return emit.Label(END.Def); }
public void BuildBody( EmitSyntax emit, LanguageData data, Ref<Args> ruleId, Ref<Args> ruleArgs, Ref<Args> argsStart, Ref<Args> ctx, Ref<Args> lookbackStart) { Def<Labels> returnLabel = emit.Labels.Generate(); var contextCode = new ContextCode( emit, il => il.Ldarg(ctx), il => il.Ldarg(lookbackStart), data, data.Grammar.GlobalContextProvider, data.LocalParseContexts); IActionCode code = new ProductionCode( emit, contextCode, ldRuleArgs: il => il.Ldarg(ruleArgs), ldArgsStart: il => il.Ldarg(argsStart), returnLabel: returnLabel); var defaultLabel = emit.Labels.Generate(); var endWithSingleResultLabel = emit.Labels.Generate(); var jumpTable = new Ref<Labels>[data.Grammar.Productions.Count]; for (int i = 0; i != jumpTable.Length; ++i) { jumpTable[i] = emit.Labels.Generate().GetRef(); } emit .Do(il => il.Ldarg(ruleId)) .Switch(jumpTable) .Br(defaultLabel.GetRef()); foreach (var prod in data.Grammar.Productions) { emit.Label(jumpTable[prod.Index].Def); if (0 == prod.Actions.Count) { // Augumented start rule has null action and should never be invoked. // Also it is possible that for some platforms production may have default // action. emit.Ldnull(); } else { foreach (var action in prod.Actions) { code = GenerateActionCode(code, action); } } emit.Br(endWithSingleResultLabel.GetRef()); } emit .Label(defaultLabel) .Ldnull() .Label(endWithSingleResultLabel) .Label(returnLabel) .Ret(); }
public void Build( EmitSyntax emit, Pipe<EmitSyntax> ldCursor, Pipe<EmitSyntax> ldTokenPtr) { var labels = emit.Labels; var locals = emit.Locals; var RETURN = labels.Generate(); var valueTmp = locals.Generate(); var tokenId = locals.Generate(); emit .Local(valueTmp, emit.Types.Object) .Ldnull() .Stloc(valueTmp.GetRef()) .Local(tokenId, emit.Types.Int32) .Ldc_I4(-1) .Stloc(tokenId.GetRef()) ; int ruleCount = data.Grammar.Conditions.Sum(cond => cond.Matchers.Count); var action = new Ref<Labels>[ruleCount]; for (int i = 0; i != ruleCount; ++i) { action[i] = labels.Generate().GetRef(); } emit .Do(ldCursor) .Ldfld((ScanCursor c) => c.CurrentActionId) .Switch(action) ; foreach (var cond in data.Grammar.Conditions) { var contextResolver = new ContextCode( emit, il => il .Do(ldCursor) .Ldfld((ScanCursor c) => c.RootContext), null, data, cond.ContextProvider); IActionCode code = new MatcherCode( emit, contextResolver, ldCursor, declaringType, data.Grammar.Conditions, RETURN.GetRef()); foreach (var matcher in cond.Matchers) { emit .Label(action[matcher.Index].Def) .Ldc_I4(matcher.Outcome == null ? -1 : matcher.Outcome.Index) .Stloc(tokenId.GetRef()) ; var productionBinding = matcher.Joint.The<CilMatcher>(); code = code .Do(productionBinding.Context.Load) .Do(productionBinding.ActionBuilder); } } // Load null value for incorrectly implemented actions emit.Ldnull(); emit .Label(RETURN) .Stloc(valueTmp.GetRef()) .Do(ldTokenPtr) .Ldloc(valueTmp.GetRef()) .Stind_Ref() .Ldloc(tokenId.GetRef()) .Ret() ; }
public EmitSyntax Build(EmitSyntax emit) { int rows = table.RowCount; int columns = table.ColumnCount; // Dispatch info index Ref <Labels> DISP_INFO = emit.Labels.Generate().GetRef(); // Return no-data result Ref <Labels> RET_NONE = emit.Labels.Generate().GetRef(); // Exit Ref <Labels> END = emit.Labels.Generate().GetRef(); Ref <Labels>[] rowLabels = new Ref <Labels> [rows]; for (int i = 0; i != rows; ++i) { rowLabels[i] = emit.Labels.Generate().GetRef(); } emit .Do(LdRow) .Switch(rowLabels) .Br(RET_NONE) ; for (int i = 0; i != rows; ++i) { emit .Label(rowLabels[i].Def) .Ldc_I4(table.RowToOffset[i]) .Br(DISP_INFO); } int infoCount = table.Info.Count; var infoLabels = new Ref <Labels> [infoCount]; for (int i = 0; i != infoCount; ++i) { infoLabels[i] = emit.Labels.Generate().GetRef(); } emit .Label(DISP_INFO.Def) // Row offset should already be in stack .Do(LdCol) .Add() .Switch(infoLabels) .Br(RET_NONE); for (int i = 0; i != infoCount; ++i) { emit .Label(infoLabels[i].Def) .Do(LdRow) .Ldc_I4(table.Check[i]) .Bne_Un(RET_NONE) .Ldc_I4(table.Info[i]) .Br(END) ; } emit .Label(RET_NONE.Def) .Ldc_I4(0) ; return(emit.Label(END.Def)); }