public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { //Do not optimize the macros arguments! They should be passed to the macro in their original form. // the macro should decide whether or not to apply AST-optimization to the arguments or not. expr = null; return false; }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { Subject = _GetOptimizedNode(target, Subject); Type = (AstTypeExpr) _GetOptimizedNode(target, Type); expr = null; var constType = Type as AstConstantTypeExpression; if (constType == null) return false; //Constant cast var constSubject = Subject as AstConstant; if (constSubject != null) return _tryOptimizeConstCast(target, constSubject, constType, out expr); //Redundant cast AstTypecast castSubject; AstConstantTypeExpression sndCastType; if ((castSubject = Subject as AstTypecast) != null && (sndCastType = castSubject.Type as AstConstantTypeExpression) != null) { if (Engine.StringsAreEqual(sndCastType.TypeExpression, constType.TypeExpression)) { //remove the outer cast. expr = castSubject; return true; } } return false; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if (Elements.Count == 0) { target.Emit(Position,OpCode.newobj, 0, "Hash"); } else { foreach (var element in Elements) { if (element is AstConstant) throw new PrexoniteException( String.Concat( "Hashes are built from key-value pairs, not constants like ", element, ". [File: ", File, ", Line: ", Line, "]")); element.EmitCode(target,stackSemantics); } if(stackSemantics == StackSemantics.Effect) return; target.EmitStaticGetCall(Position, Elements.Count, "Hash", "Create", false); } }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Effect) return; target.EmitNull(Position); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Effect) return; target.Emit(Position,OpCode.ldr_type, TypeExpression); }
private void _reportUnresolved(CompilerTarget target) { target.Loader.ReportMessage( Message.Error( string.Format(Resources.AstUnresolved_The_symbol__0__has_not_been_resolved_, Id), Position, MessageClasses.SymbolNotResolved)); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Value) throw new NotSupportedException("Using blocks do not produce values and can thus not be used as expressions."); if (_resourceExpression == null) throw new PrexoniteException("AstUsing requires Expression to be initialized."); var tryNode = new AstTryCatchFinally(Position, this); var vContainer = _block.CreateLabel("container"); target.Function.Variables.Add(vContainer); //Try block => Container = {Expression}; {Block}; var setCont = target.Factory.Call(Position, EntityRef.Variable.Local.Create(vContainer),PCall.Set); setCont.Arguments.Add(_resourceExpression); var getCont = target.Factory.Call(Position, EntityRef.Variable.Local.Create(vContainer)); var tryBlock = tryNode.TryBlock; tryBlock.Add(setCont); tryBlock.AddRange(_block); //Finally block => dispose( Container ); var dispose = target.Factory.Call(Position, EntityRef.Command.Create(Engine.DisposeAlias)); dispose.Arguments.Add(getCont); tryNode.FinallyBlock.Add(dispose); //Emit code! tryNode.EmitEffectCode(target); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { var labelNs = @"Or\" + Guid.NewGuid().ToString("N"); var trueLabel = @"True\" + labelNs; var falseLabel = @"False\" + labelNs; var evalLabel = @"Eval\" + labelNs; EmitCode(target, trueLabel, falseLabel); if (stackSemantics == StackSemantics.Value) { target.EmitLabel(Position, falseLabel); target.EmitConstant(Position, false); target.EmitJump(Position, evalLabel); target.EmitLabel(Position, trueLabel); target.EmitConstant(Position, true); target.EmitLabel(Position, evalLabel); } else { Debug.Assert(stackSemantics == StackSemantics.Effect); target.EmitLabel(Position, falseLabel); target.EmitLabel(Position, trueLabel); } }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { //Jumps need special treatment for label resolution if (Instruction.Arguments == -1) { switch (Instruction.OpCode) { case OpCode.jump: target.EmitJump(Position, Instruction.Id); break; case OpCode.jump_t: target.EmitJumpIfTrue(Position, Instruction.Id); break; case OpCode.jump_f: target.EmitJumpIfFalse(Position, Instruction.Id); break; case OpCode.leave: target.EmitLeave(Position, Instruction.Id); break; default: goto emitNormally; } } else goto emitNormally; return; emitNormally: target.Emit(Position, Instruction); }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { //Optimize condition _OptimizeNode(target, ref Condition); // Invert condition when unary logical not AstIndirectCall unaryCond; while (Condition.IsCommandCall(Commands.Core.Operators.LogicalNot.DefaultAlias, out unaryCond)) { Condition = unaryCond.Arguments[0]; IsNegative = !IsNegative; } //Constant conditions if (Condition is AstConstant) { var constCond = (AstConstant) Condition; PValue condValue; if ( !constCond.ToPValue(target).TryConvertTo( target.Loader, PType.Bool, out condValue)) expr = null; else if (((bool) condValue.Value) ^ IsNegative) expr = IfExpression; else expr = ElseExpression; return expr != null; } expr = null; return false; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if (Expression == null) throw new PrexoniteException("Expression must be assigned."); Expression.EmitValueCode(target); target.Emit(Position,OpCode.@throw); if (stackSemantics == StackSemantics.Value) target.Emit(Position,OpCode.ldc_null); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if (Key == null) throw new PrexoniteException("AstKeyValuePair.Key must be initialized."); if (Value == null) throw new ArgumentNullException("target"); var call = target.Factory.Call(Position, EntityRef.Command.Create(Engine.PairAlias)); call.Arguments.Add(Key); call.Arguments.Add(Value); call.EmitCode(target, stackSemantics); }
/// <summary> /// Creates a new macro expansion session for the specified compiler target. /// </summary> /// <param name = "target">The target to expand macros in.</param> public MacroSession([NotNull] CompilerTarget target) { if(target == null) throw new ArgumentNullException("target"); _target = target; _astFactory = _target.Factory; _globalSymbols = SymbolStore.Create(_target.Loader.TopLevelSymbols); _outerVariables = new ReadOnlyCollectionView<string>(_target.OuterVariables); _buildCommandToken = target.Loader.RequestBuildCommands(); }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { expr = null; var isConstant = true; var buffer = new StringBuilder(TypeId); buffer.Append("("); //Optimize arguments AstExpr oArg; foreach (var arg in Arguments.ToArray()) { oArg = _GetOptimizedNode(target, arg); if (!ReferenceEquals(oArg, arg)) { Arguments.Remove(arg); Arguments.Add(oArg); } var constValue = oArg as AstConstant; var constType = oArg as AstConstantTypeExpression; if (constValue == null && constType == null) { isConstant = false; } else if (isConstant) { if (constValue != null) { buffer.Append('"'); buffer.Append( StringPType.Escape( constValue.ToPValue(target).CallToString(target.Loader))); buffer.Append('"'); } else //if(constType != null) buffer.Append(constType.TypeExpression); buffer.Append(","); } } if (!isConstant) return false; buffer.Remove(buffer.Length - 1, 1); //remove , or ( if (Arguments.Count != 0) buffer.Append(")"); //Add ) if necessary expr = new AstConstantTypeExpression(File, Line, Column, buffer.ToString()); return true; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Effect) return; if (Expression == null) throw new PrexoniteException("CreateCoroutine node requires an Expression."); Expression.EmitValueCode(target); foreach (var argument in _arguments) argument.EmitValueCode(target); target.Emit(Position,OpCode.newcor, _arguments.Count); }
/// <summary> /// Emits code responsible for changing the variables identity. /// </summary> /// <param name = "target">The target to compile to</param> private void _emitNewDeclareCode(CompilerTarget target) { _ensureValid(); //create command call // unbind(->variable) var unlinkCall = new AstIndirectCall(Position, PCall.Get, new AstReference(Position, EntityRef.Command.Create(Engine.UnbindAlias))); var targetRef = new AstReference(Position, EntityRef.Variable.Local.Create(Id)); unlinkCall.Arguments.Add(targetRef); //Optimize call and emit code var call = (AstExpr) unlinkCall; _OptimizeNode(target, ref call); call.EmitEffectCode(target); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Effect) return; Subject.EmitValueCode(target); var constType = Type as AstConstantTypeExpression; if (constType != null) target.Emit(Position,OpCode.cast_const, constType.TypeExpression); else { Type.EmitValueCode(target); target.Emit(Position,OpCode.cast_arg); } }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if (stackSemantics == StackSemantics.Effect) return; PFunction targetFunction; MetaEntry sharedNamesEntry; if (target.Loader.ParentApplication.TryGetFunction(_implementation.Id, _implementation.ModuleName, out targetFunction) && (!targetFunction.Meta.TryGetValue(PFunction.SharedNamesKey, out sharedNamesEntry) || !sharedNamesEntry.IsList || sharedNamesEntry.List.Length == 0)) target.Emit(Position,OpCode.ldr_func, _implementation.Id, target.ToInternalModule(_implementation.ModuleName)); else target.Emit(Position,OpCode.newclo, _implementation.Id, target.ToInternalModule(_implementation.ModuleName)); }
protected override void EmitGetCode(CompilerTarget target, StackSemantics stackSemantics) { var constType = TypeExpr as AstConstantTypeExpression; var justEffect = stackSemantics == StackSemantics.Effect; if (constType != null) { EmitArguments(target); target.EmitStaticGetCall(Position, Arguments.Count, constType.TypeExpression, _memberId, justEffect); } else { TypeExpr.EmitValueCode(target); target.EmitConstant(Position, _memberId); EmitArguments(target); target.EmitGetCall(Position, Arguments.Count + 1, PType.StaticCallFromStackId, justEffect); } }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { expr = null; _typeExpr = (AstTypeExpr) _GetOptimizedNode(target, _typeExpr); //Optimize arguments for (var i = 0; i < _arguments.Count; i++) { var arg = _arguments[i]; var oArg = _GetOptimizedNode(target, arg); if (ReferenceEquals(oArg, arg)) continue; _arguments[i] = oArg; } return false; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Effect) return; if (Constant == null) target.EmitNull(Position); else switch (Type.GetTypeCode(Constant.GetType())) { case TypeCode.Boolean: target.EmitConstant(Position, (bool) Constant); break; case TypeCode.Int16: case TypeCode.Byte: case TypeCode.Int32: case TypeCode.UInt16: case TypeCode.UInt32: target.EmitConstant(Position, (int) Constant); break; case TypeCode.Single: case TypeCode.Double: target.EmitConstant(Position, (double) Constant); break; case TypeCode.String: target.EmitConstant(Position, (string) Constant); break; default: var moduleName = Constant as ModuleName; if (moduleName != null) { target.EmitConstant(Position, moduleName); } else { throw new PrexoniteException( "Prexonite does not support constants of type " + Constant.GetType().Name + "."); } break; } }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { foreach (var arg in Elements.ToArray()) { if (arg == null) throw new PrexoniteException( "Invalid (null) argument in ListLiteral node (" + ToString() + ") detected at position " + Elements.IndexOf(arg) + "."); var oArg = _GetOptimizedNode(target, arg); if (!ReferenceEquals(oArg, arg)) { var idx = Elements.IndexOf(arg); Elements.Insert(idx, oArg); Elements.RemoveAt(idx + 1); } } expr = null; return false; }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { expr = null; //Optimize arguments for (var i = 0; i < Arguments.Count; i++) { var arg = Arguments[i]; if (arg == null) throw new PrexoniteException( "Invalid (null) argument in GetSet node (" + ToString() + ") detected at position " + Arguments.IndexOf(arg) + "."); var oArg = _GetOptimizedNode(target, arg); if (!ReferenceEquals(oArg, arg)) Arguments[i] = oArg; } return false; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { if(stackSemantics == StackSemantics.Value) throw new NotSupportedException("Return nodes cannot be used with value stack semantics. (They don't produce any values)"); var warned = false; if (target.Function.Meta[Coroutine.IsCoroutineKey].Switch) _warnInCoroutines(target, ref warned); if (Expression != null) { _OptimizeNode(target, ref Expression); if (ReturnVariant == ReturnVariant.Exit) { _emitTailCallExit(target); return; } } switch (ReturnVariant) { case ReturnVariant.Exit: target.Emit(Position,OpCode.ret_exit); break; case ReturnVariant.Set: if (Expression == null) throw new PrexoniteException("Return assignment requires an expression."); Expression.EmitValueCode(target); target.Emit(Position,OpCode.ret_set); break; case ReturnVariant.Continue: if (Expression != null) { Expression.EmitValueCode(target); target.Emit(Position,OpCode.ret_set); _warnInCoroutines(target, ref warned); } target.Emit(Position,OpCode.ret_continue); break; case ReturnVariant.Break: target.Emit(Position,OpCode.ret_break); break; } }
public static bool TryCreateConstant( CompilerTarget target, ISourcePosition position, PValue value, out AstExpr expr) { expr = null; if (value.Type is ObjectPType) target.Loader.Options.ParentEngine.CreateNativePValue(value.Value); if (value.Type is IntPType || value.Type is RealPType || value.Type is BoolPType || value.Type is StringPType || value.Type is NullPType || _isModuleName(value)) expr = new AstConstant(position.File, position.Line, position.Column, value.Value); else //Cannot represent value in a constant instruction return false; return true; }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { //instantiate macro for the current target MacroSession session = null; try { //Acquire current macro session session = target.AcquireMacroSession(); //Expand macro var justEffect = stackSemantics == StackSemantics.Effect; var node = session.ExpandMacro(this, justEffect); //Emit generated code node.EmitCode(target, stackSemantics); } finally { if (session != null) target.ReleaseMacroSession(session); } }
public override bool TryOptimize(CompilerTarget target, out AstExpr expr) { expr = null; //Optimize arguments for (var i = 0; i < _expressions.Count; i++) { var arg = _expressions[i]; if (arg == null) throw new PrexoniteException( "Invalid (null) argument in GetSet node (" + ToString() + ") detected at position " + _expressions.IndexOf(arg) + "."); var oArg = _GetOptimizedNode(target, arg); if (!ReferenceEquals(oArg, arg)) _expressions[i] = oArg; } var nonNullExpressions = _expressions.Where(_exprIsNotNull).ToArray(); _expressions.Clear(); _expressions.AddRange(nonNullExpressions); if (_expressions.Count == 1) { var pExpr = _expressions[0]; expr = pExpr is AstPlaceholder ? ((AstPlaceholder) pExpr).IdFunc() : pExpr; return true; } else if (_expressions.Count == 0) { expr = new AstNull(File, Line, Column); return true; } else { return false; } }
protected override void DoEmitCode(CompilerTarget target, string trueLabel, string falseLabel) { var labelNs = @"Or\" + Guid.NewGuid().ToString("N"); var nextLabel = @"Next\" + labelNs; foreach (var expr in Conditions) { var and = expr as AstLogicalAnd; if (and != null) { and.EmitCode(target, trueLabel, nextLabel); //ResolveOperator pending jumps to Next target.EmitLabel(Position, nextLabel); target.FreeLabel(nextLabel); //Future references of to nextLabel will be resolved in the next iteration } else { expr.EmitValueCode(target); target.EmitJumpIfTrue(Position, trueLabel); } } target.EmitJump(Position, falseLabel); }
private bool _optimizeConditionalReturnExpression(CompilerTarget target) { var cond = Expression as AstConditionalExpression; if (cond == null) return false; // return if( cond ) // expr1 // else // expr2 var retif = new AstCondition(Position, target.CurrentBlock, cond.Condition, cond.IsNegative); var ret1 = new AstReturn(File, Line, Column, ReturnVariant) { Expression = cond.IfExpression }; retif.IfBlock.Add(ret1); var ret2 = new AstReturn(File, Line, Column, ReturnVariant) { Expression = cond.ElseExpression }; //not added to the condition retif.EmitEffectCode(target); // if( cond ) // return expr1 ret2.EmitEffectCode(target); // return expr2 //ret1 and ret2 will continue optimizing return true; }
private static bool _isStacklessRecursionPossible(CompilerTarget target, AstIndirectCall symbol) { var refNode = symbol.Subject as AstReference; if (refNode == null) return false; EntityRef.Function funcRef; if (!refNode.Entity.TryGetFunction(out funcRef)) return false; if (funcRef.Id != target.Function.Id) return false; if (funcRef.ModuleName != target.Function.ParentApplication.Module.Name) return false; if (target.Function.Variables.Contains(PFunction.ArgumentListId)) //must not use argument list return false; if (symbol.Arguments.Count > target.Function.Parameters.Count) //must not supply more arguments than mapped return false; return true; }
void OnGUI() { // Choose the compiler m_Compiler = (CompilerTarget)EditorGUILayout.Popup(Content.compilerContent, (int)m_Compiler, Content.compileOptions); if (m_Compiler == CompilerTarget.Custom) { EditorGUILayout.BeginHorizontal(); m_CompilerPath = EditorGUILayout.TextField(m_CompilerPath); if (GUILayout.Button("...")) { #if UNITY_STANDALONE_WIN m_CompilerPath = EditorUtility.OpenFilePanel("Mali Offline Compiler", "", "exe"); #else m_CompilerPath = EditorUtility.OpenFilePanel("Mali Offline Compiler", "", ""); #endif } EditorGUILayout.EndHorizontal(); } // Select the shader Shader s = EditorGUILayout.ObjectField(Content.targetContent, m_Target, typeof(Shader), true) as Shader; // Go through and setup the data needed to compile a shader // we only do this once when a shader is selected. ProcessShader(s); // Display the keywords { GUILayout.Label(Content.allKeywords, EditorStyles.boldLabel); EditorGUILayout.BeginVertical(GUILayout.MaxHeight(40.0f)); m_KeywordScroll = EditorGUILayout.BeginScrollView(m_KeywordScroll); EditorGUILayout.BeginHorizontal(); for (int i = 0; i < m_Keywords.Count; i++) { GUILayout.Label(m_Keywords[i], EditorStyles.label); } EditorGUILayout.EndHorizontal(); EditorGUILayout.EndScrollView(); EditorGUILayout.EndVertical(); } // Select Pass to investigate GUILayout.Label("Pass:"******"Pass Name:"); GUILayout.Label(info.name); EditorGUILayout.EndHorizontal(); GUILayout.Label("Pass Keywords:"); m_PassKeywordScroll = EditorGUILayout.BeginScrollView(m_PassKeywordScroll); EditorGUILayout.BeginVertical(); for (int i = 0; i < m_SelectedKeywords.Count; i++) { string[] options = info.keywords[i].ToArray(); if (options.Length == 0) { continue; } if (options[0].Length == 0) { options[0] = k_NA; } m_SelectedKeywords[i] = EditorGUILayout.Popup(info.keywordHint[i], Mathf.Clamp(m_SelectedKeywords[i], 0, options.Length), options); } EditorGUILayout.EndVertical(); EditorGUILayout.EndScrollView(); } // Report section { m_ReportScroll = EditorGUILayout.BeginScrollView(m_ReportScroll); EditorGUILayout.BeginVertical(); string value = null; for (int i = 0; i < k_ReportOrder.Length; i++) { if (m_Report.TryGetValue(k_ReportOrder[i], out value)) { EditorGUILayout.BeginHorizontal(); GUILayout.Label(Content.shaderTypes[i]); if (GUILayout.Button("Copy text")) { EditorGUIUtility.systemCopyBuffer = value; } EditorGUILayout.EndHorizontal(); GUILayout.Box(value, EditorStyles.helpBox); } } EditorGUILayout.EndVertical(); EditorGUILayout.EndScrollView(); } EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal(); GUI.enabled = info != defaultPassInfo; if (GUILayout.Button("Compile & Report")) { CompileAndReport(); } GUI.enabled = true; if (GUILayout.Button("Refresh Shader")) { // preprocess the shader ProcessShader(s, true); } if (GUILayout.Button("Clear Report")) { m_Report.Clear(); } EditorGUILayout.EndHorizontal(); }