public IAstNode CreateIAstNode(IAstNode beforeNode, string token) { if ((token[0] == '@' || token[0] == ':') && token.Length > 1) { // If the variable name is quoted if (token[1] == '"' || token[1] == '\'') { //_regex r2 = new _regex(@"^(((""[^""\\]*(?:\\.[^""\\]*)*(""|$))+)|(('[^'\\]*(?:\\.[^'\\]*)*('|$))+))\s"); //TODO Valiable Node //return new ASTNode( TokenType.VARIABLE // , token[0] + r2.Match(token.Substring(1)).OriginalValue); } else { Match match = _regex.Match(token); if (match.Success) { //TODO ValiableNode //return new ASTNode( TokenType.VARIABLE // , m3.OriginalValue // ); } } } return null; }
public override bool Parse(ParseContext context, IAstNode parent) { if (context.Tokens.CurrentToken.TokenType == RTokenType.OpenBrace) { context.AddError(new ParseError(ParseErrorType.UnexpectedToken, ErrorLocation.Token, context.Tokens.CurrentToken)); } return false; }
public override bool Parse(ParseContext context, IAstNode parent) { TokenStream<RToken> tokens = context.Tokens; Debug.Assert(tokens.CurrentToken.TokenType == RTokenType.Keyword); this.Keyword = RParser.ParseKeyword(context, this); this.Text = context.TextProvider.GetText(this.Keyword); if (tokens.CurrentToken.TokenType == RTokenType.OpenBrace) { this.OpenBrace = RParser.ParseToken(context, this); this.Arguments = new ArgumentList(RTokenType.CloseBrace); this.Arguments.Parse(context, this); if (tokens.CurrentToken.TokenType == RTokenType.CloseBrace) { this.CloseBrace = RParser.ParseToken(context, this); this.Scope = RParser.ParseScope(context, this, allowsSimpleScope: true, terminatingKeyword: null); if (this.Scope != null) { return base.Parse(context, parent); } else { context.AddError(new ParseError(ParseErrorType.FunctionBodyExpected, ErrorLocation.Token, tokens.PreviousToken)); } } else { context.AddError(new ParseError(ParseErrorType.CloseBraceExpected, ErrorLocation.Token, tokens.CurrentToken)); } } else { context.AddError(new ParseError(ParseErrorType.OpenBraceExpected, ErrorLocation.Token, tokens.CurrentToken)); } return false; }
protected override CommaSeparatedItem CreateItem(IAstNode parent, ParseContext context) { RToken currentToken = context.Tokens.CurrentToken; RToken nextToken = context.Tokens.NextToken; switch (currentToken.TokenType) { case RTokenType.Ellipsis: return new EllipsisArgument(); case RTokenType.Comma: return new MissingArgument(); case RTokenType.Identifier: case RTokenType.String: case RTokenType.Logical: case RTokenType.Complex: case RTokenType.NaN: case RTokenType.Null: case RTokenType.Number: case RTokenType.Infinity: if (nextToken.TokenType == RTokenType.Operator && context.TextProvider.GetText(nextToken) == "=") { return new NamedArgument(); } break; case RTokenType.CloseBrace: return null; // no arguments supplied } return new ExpressionArgument(); }
public override bool Parse(ParseContext context, IAstNode parent) { // Remove comments from the token stream this.Comments = new CommentsCollection(context.Comments); GlobalScope globalScope = new GlobalScope(); return globalScope.Parse(context, this); }
public override bool Parse(ParseContext context, IAstNode parent) { if (ParseExpression(context) && this.Children.Count > 0) { return base.Parse(context, parent); } return false; }
public StatementIndent(IAstNode node) { BeforeNode = node.BeforeNode; AfterNode = node; node.BeforeNode = this; ParentNode = (Statement)node.ParentNode; }
protected override void DefaultVisit(IAstNode node) { foreach (var child in node.Children) { child.Accept(this); } }
private void BuildAddIndexNode(IIndexDefinition index, IAstNode parent) { IAddIndexNode addIndexNode = new AddIndexNode(parent, index.Name); parent.ChildNodes.Add(addIndexNode); SemanticModelUtil.Copy(index, addIndexNode); }
public override bool Parse(ParseContext context, IAstNode parent) { // First parse base which should pick up keyword, braces, inner // expression and either full or simple (single statement) scope if (!base.Parse(context, parent)) { return false; } // At this point we should be either at 'else' token or // at the next statement. In the latter case we are done. TokenStream<RToken> tokens = context.Tokens; if (tokens.CurrentToken.IsKeywordText(context.TextProvider, "else")) { bool allowLineBreak = AllowLineBreakBeforeElse(context); if (!allowLineBreak) { // Verify that there is no line break before the 'else' if (context.Tokens.IsLineBreakAfter(context.TextProvider, tokens.Position - 1)) { context.AddError(new ParseError(ParseErrorType.UnexpectedToken, ErrorLocation.Token, tokens.CurrentToken)); return true; } } this.Else = new KeywordScopeStatement(allowsSimpleScope: true); return this.Else.Parse(context, this); } // Not at 'else' so we are done here return true; }
public override bool Parse(ParseContext context, IAstNode parent) { TokenStream<RToken> tokens = context.Tokens; if (tokens.CurrentToken.IsVariableKind()) { var v = new Variable(); v.Parse(context, this); // Variables don't set parent since during complex // exression parsing parent is determined by the // expression parser based on precedence and grouping. v.Parent = this; this.Variable = v; if (tokens.CurrentToken.IsKeywordText(context.TextProvider, "in")) { this.InOperator = new TokenNode(); this.InOperator.Parse(context, this); this.Expression = new Expression(inGroup: true); if (this.Expression.Parse(context, this)) { return base.Parse(context, parent); } } else { context.AddError(new MissingItemParseError(ParseErrorType.InKeywordExpected, tokens.CurrentToken)); } } else { context.AddError(new MissingItemParseError(ParseErrorType.IndentifierExpected, tokens.PreviousToken)); } return false; }
public static void CompareNodes(EditorTree editorTree, IAstNode node1, IAstNode node2) { #if ___DEBUG Debug.Assert(node1 is RootNode || editorTree.ParseTree.ContainsElement(node1.Key)); if (!node1.ChildrenInvalidated) Debug.Assert(node1.Children.Count == node2.Children.Count); Debug.Assert(TextRange.AreEqual(node1.NameRange, node2.NameRange)); Debug.Assert(node1.Attributes.Count == node2.Attributes.Count); Debug.Assert(TextRange.AreEqual(node1.OuterRange, node2.OuterRange)); Debug.Assert(TextRange.AreEqual(node1.InnerRange, node2.InnerRange)); Debug.Assert(node1.Start == node2.Start); Debug.Assert(node1.End == node2.End); if (!node1.ChildrenInvalidated) { if (node1.Children.Count == node2.Children.Count) { for (int i = 0; i < node1.Children.Count; i++) { CompareNodes(editorTree, node1.Children[i], node2.Children[i]); } } } #endif }
public override bool Parse(ParseContext context, IAstNode parent) { if (context.Tokens.CurrentToken.TokenType == RTokenType.Comma) { this.Comma = RParser.ParseToken(context, this); } return base.Parse(context, parent); }
public static TokenNode ParseToken(ParseContext context, IAstNode parent) { TokenStream<RToken> tokens = context.Tokens; TokenNode node = new TokenNode(); node.Parse(context, parent); return node; }
public override bool Parse(ParseContext context, IAstNode parent) { TokenStream<RToken> tokens = context.Tokens; Debug.Assert(context.Tokens.CurrentToken.TokenType == RTokenType.Identifier || context.Tokens.CurrentToken.TokenType == RTokenType.String); this.Identifier = RParser.ParseToken(context, this); this.EqualsSign = RParser.ParseToken(context, this); if (context.Tokens.CurrentToken.TokenType != RTokenType.Comma && context.Tokens.CurrentToken.TokenType != RTokenType.CloseBrace) { Expression exp = new Expression(inGroup: true); if (exp.Parse(context, this)) { this.DefaultValue = exp; } } else { this.DefaultValue = new NullExpression(); if (context.Tokens.IsEndOfStream()) { context.AddError(new ParseError(ParseErrorType.ExpressionExpected, ErrorLocation.Token, context.Tokens.CurrentToken)); } else { context.AddError(new ParseError(ParseErrorType.ExpressionExpected, ErrorLocation.Token, EqualsSign)); } } return base.Parse(context, parent); }
public IEnumerable<SuggestedActionSet> GetSuggestedActions(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested || !range.Snapshot.TextBuffer.ContentType.TypeName.EqualsOrdinal(RContentTypeDefinition.ContentType)) { return Enumerable.Empty<SuggestedActionSet>(); } List<SuggestedActionSet> actionSets = new List<SuggestedActionSet>(); var caretPosition = _textView.Caret.Position.BufferPosition; SnapshotPoint? bufferPoint = _textView.MapDownToR(caretPosition); if (bufferPoint.HasValue) { AstRoot ast = _document?.EditorTree.AstRoot; int bufferPosition = bufferPoint.Value.Position; _lastNode = ast?.GetNodeOfTypeFromPosition<TokenNode>(bufferPosition); if (_lastNode != null) { foreach (IRSuggestedActionProvider actionProvider in _suggestedActionProviders) { if (actionProvider.HasSuggestedActions(_textView, _textBuffer, bufferPosition)) { IEnumerable<ISuggestedAction> actions = actionProvider.GetSuggestedActions(_textView, _textBuffer, bufferPosition); Span applicableSpan = new Span(_lastNode.Start, _lastNode.Length); SuggestedActionSet actionSet = new SuggestedActionSet(actions, applicableToSpan: applicableSpan); actionSets.Add(actionSet); } } } } return actionSets; }
public void RemoveChildren(int start, int count) { if (count == 0) return; if (start < 0 || start >= Children.Count) throw new ArgumentOutOfRangeException("start"); if (count < 0 || count > Children.Count || start + count > Children.Count) throw new ArgumentOutOfRangeException("count"); if (Children.Count == count) { _children = new TextRangeCollection<IAstNode>(); } else { var newChildren = new IAstNode[Children.Count - count]; int j = 0; for (int i = 0; i < start; i++, j++) newChildren[j] = Children[i]; for (int i = start; i < start + count; i++) Children[i].Parent = null; for (int i = start + count; i < Children.Count; i++, j++) newChildren[j] = Children[i]; _children = new TextRangeCollection<IAstNode>(newChildren); } }
public TableOrColumnName(IAstNode preNode, string originalValue) : base(preNode, originalValue) { // SQLが成立していないとき if (ParentNode == null || ParentNode.ParentNode == null) { Order = OrderType.Unknown; throw new Exception("SQLが成立していません"); } // 定義の親がStatementでその親が予約語 if (ParentNode.ParentNode.GetType() == typeof (ReservedTopLevel)) { string reservedWord = ParentNode.ParentNode.OriginalValue; Match m = _regex.Match(reservedWord); if (m.Success) { // FROMやUPDATEなど、カラム名称が定義されない予約語ならテーブル名 Order = OrderType.Table; } else { // SELECT句やWHERE区ででてきたカラム定義 Order = OrderType.Column; } } else { // JOIN句など、予約語とは違うネスト階層により出現する定義 Order = OrderType.Column; } }
/// <summary> /// Abstract factory creating statements depending on current /// token and the following token sequence /// </summary> /// <returns></returns> public static IStatement Create(ParseContext context, IAstNode parent, string terminatingKeyword) { TokenStream<RToken> tokens = context.Tokens; RToken currentToken = tokens.CurrentToken; IStatement statement = null; switch (currentToken.TokenType) { case RTokenType.Keyword: // If statement starts with a keyword, it is not an assignment // hence we should always try keyword based statements first. // Some of the statements may be R-values like typeof() but // in case of the statement appearing on its own return value // will be simply ignored. IDE may choose to show a warning. if (currentToken.SubType == RTokenSubType.BuiltinFunction && tokens.NextToken.TokenType != RTokenType.OpenBrace) { // 'return <- x + y' is allowed statement = new ExpressionStatement(terminatingKeyword); } else { statement = KeywordStatement.CreateStatement(context, parent); } break; case RTokenType.Semicolon: statement = new EmptyStatement(); break; default: // Possible L-value in a left-hand assignment, // a function call or R-value in a right hand assignment. statement = new ExpressionStatement(terminatingKeyword); break; } return statement; }
public override bool Parse(ParseContext context, IAstNode parent) { RToken currentToken = context.Tokens.CurrentToken; this.Token = currentToken; context.Tokens.MoveToNextToken(); return base.Parse(context, parent); }
public override bool Parse(ParseContext context, IAstNode parent) { this.ArgumentValue = new Expression(inGroup: true); if (this.ArgumentValue.Parse(context, this)) { return base.Parse(context, parent); } return false; }
public override bool Parse(ParseContext context, IAstNode parent) { foreach (RToken t in Tokens) { TokenNode n = new TokenNode(t); n.Parent = this; } return base.Parse(context, parent); }
public ParseResult(IAstNode rootNode, IdentifierCollection identifiers) { Require.NotNull(rootNode, "rootNode"); Require.NotNull(identifiers, "identifiers"); RootNode = rootNode; Identifiers = identifiers; }
public RObject Evaluate(IAstNode node) { IRValueNode rValue = node as IRValueNode; if (rValue == null) { return RNull.Null; } return RNull.Null; }
public IAstNode CreateIAstNode(IAstNode beforeNode, string token) { if (token[0] == '(' || token[0] == ')') { return new Bracket(beforeNode, token[0].ToString()); } return null; }
public IAstNode CreateIAstNode(IAstNode beforeNode, string token) { Match match = _regex.Match(token); if (match.Success) { return new Boundaries(beforeNode, match.Value); } return null; }
public override void SetParentInChildNode(IAstNode node) { if (node.GetType() == typeof (ReservedTopLevel)) { // SELECTなどの予約語をもつことからネスト構造のSQLをもつ HasQuery = true; } base.SetParentInChildNode(node); }
public IAstNode CreateIAstNode(IAstNode beforeNode, string token) { Match match = _regex.Match(token); if (match.Success) { return new FunctionWord(beforeNode, match.Groups["target"].Value); } return null; }
public override bool Parse(ParseContext context, IAstNode parent) { if (ParseKeyword(context, this)) { if (ParseSemicolon(context, this)) { return base.Parse(context, parent); } } return false; }
/// <summary> /// Formats specific AST node /// </summary> public static void FormatNode(ITextView textView, ITextBuffer textBuffer, IEditorShell editorShell, IAstNode node, int limit = -1) { if (node != null) { if (limit >= 0 && limit < node.Start) { throw new ArgumentException(nameof(limit)); } ITextRange range = limit < 0 ? node as ITextRange : TextRange.FromBounds(node.Start, limit); UndoableFormatRange(textView, textBuffer, range, editorShell); } }
public void EndVisit(IAstNode element, object parameter) { }
public static void DumpAst(IAstNode ast) { ast.Accept(new DumpAstVisitor()); }
public virtual bool Transform(IAstNode node) { return(true); }
public EvaluationString(IAstNode beforeNode, string value) : base(beforeNode, value) { }
/// <summary> /// Leave the scope. Must corespond to <see cref="EnterScope"/> /// </summary> public virtual void LeaveScope(IAstNode node) { var pop = _scope.Pop(); Debug.Assert(pop == node); }
private IAstNode Process_SourceFilter(IReadWriteOperation op, int operationId, IAstNode result) { return(Process_ValuesFilter( op, operationId, result, AstBuildHelper.ReadMembersChain( AstBuildHelper.ReadLocalRA(locFrom), op.Source.MembersChain ), "SourceFilter", op.SourceFilter )); }
public GreaterThanNode(IAstNode value1, IAstNode value2) { Value1 = value1; Value2 = value2; }
public override bool Parse(ParseContext context, IAstNode parent) { Value = new RMissing(); return(base.Parse(context, parent)); }
public override bool Parse(ParseContext context, IAstNode parent) { TokenStream <RToken> tokens = context.Tokens; RToken currentToken = tokens.CurrentToken; context.Scopes.Push(this); if (!(this is GlobalScope) && currentToken.TokenType == RTokenType.OpenCurlyBrace) { this.OpenCurlyBrace = RParser.ParseToken(context, this); } while (!tokens.IsEndOfStream()) { currentToken = context.Tokens.CurrentToken; switch (currentToken.TokenType) { case RTokenType.CloseCurlyBrace: if (this.OpenCurlyBrace != null) { this.CloseCurlyBrace = RParser.ParseToken(context, this); } else { context.AddError(new ParseError(ParseErrorType.UnexpectedToken, ErrorLocation.Token, currentToken)); context.Tokens.MoveToNextToken(); } break; case RTokenType.OpenCurlyBrace: IScope scope = new Scope(string.Empty); scope.Parse(context, this); break; default: IStatement statement = Statement.Create(context, this, null); if (statement != null) { if (statement.Parse(context, this)) { this.statements.Add(statement); } else { statement = null; } } if (statement == null) { if (!context.TextProvider.IsNewLineBeforePosition(context.Tokens.CurrentToken.Start)) { // try recovering at the next line or past nearest // semicolon or closing curly brace tokens.MoveToNextLine(context.TextProvider, (TokenStream <RToken> ts) => { return(ts.CurrentToken.TokenType == RTokenType.Semicolon || ts.NextToken.TokenType == RTokenType.CloseCurlyBrace); }); } else { tokens.MoveToNextToken(); } } break; } if (this.CloseCurlyBrace != null) { break; } } context.Scopes.Pop(); if (this.OpenCurlyBrace != null && this.CloseCurlyBrace == null) { context.AddError(new MissingItemParseError(ParseErrorType.CloseCurlyBraceExpected, context.Tokens.PreviousToken)); } // TODO: process content and fill out declared variables // and functions and get data to the classifier for colorization. return(base.Parse(context, parent)); }
public DeclarationSemanticException(IAstNode node, string message) : base(node, message) { }
public ReservedWord(IAstNode preNode, string originalValue) : base(preNode, originalValue) { }
public void Declare(string name, SymbolKind kind, IAstNode ctx, params (string, object)[] properties)
private static void AddOperation(StructuredProgramContext context, LinkedListNode <INode> opNode) { Operation operation = (Operation)opNode.Value; Instruction inst = operation.Inst; bool isCall = inst == Instruction.Call; int sourcesCount = operation.SourcesCount; List <Operand> callOutOperands = new List <Operand>(); if (isCall) { LinkedListNode <INode> scan = opNode.Next; while (scan != null && scan.Value is Operation nextOp && nextOp.Inst == Instruction.CallOutArgument) { callOutOperands.Add(nextOp.Dest); scan = scan.Next; } sourcesCount += callOutOperands.Count; } IAstNode[] sources = new IAstNode[sourcesCount]; for (int index = 0; index < operation.SourcesCount; index++) { sources[index] = context.GetOperandUse(operation.GetSource(index)); } if (isCall) { for (int index = 0; index < callOutOperands.Count; index++) { sources[operation.SourcesCount + index] = context.GetOperandDef(callOutOperands[index]); } callOutOperands.Clear(); } AstTextureOperation GetAstTextureOperation(TextureOperation texOp) { return(new AstTextureOperation( inst, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle, 4, // TODO: Non-hardcoded array size. texOp.Index, sources)); } if (operation.Dest != null) { AstOperand dest = context.GetOperandDef(operation.Dest); if (inst == Instruction.LoadConstant) { Operand slot = operation.GetSource(0); if (slot.Type == OperandType.Constant) { context.Info.CBuffers.Add(slot.Value); } else { // If the value is not constant, then we don't know // how many constant buffers are used, so we assume // all of them are used. int cbCount = 32 - BitOperations.LeadingZeroCount(context.Config.GpuAccessor.QueryConstantBufferUse()); for (int index = 0; index < cbCount; index++) { context.Info.CBuffers.Add(index); } context.Info.UsesCbIndexing = true; } } else if (UsesStorage(inst)) { AddSBufferUse(context.Info.SBuffers, operation); } // If all the sources are bool, it's better to use short-circuiting // logical operations, rather than forcing a cast to int and doing // a bitwise operation with the value, as it is likely to be used as // a bool in the end. if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool)) { inst = GetLogicalFromBitwiseInst(inst); } bool isCondSel = inst == Instruction.ConditionalSelect; bool isCopy = inst == Instruction.Copy; if (isCondSel || isCopy) { VariableType type = GetVarTypeFromUses(operation.Dest); if (isCondSel && type == VariableType.F32) { inst |= Instruction.FP32; } dest.VarType = type; } else { dest.VarType = InstructionInfo.GetDestVarType(inst); } IAstNode source; if (operation is TextureOperation texOp) { if (texOp.Inst == Instruction.ImageLoad || texOp.Inst == Instruction.ImageStore) { dest.VarType = texOp.Format.GetComponentType(); } AstTextureOperation astTexOp = GetAstTextureOperation(texOp); if (texOp.Inst == Instruction.ImageLoad) { context.Info.Images.Add(astTexOp); } else { context.Info.Samplers.Add(astTexOp); } source = astTexOp; } else if (!isCopy) { source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount); } else { source = sources[0]; } context.AddNode(new AstAssignment(dest, source)); } else if (operation.Inst == Instruction.Comment) { context.AddNode(new AstComment(((CommentNode)operation).Comment)); } else if (operation is TextureOperation texOp) { AstTextureOperation astTexOp = GetAstTextureOperation(texOp); context.Info.Images.Add(astTexOp); context.AddNode(astTexOp); } else { if (UsesStorage(inst)) { AddSBufferUse(context.Info.SBuffers, operation); } context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount)); } // Those instructions needs to be emulated by using helper functions, // because they are NVIDIA specific. Those flags helps the backend to // decide which helper functions are needed on the final generated code. switch (operation.Inst) { case Instruction.MultiplyHighS32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32; break; case Instruction.MultiplyHighU32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32; break; case Instruction.Shuffle: context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle; break; case Instruction.ShuffleDown: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown; break; case Instruction.ShuffleUp: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp; break; case Instruction.ShuffleXor: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor; break; case Instruction.SwizzleAdd: context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd; break; } }
/// <summary> /// Enter the scope. /// </summary> public virtual void EnterScope(IAstNode node) { _scope.Push(node); }
private static void FindSpecificNode(IAstNode node, int position, Func <IAstNode, bool> match, ref IAstNode deepestNode, bool includeEnd = false) { if (position == node.Start || (!node.Contains(position) && !(includeEnd && node.End == position))) { return; // not this element } if (match(node)) { deepestNode = node; } for (var i = 0; i < node.Children.Count && node.Children[i].Start <= position; i++) { FindSpecificNode(node.Children[i], position, match, ref deepestNode, includeEnd); } }
private static void AddOperation(StructuredProgramContext context, Operation operation) { Instruction inst = operation.Inst; IAstNode[] sources = new IAstNode[operation.SourcesCount]; for (int index = 0; index < sources.Length; index++) { sources[index] = context.GetOperandUse(operation.GetSource(index)); } AstTextureOperation GetAstTextureOperation(TextureOperation texOp) { return(new AstTextureOperation( inst, texOp.Type, texOp.Flags, texOp.Handle, 4, // TODO: Non-hardcoded array size. texOp.Index, sources)); } if (operation.Dest != null) { AstOperand dest = context.GetOperandDef(operation.Dest); if (inst == Instruction.LoadConstant) { Operand slot = operation.GetSource(0); if (slot.Type != OperandType.Constant) { throw new InvalidOperationException("Found load with non-constant constant buffer slot."); } context.Info.CBuffers.Add(slot.Value); } else if (UsesStorage(inst)) { AddSBufferUse(context.Info.SBuffers, operation); } AstAssignment assignment; // If all the sources are bool, it's better to use short-circuiting // logical operations, rather than forcing a cast to int and doing // a bitwise operation with the value, as it is likely to be used as // a bool in the end. if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool)) { inst = GetLogicalFromBitwiseInst(inst); } bool isCondSel = inst == Instruction.ConditionalSelect; bool isCopy = inst == Instruction.Copy; if (isCondSel || isCopy) { VariableType type = GetVarTypeFromUses(operation.Dest); if (isCondSel && type == VariableType.F32) { inst |= Instruction.FP; } dest.VarType = type; } else { dest.VarType = InstructionInfo.GetDestVarType(inst); } IAstNode source; if (operation is TextureOperation texOp) { AstTextureOperation astTexOp = GetAstTextureOperation(texOp); if (texOp.Inst == Instruction.ImageLoad) { context.Info.Images.Add(astTexOp); } else { context.Info.Samplers.Add(astTexOp); } source = astTexOp; } else if (!isCopy) { source = new AstOperation(inst, operation.Index, sources); } else { source = sources[0]; } assignment = new AstAssignment(dest, source); context.AddNode(assignment); } else if (operation.Inst == Instruction.Comment) { context.AddNode(new AstComment(((CommentNode)operation).Comment)); } else if (operation is TextureOperation texOp) { AstTextureOperation astTexOp = GetAstTextureOperation(texOp); context.Info.Images.Add(astTexOp); context.AddNode(astTexOp); } else { if (UsesStorage(inst)) { AddSBufferUse(context.Info.SBuffers, operation); } context.AddNode(new AstOperation(inst, operation.Index, sources)); } // Those instructions needs to be emulated by using helper functions, // because they are NVIDIA specific. Those flags helps the backend to // decide which helper functions are needed on the final generated code. switch (operation.Inst) { case Instruction.MultiplyHighS32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32; break; case Instruction.MultiplyHighU32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32; break; case Instruction.Shuffle: context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle; break; case Instruction.ShuffleDown: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown; break; case Instruction.ShuffleUp: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp; break; case Instruction.ShuffleXor: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor; break; case Instruction.SwizzleAdd: context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd; break; } }
private IAstNode Process_DestinationFilter(IReadWriteOperation op, int operationId, IAstNode result) { return(Process_ValuesFilter( op, operationId, result, AstBuildHelper.ReadMembersChain( AstBuildHelper.ReadLocalRA(locTo), op.Destination.MembersChain ), "DestinationFilter", op.DestinationFilter )); }
public LessThanNode(IAstNode value1, IAstNode value2) { Value1 = value1; Value2 = value2; }
public static IAstNode Next(IAstNode node) { return(node.LLNode.Next?.Value); }
private static string GetExpression(CodeGenContext context, AstOperation operation) { Instruction inst = operation.Inst; InstInfo info = GetInstructionInfo(inst); if ((info.Type & InstType.Call) != 0) { bool atomic = (info.Type & InstType.Atomic) != 0; int arity = (int)(info.Type & InstType.ArityMask); string args = string.Empty; for (int argIndex = 0; argIndex < arity; argIndex++) { // For shared memory access, the second argument is unused and should be ignored. // It is there to make both storage and shared access have the same number of arguments. // For storage, both inputs are consumed when the argument index is 0, so we should skip it here. if (argIndex == 1 && (atomic || (inst & Instruction.MrMask) == Instruction.MrShared)) { continue; } if (argIndex != 0) { args += ", "; } if (argIndex == 0 && atomic) { Instruction memRegion = inst & Instruction.MrMask; switch (memRegion) { case Instruction.MrShared: args += LoadShared(context, operation); break; case Instruction.MrStorage: args += LoadStorage(context, operation, forAtomic: true); break; default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\"."); } } else { VariableType dstType = GetSrcVarType(inst, argIndex); args += GetSoureExpr(context, operation.GetSource(argIndex), dstType); } } if (inst == Instruction.Ballot) { return($"unpackUint2x32({info.OpName}({args})).x"); } else { return(info.OpName + "(" + args + ")"); } } else if ((info.Type & InstType.Op) != 0) { string op = info.OpName; // Return may optionally have a return value (and in this case it is unary). if (inst == Instruction.Return && operation.SourcesCount != 0) { return($"{op} {GetSoureExpr(context, operation.GetSource(0), context.CurrentFunction.ReturnType)}"); } int arity = (int)(info.Type & InstType.ArityMask); string[] expr = new string[arity]; for (int index = 0; index < arity; index++) { IAstNode src = operation.GetSource(index); string srcExpr = GetSoureExpr(context, src, GetSrcVarType(inst, index)); bool isLhs = arity == 2 && index == 0; expr[index] = Enclose(srcExpr, src, inst, info, isLhs); } switch (arity) { case 0: return(op); case 1: return(op + expr[0]); case 2: return($"{expr[0]} {op} {expr[1]}"); case 3: return($"{expr[0]} {op[0]} {expr[1]} {op[1]} {expr[2]}"); } } else if ((info.Type & InstType.Special) != 0) { switch (inst) { case Instruction.Call: return(Call(context, operation)); case Instruction.ImageLoad: return(ImageLoadOrStore(context, operation)); case Instruction.ImageStore: return(ImageLoadOrStore(context, operation)); case Instruction.LoadAttribute: return(LoadAttribute(context, operation)); case Instruction.LoadConstant: return(LoadConstant(context, operation)); case Instruction.LoadLocal: return(LoadLocal(context, operation)); case Instruction.LoadShared: return(LoadShared(context, operation)); case Instruction.LoadStorage: return(LoadStorage(context, operation)); case Instruction.Lod: return(Lod(context, operation)); case Instruction.PackDouble2x32: return(PackDouble2x32(context, operation)); case Instruction.PackHalf2x16: return(PackHalf2x16(context, operation)); case Instruction.StoreLocal: return(StoreLocal(context, operation)); case Instruction.StoreShared: return(StoreShared(context, operation)); case Instruction.StoreStorage: return(StoreStorage(context, operation)); case Instruction.TextureSample: return(TextureSample(context, operation)); case Instruction.TextureSize: return(TextureSize(context, operation)); case Instruction.UnpackDouble2x32: return(UnpackDouble2x32(context, operation)); case Instruction.UnpackHalf2x16: return(UnpackHalf2x16(context, operation)); } } throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\"."); }
public static IAstNode InverseCond(IAstNode cond) { return(new AstOperation(Instruction.LogicalNot, cond)); }
private static string GetExpression(CodeGenContext context, AstOperation operation) { Instruction inst = operation.Inst; InstInfo info = GetInstructionInfo(inst); if ((info.Type & InstType.Call) != 0) { int arity = (int)(info.Type & InstType.ArityMask); string args = string.Empty; for (int argIndex = 0; argIndex < arity; argIndex++) { if (argIndex != 0) { args += ", "; } VariableType dstType = GetSrcVarType(inst, argIndex); args += GetSoureExpr(context, operation.GetSource(argIndex), dstType); } return(info.OpName + "(" + args + ")"); } else if ((info.Type & InstType.Op) != 0) { string op = info.OpName; int arity = (int)(info.Type & InstType.ArityMask); string[] expr = new string[arity]; for (int index = 0; index < arity; index++) { IAstNode src = operation.GetSource(index); string srcExpr = GetSoureExpr(context, src, GetSrcVarType(inst, index)); bool isLhs = arity == 2 && index == 0; expr[index] = Enclose(srcExpr, src, inst, info, isLhs); } switch (arity) { case 0: return(op); case 1: return(op + expr[0]); case 2: return($"{expr[0]} {op} {expr[1]}"); case 3: return($"{expr[0]} {op[0]} {expr[1]} {op[1]} {expr[2]}"); } } else if ((info.Type & InstType.Special) != 0) { switch (inst) { case Instruction.LoadConstant: return(InstGenMemory.LoadConstant(context, operation)); case Instruction.PackHalf2x16: return(InstGenPacking.PackHalf2x16(context, operation)); case Instruction.TextureSample: return(InstGenMemory.TextureSample(context, operation)); case Instruction.TextureSize: return(InstGenMemory.TextureSize(context, operation)); case Instruction.UnpackHalf2x16: return(InstGenPacking.UnpackHalf2x16(context, operation)); } } throw new InvalidOperationException($"Unexpected instruction type \"{info.Type}\"."); }
public virtual bool Parse(ParseContext context, IAstNode parent = null) { Parent = parent; return(true); }
public static IAstNode Previous(IAstNode node) { return(node.LLNode.Previous?.Value); }
private static void AddOperation(StructuredProgramContext context, Operation operation) { Instruction inst = operation.Inst; int sourcesCount = operation.SourcesCount; int outDestsCount = operation.DestsCount != 0 ? operation.DestsCount - 1 : 0; IAstNode[] sources = new IAstNode[sourcesCount + outDestsCount]; for (int index = 0; index < operation.SourcesCount; index++) { sources[index] = context.GetOperandUse(operation.GetSource(index)); } for (int index = 0; index < outDestsCount; index++) { AstOperand oper = context.GetOperandDef(operation.GetDest(1 + index)); oper.VarType = InstructionInfo.GetSrcVarType(inst, sourcesCount + index); sources[sourcesCount + index] = oper; } AstTextureOperation GetAstTextureOperation(TextureOperation texOp) { return(new AstTextureOperation( inst, texOp.Type, texOp.Format, texOp.Flags, texOp.CbufSlot, texOp.Handle, texOp.Index, sources)); } if (operation.Dest != null) { AstOperand dest = context.GetOperandDef(operation.Dest); // If all the sources are bool, it's better to use short-circuiting // logical operations, rather than forcing a cast to int and doing // a bitwise operation with the value, as it is likely to be used as // a bool in the end. if (IsBitwiseInst(inst) && AreAllSourceTypesEqual(sources, VariableType.Bool)) { inst = GetLogicalFromBitwiseInst(inst); } bool isCondSel = inst == Instruction.ConditionalSelect; bool isCopy = inst == Instruction.Copy; if (isCondSel || isCopy) { VariableType type = GetVarTypeFromUses(operation.Dest); if (isCondSel && type == VariableType.F32) { inst |= Instruction.FP32; } dest.VarType = type; } else { dest.VarType = InstructionInfo.GetDestVarType(inst); } IAstNode source; if (operation is TextureOperation texOp) { if (texOp.Inst == Instruction.ImageLoad) { dest.VarType = texOp.Format.GetComponentType(); } source = GetAstTextureOperation(texOp); } else if (!isCopy) { source = new AstOperation(inst, operation.Index, sources, operation.SourcesCount); } else { source = sources[0]; } context.AddNode(new AstAssignment(dest, source)); } else if (operation.Inst == Instruction.Comment) { context.AddNode(new AstComment(((CommentNode)operation).Comment)); } else if (operation is TextureOperation texOp) { AstTextureOperation astTexOp = GetAstTextureOperation(texOp); context.AddNode(astTexOp); } else { context.AddNode(new AstOperation(inst, operation.Index, sources, operation.SourcesCount)); } // Those instructions needs to be emulated by using helper functions, // because they are NVIDIA specific. Those flags helps the backend to // decide which helper functions are needed on the final generated code. switch (operation.Inst) { case Instruction.AtomicMaxS32 | Instruction.MrShared: case Instruction.AtomicMinS32 | Instruction.MrShared: context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared; break; case Instruction.AtomicMaxS32 | Instruction.MrStorage: case Instruction.AtomicMinS32 | Instruction.MrStorage: context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage; break; case Instruction.MultiplyHighS32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32; break; case Instruction.MultiplyHighU32: context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighU32; break; case Instruction.Shuffle: context.Info.HelperFunctionsMask |= HelperFunctionsMask.Shuffle; break; case Instruction.ShuffleDown: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleDown; break; case Instruction.ShuffleUp: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleUp; break; case Instruction.ShuffleXor: context.Info.HelperFunctionsMask |= HelperFunctionsMask.ShuffleXor; break; case Instruction.SwizzleAdd: context.Info.HelperFunctionsMask |= HelperFunctionsMask.SwizzleAdd; break; } }
public static string GetSoureExpr(CodeGenContext context, IAstNode node, VariableType dstType) { return(ReinterpretCast(context, node, OperandManager.GetNodeDestType(context, node), dstType)); }
public UserDefinedPeekItem(string fileName, IAstNode definitionNode, string name, IPeekResultFactory peekResultFactory) : base(name, peekResultFactory) { DefinitionNode = definitionNode; FileName = fileName; }
public static string Enclose(string expr, IAstNode node, Instruction pInst, bool isLhs) { InstInfo pInfo = GetInstructionInfo(pInst); return(Enclose(expr, node, pInst, pInfo, isLhs)); }
public static AstAssignment Assign(IAstNode destination, IAstNode source) { return(new AstAssignment(destination, source)); }