private Statement VariableDeclaration() { // TODO : multiple declarations style int a, b, c; TypeToken type = Type(); WordToken identifierToken = look as WordToken; Match(Tags.ID); Expression initialValue = null; if (look.Tag == '=') { Match('='); initialValue = Bool(); } Match(';'); LocalVariableSymbol symbol = symbolTable.PutVar(identifierToken.Lexeme, type.DotNetType); memoryUsed += type.Width; return(new VariableDeclarationStatement(symbol, initialValue)); }
public BoundVariableDeclaration(VariableDeclarationStatementSyntax syntax, LocalVariableSymbol variableSymbol, TypeSymbol declaredType, BoundExpression initializerOpt) : base(BoundNodeKind.VariableDeclaration, syntax) { VariableSymbol = variableSymbol; DeclaredType = declaredType; InitializerOpt = initializerOpt; }
public VariableDeclarationStatement(LocalVariableSymbol symbol, Expression initialValue = null) { this.symbol = symbol; this.initialValue = initialValue; // TODO : Type checking }
public static void AssignValue_ToArrayIndexZero(this InstructionWriter instructionWriter, LocalVariableSymbol array, Action valueGetter) { instructionWriter.Get_LocalVariable(array); instructionWriter.EmitInstruction(OpCodeNumber.Ldc_I4_0); valueGetter(); instructionWriter.EmitInstruction(OpCodeNumber.Stelem_Ref); }
public static void AssignValue_ToArrayIndexOne(this InstructionWriter instructionWriter, LocalVariableSymbol array, LocalVariableSymbol value) { instructionWriter.Get_LocalVariable(array); instructionWriter.EmitInstruction(OpCodeNumber.Ldc_I4_1); instructionWriter.Get_LocalVariable(value); instructionWriter.EmitInstruction(OpCodeNumber.Stelem_Ref); }
public int CompareTo(LocalVariableSymbol <T> other) { Contract.ThrowIfNull(other); if (this == other) { return(0); } Contract.ThrowIfFalse(_localSymbol.Locations.Length == 1); Contract.ThrowIfFalse(other._localSymbol.Locations.Length == 1); Contract.ThrowIfFalse(_localSymbol.Locations[0].IsInSource); Contract.ThrowIfFalse(other._localSymbol.Locations[0].IsInSource); Contract.ThrowIfFalse( _localSymbol.Locations[0].SourceTree == other._localSymbol.Locations[0].SourceTree ); Contract.ThrowIfFalse( _localSymbol.Locations[0].SourceSpan.Start != other._localSymbol.Locations[0].SourceSpan.Start ); return(_localSymbol.Locations[0].SourceSpan.Start - other._localSymbol.Locations[0].SourceSpan.Start); }
protected override void ImplementOnException(InstructionBlock block, ITypeSignature exceptionType, InstructionWriter writer) { MethodDefDeclaration targetMethod = this.transformationInstance.AspectWeaverInstance.TargetElement as MethodDefDeclaration; if (targetMethod == null) { return; } // TODO: nested types string category = targetMethod.DeclaringType.Name; ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category); InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null); writer.AttachInstructionSequence(sequence); LocalVariableSymbol exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable( exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex")); LogSeverity logSeverity = LogSeverity.Warning; if (builder.SupportsIsEnabled) { builder.EmitGetIsEnabled(writer, logSeverity); InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence); } builder.EmitWrite(writer, block, "An exception occurred:\n{0}", 1, logSeverity, w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal), (i, w) => w.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal)); writer.EmitInstruction(OpCodeNumber.Rethrow); writer.DetachInstructionSequence(); }
private void AddCollectionLoop(LocalVariableSymbol resultVariable, InstructionWriter t, LocalVariableSymbol enumeratorVariable, LocalVariableSymbol currentVariable) { t.WhileNotZero( c => { c.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable); c.EmitInstructionMethod(OpCodeNumber.Callvirt, MoveNext); }, b => { b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable); b.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber); b.EmitInstruction(OpCodeNumber.Mul); b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, enumeratorVariable); b.EmitInstructionMethod(OpCodeNumber.Callvirt, GetCurrent); b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, currentVariable); b.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable); b.IfNotZero( bt => { bt.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, currentVariable); bt.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode); }, et => { et.EmitInstruction(OpCodeNumber.Ldc_I4_0); }); b.EmitInstruction(OpCodeNumber.Xor); b.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable); }); }
private void AddFieldCode(FieldDefDeclaration field, bool isFirst, InstructionWriter writer, LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType) { bool isCollection; var propType = field.FieldType; bool isValueType = propType.IsValueTypeSafe() == true; bool isGenericParameter = false; if (propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameter || propType.TypeSignatureElementKind == TypeSignatureElementKind.GenericParameterReference) { // TODO what does this mean? // maybe something else also needs to be checked? isCollection = false; isGenericParameter = true; } else { isCollection = propType.IsCollection() || propType.TypeSignatureElementKind == TypeSignatureElementKind.Array; } AddMultiplicityByMagicNumber(isFirst, writer, resultVariable, isCollection); if (propType.GetReflectionName().StartsWith("System.Nullable")) { AddNullableProperty(field, writer); } else if (isCollection && propType.GetReflectionName() != "System.String") { AddCollectionCode(field, writer, resultVariable, method, enhancedType); } else if (isValueType || isGenericParameter) { LoadVariable(field, writer); if (propType.GetReflectionName() != "System.Int32") { writer.EmitInstructionType(OpCodeNumber.Box, propType); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, Object_GetHashCode); } } else { LoadVariable(field, writer); AddNormalCode(field, writer, enhancedType); } if (!isFirst && !isCollection) { writer.EmitInstruction(OpCodeNumber.Xor); } if (!isCollection) { writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable); } }
protected internal override void OnPopulate(TreeViewCancelEventArgs e) { for (int i = 0; i < block.LocalVariableSymbolCount; i++) { LocalVariableSymbol symbol = block.GetLocalVariableSymbol(i); TreeNode node = new TreeNode(symbol.Name + ": " + symbol.LocalVariable.Ordinal.ToString()); this.Nodes.Add(node); } }
private VariableUseExpression VariableUseExpression() { LocalVariableSymbol var = symbolTable.GetVar((prev as WordToken).Lexeme); if (var == null) { Error("Undeclared identifier : " + prev); } return(new VariableUseExpression(var)); }
void AddGetEnumerator(InstructionWriter ins, LocalVariableSymbol variable, FieldDefDeclaration field) { if (field.FieldType.IsValueTypeSafe() == true) { ins.EmitInstructionType(OpCodeNumber.Box, field.FieldType); } ins.EmitInstructionMethod(OpCodeNumber.Callvirt, GetEnumerator); ins.EmitInstructionLocalVariable(OpCodeNumber.Stloc, variable); }
private static void WriteLocalVariableTo(LocalVariableSymbol symbol, TextWriter writer) { writer.WriteKeyword(symbol.IsReadOnly ? SyntaxKind.LetKeyword : SyntaxKind.VarKeyword); writer.WriteSpace(); writer.WriteIdentifier(symbol.Name); writer.WritePunctuation(SyntaxKind.ColonToken); writer.WriteSpace(); symbol.Type.WriteTo(writer); }
private bool IsLocalAccessibleAfterMove(LocalVariableSymbol symbol, SyntaxBase newParent) { // find out the scope where the local symbol starts being accessible // (the declaration is outside of that node) var bindingContainer = GetScopeBindingContainer(symbol); // the symbol remains accessible IFF the newParent is the binding container or is below the binding container return(ReferenceEquals(newParent, bindingContainer) || this.semanticModel.SourceFile.Hierarchy.IsDescendant(node: newParent, potentialAncestor: bindingContainer)); }
private void AddMultiplicityByMagicNumber(bool isFirst, InstructionWriter writer, LocalVariableSymbol resultVariable, bool isCollection) { if (!isFirst && !isCollection) { writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber); writer.EmitInstruction(OpCodeNumber.Mul); } }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { // for <var> = <lower> to <upper> // <body> // // ----> // { // var <var> = <lower> // let upperBound = <upper> // while (<var> <= upperBound) // { // <body> // continue: // <var> = <var> + 1 // } // } var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int), new BoundVariableExpression(upperBoundSymbol) ); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1) ) ) ); var whileBody = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( node.Body, continueLabelStatement, increment ) ); var whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel()); var result = new BoundBlockStatement( ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, whileStatement ) ); return(RewriteStatement(result)); }
/// <summary> /// Gets the syntax in which the specified symbol starts being accessible. /// </summary> /// <param name="symbol">the local variable symbol</param> private SyntaxBase GetScopeBindingContainer(LocalVariableSymbol symbol) { var parent = this.semanticModel.GetSymbolParent(symbol); if (parent is LocalScope scope) { return(scope.BindingSyntax); } throw new InvalidOperationException($"Unexpected local variable parent type '{parent?.GetType().Name}'"); }
private LanguageExpression GetLocalVariableExpression(LocalVariableSymbol localVariableSymbol) { if (this.localReplacements.TryGetValue(localVariableSymbol, out var replacement)) { // the current context has specified an expression to be used for this local variable symbol // to override the regular conversion return(replacement); } var @for = GetEnclosingForExpression(localVariableSymbol); return(GetLoopVariableExpression(localVariableSymbol, @for, CreateCopyIndexFunction(@for))); }
private LanguageExpression GetLoopVariableExpression(LocalVariableSymbol localVariableSymbol, ForSyntax @for, LanguageExpression indexExpression) { return(localVariableSymbol.LocalKind switch { // this is the "item" variable of a for-expression // to emit this, we need to index the array expression by the copyIndex() function LocalKind.ForExpressionItemVariable => GetLoopItemVariableExpression(@for, indexExpression), // this is the "index" variable of a for-expression inside a variable block // to emit this, we need to return a copyIndex(...) function LocalKind.ForExpressionIndexVariable => indexExpression, _ => throw new NotImplementedException($"Unexpected local variable kind '{localVariableSymbol.LocalKind}'."), });
protected override BoundStatement RewriteForToStatement(BoundForToStatement node) { // for <var> = <lower> to <upper> <body> // --- to ---> // { // var <var> = <lower> // let upperBound = <upper> // while <var> <= upperBound // <body> // continue: // <var> = <var> + 1 // } var variableDeclaration = new BoundVariableDeclarationStatement(node.Variable, node.LowerBound); var upperBoundSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclarationStatement(upperBoundSymbol, node.UpperBound); var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol); var condition = new BoundBinaryExpression( new BoundVariableExpression(node.Variable), BoundBinaryOperator.Bind(Lexing.TokenKind.LessOrEquals, TypeSymbol.Int, TypeSymbol.Int), upperBoundExpression); var increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( new BoundVariableExpression(node.Variable), BoundBinaryOperator.Bind(Lexing.TokenKind.Plus, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1)))); var whileBlock = new BoundBlockStatement( node.Body, increment); var whileStatement = new BoundWhileStatement(condition, whileBlock, node.BreakLabel, node.ContinueLabel); var result = new BoundBlockStatement( variableDeclaration, upperBoundDeclaration, whileStatement); return(RewriteStatement(result)); }
private void AddCollectionCodeInternal(FieldDefDeclaration field, LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType, InstructionWriter writer) { LoadVariable(field, writer); var enumeratorVariable = method.MethodBody.RootInstructionBlock.DefineLocalVariable(IEnumeratorType, "enumeratorVariable"); var currentVariable = method.MethodBody.RootInstructionBlock.DefineLocalVariable( method.Module.Cache.GetIntrinsic(IntrinsicType.Object), "enumeratorObject"); AddGetEnumerator(writer, enumeratorVariable, field); AddCollectionLoop(resultVariable, writer, enumeratorVariable, currentVariable); }
private void AddCollectionCode(FieldDefDeclaration field, InstructionWriter writer, LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType) { if (field.FieldType.IsValueTypeSafe() == true) { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, writer); } else { LoadVariable(field, writer); writer.IfNotZero( thenw => { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, thenw); }, elsew => { }); } }
protected override BoundStatement RewriteForStatement(BoundForStatement node) { BoundVariableDeclaration variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); BoundVariableExpression variableExpression = new BoundVariableExpression(node.Variable); VariableSymbol upperVariableSymbol = new LocalVariableSymbol("upperBound", true, TypeSymbol.Int); BoundVariableDeclaration upperVariableDeclaration = new BoundVariableDeclaration(upperVariableSymbol, node.UpperBound); BoundBinaryExpression condition = new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.LessOrEqualsToken, TypeSymbol.Int, TypeSymbol.Int), new BoundVariableExpression(upperVariableSymbol) ); BoundLabelStatement continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); BoundExpressionStatement increment = new BoundExpressionStatement( new BoundAssignmentExpression( node.Variable, new BoundBinaryExpression( variableExpression, BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), new BoundLiteralExpression(1) ) ) ); BoundBlockStatement whileBody = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( node.Body, continueLabelStatement, increment )); BoundWhileStatement whileStatement = new BoundWhileStatement(condition, whileBody, node.BreakLabel, GenerateLabel()); BoundBlockStatement result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperVariableDeclaration, whileStatement )); return(RewriteStatement(result)); }
private void EmitMessage(InstructionBlock block, InstructionWriter writer, LogLevel logLevel, string messageFormatString, int[] arguments, ITypeSignature exceptionType = null) { MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration; if (targetMethod == null) { return; } // TODO: nested types string category = targetMethod.DeclaringType.Name; ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category); InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null); writer.AttachInstructionSequence(sequence); LocalVariableSymbol exceptionLocal = null; if (exceptionType != null) { exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable( exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex")); } if (builder.SupportsIsEnabled) { builder.EmitGetIsEnabled(writer, logLevel); InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence); } bool useWrapper = ShouldUseWrapper(targetMethod); Action <InstructionWriter> getExceptionAction = exceptionLocal != null ? (Action <InstructionWriter>)(w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal)) : null; builder.EmitWrite(writer, messageFormatString, exceptionType == null ? arguments.Length : arguments.Length + 1, logLevel, getExceptionAction, (i, instructionWriter) => { if (i < arguments.Length) { int index = arguments[i]; if (index == MessageArgumentsFormatter.ThisArgumentPosition) { this.methodMappingWriter.EmitLoadInstance(false, instructionWriter); } else if (index == MessageArgumentsFormatter.ReturnParameterPosition) { instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, Context.ReturnValueVariable); instructionWriter.EmitConvertToObject( Context.MethodMapping.MethodSignature.ReturnType); } else { this.methodMappingWriter.EmitLoadArgument(index, instructionWriter); instructionWriter.EmitConvertToObject(this.methodMappingWriter.MethodMapping.MethodSignature.GetParameterType(index).GetNakedType(TypeNakingOptions.IgnoreManagedPointers)); } } else { //Emit exception parameter instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal); } }, useWrapper); if (exceptionType == null) { writer.DetachInstructionSequence(); } }
public override void Implement(TransformationContext context) { TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; ModuleDeclaration module = this.AspectWeaver.Module; ITypeSignature baseEntityType = module.Cache.GetType(typeof(BaseEntity)); // Find the base method. IMethod baseCopyToMethod = null; IType baseTypeCursor = typeDef; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new[] { baseEntityType }, 0); while (baseCopyToMethod == null && baseTypeCursor != null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseCopyToMethod = baseTypeCursorTypeDef.Methods.GetMethod("CopyTo", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } if (baseCopyToMethod == null) { throw new AssertionFailedException("Could not find a method CopyTo."); } if (baseCopyToMethod.DeclaringType == typeDef) { return; } // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "CopyTo", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; ParameterDeclaration cloneParameter = new ParameterDeclaration(0, "clone", baseEntityType); methodDef.Parameters.Add(cloneParameter); // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Cast the argument and store it in a local variable. IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance(typeDef); LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable(typeSpec, "typedClone"); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Castclass, typeSpec); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, castedCloneLocal); // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseCopyToMethod.Translate(typeDef.Module)); // Loop on all fields and clone cloneable ones. TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration) module.Cache.GetType(typeof(ICloneable)); MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration)cloneableTypeRef.MethodRefs.GetMethod( "Clone", new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Object), new ITypeSignature[0], 0), BindingOptions.Default); foreach (FieldDefDeclaration fieldDef in typeDef.Fields) { if ((fieldDef.Attributes & FieldAttributes.Static) != 0) { continue; } if (fieldDef.FieldType == module.Cache.GetIntrinsic(IntrinsicType.String)) { continue; } // Does not work? //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty); bool cloneable = typeof(ICloneable).IsAssignableFrom(fieldDef.FieldType.GetSystemType(null, null)); if (cloneable) { IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); bool isValueType = fieldSpec.FieldType.BelongsToClassification(TypeClassifications.ValueType).Equals( NullableBool.True); InstructionSequence nextSequence = null; if (!isValueType) { nextSequence = methodBody.CreateInstructionSequence(); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, nextSequence); } writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, castedCloneLocal); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Box, fieldSpec.FieldType); } //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, cloneMethodRef); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Unbox, fieldSpec.FieldType); writer.EmitInstructionType(OpCodeNumber.Ldobj, fieldSpec.FieldType); } else { writer.EmitInstructionType(OpCodeNumber.Castclass, fieldSpec.FieldType); } writer.EmitInstructionField(OpCodeNumber.Stfld, fieldSpec); if (!isValueType) { writer.DetachInstructionSequence(); instructionBlock.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; writer.AttachInstructionSequence(sequence); } } } writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
private static BoundVariableDeclaration VariableDeclarationInternal(SyntaxNode syntax, string name, BoundExpression initializer, bool isReadOnly) { var local = new LocalVariableSymbol(name, isReadOnly, initializer.Type, initializer.ConstantValue); return(new BoundVariableDeclaration(syntax, local, initializer)); }
/// <inheritdoc/> protected override BoundStatement RewriteForEllipsisStatement(BoundForEllipsisStatement node) { // for <var> := <lower> ... <upper> // <body> // // ----> // // { // var <var> = <lower> // const upperBound = <upper> // var step = 1 // if <var> greaterthan upperBound { // step = -1 // } // goto start // body: // <body> // continue: // <var> = <var> + step // start: // gotoTrue ((step > 0 && lower < upper) || (step < 0 && lower > upper)) body // break: // } var variableDeclaration = new BoundVariableDeclaration(node.Variable, node.LowerBound); var upperBoundSymbol = new LocalVariableSymbol("upperBound", isReadOnly: true, type: TypeSymbol.Int); var upperBoundDeclaration = new BoundVariableDeclaration(upperBoundSymbol, node.UpperBound); var stepBoundSymbol = new LocalVariableSymbol("step", isReadOnly: false, type: TypeSymbol.Int); var stepBoundDeclaration = new BoundVariableDeclaration( variable: stepBoundSymbol, initializer: new BoundLiteralExpression(1)); var variableExpression = new BoundVariableExpression(node.Variable); var upperBoundExpression = new BoundVariableExpression(upperBoundSymbol); var stepBoundExpression = new BoundVariableExpression(stepBoundSymbol); var ifLowerIsGreaterThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var stepBoundAssingment = new BoundExpressionStatement( expression: new BoundAssignmentExpression( variable: stepBoundSymbol, expression: new BoundLiteralExpression(-1))); var ifLowerIsGreaterThanUpperIfStatement = new BoundIfStatement( condition: ifLowerIsGreaterThanUpperExpression, thenStatement: stepBoundAssingment, elseStatement: null); var startLabel = GenerateLabel(); var gotoStart = new BoundGotoStatement(startLabel); var bodyLabel = GenerateLabel(); var bodyLabelStatement = new BoundLabelStatement(bodyLabel); var continueLabelStatement = new BoundLabelStatement(node.ContinueLabel); var increment = new BoundExpressionStatement( expression: new BoundAssignmentExpression( variable: node.Variable, expression: new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int), right: stepBoundExpression))); var startLabelStatement = new BoundLabelStatement(startLabel); var zeroLiteralExpression = new BoundLiteralExpression(0); var stepGreaterThanZeroExpression = new BoundBinaryExpression( left: stepBoundExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: zeroLiteralExpression); var lowerLessThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var positiveStepAndLowerLessThanUpper = new BoundBinaryExpression( left: stepGreaterThanZeroExpression, op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool), right: lowerLessThanUpperExpression); var stepLessThanZeroExpression = new BoundBinaryExpression( left: stepBoundExpression, op: BoundBinaryOperator.Bind(SyntaxKind.LessToken, TypeSymbol.Int, TypeSymbol.Int), right: zeroLiteralExpression); var lowerGreaterThanUpperExpression = new BoundBinaryExpression( left: variableExpression, op: BoundBinaryOperator.Bind(SyntaxKind.GreaterToken, TypeSymbol.Int, TypeSymbol.Int), right: upperBoundExpression); var negativeStepAndLowerGreaterThanUpper = new BoundBinaryExpression( left: stepLessThanZeroExpression, op: BoundBinaryOperator.Bind(SyntaxKind.AmpersandAmpersandToken, TypeSymbol.Bool, TypeSymbol.Bool), right: lowerGreaterThanUpperExpression); var condition = new BoundBinaryExpression( positiveStepAndLowerLessThanUpper, BoundBinaryOperator.Bind(SyntaxKind.PipePipeToken, TypeSymbol.Bool, TypeSymbol.Bool), negativeStepAndLowerGreaterThanUpper); var gotoTrue = new BoundConditionalGotoStatement(bodyLabel, condition, jumpIfTrue: true); var breakLabelStatement = new BoundLabelStatement(node.BreakLabel); var result = new BoundBlockStatement(ImmutableArray.Create <BoundStatement>( variableDeclaration, upperBoundDeclaration, stepBoundDeclaration, ifLowerIsGreaterThanUpperIfStatement, gotoStart, bodyLabelStatement, node.Body, continueLabelStatement, increment, startLabelStatement, gotoTrue, breakLabelStatement)); return(RewriteStatement(result)); }
public CreatedEmptyMethod(MethodDefDeclaration methodDeclaration, InstructionBlock principalBlock, LocalVariableSymbol returnVariable, InstructionSequence returnSequence) { this.MethodDeclaration = methodDeclaration; this.PrincipalBlock = principalBlock; this.ReturnVariable = returnVariable; this.ReturnSequence = returnSequence; }
/// <summary> /// Emits the MSIL that calls the logging method with the specified format provider, message and arguments. /// </summary> /// <param name="emitter">IL emitter.</param> /// <param name="log">Field that stores reference to the logger.</param> /// <param name="method">Logging method to use. The method must return no value and must take 3 arguments of types <see cref="IFormatProvider"/>, <see cref="string"/> and <see cref="Array"/> of <see cref="object"/>s.</param> /// <param name="formatProviderGetter">Getter of the property that returns the <see cref="IFormatProvider"/> instance.</param> /// <param name="formatString">Format string for the log.</param> /// <param name="args">Variable storing reference to array of arguments for placeholders used in the format string.</param> /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="formatProviderGetter"/>, <paramref name="formatString"/> or <paramref name="args"/> is <see langword="null"/>.</exception> /// <remarks> /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack /// and it leaves the stack unmodified.</para> /// </remarks> private static void EmitLogProviderStringArgs(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, IMethod formatProviderGetter, string formatString, LocalVariableSymbol args) { if (emitter == null) { throw new ArgumentNullException("emitter"); } if (log == null) { throw new ArgumentNullException("log"); } if (method == null) { throw new ArgumentNullException("method"); } if (formatProviderGetter == null) { throw new ArgumentNullException("formatProviderGetter"); } if (args == null) { throw new ArgumentNullException("args"); } emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log)); emitter.EmitInstructionMethod(OpCodeNumber.Call, formatProviderGetter); emitter.EmitInstructionString(OpCodeNumber.Ldstr, formatString); emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args); emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method); }
public ExpressionConverter AppendReplacement(LocalVariableSymbol symbol, LanguageExpression replacement) { // Allow local variable symbol replacements to be overwritten, as there are scenarios where we recursively generate expressions for the same index symbol return(new(this.context, this.localReplacements.SetItem(symbol, replacement))); }
public static void Box_LocalVariableIfNeeded(this InstructionWriter instructionWriter, LocalVariableSymbol symbol) { instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, symbol); EmitBoxIfNeeded(instructionWriter, symbol.LocalVariable.Type); }
public ExpressionConverter AppendReplacement(LocalVariableSymbol symbol, LanguageExpression replacement) =>
public static void Get_LocalVariable(this InstructionWriter instructionWriter, LocalVariableSymbol symbol) { instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, symbol); }
public static void AssignValue_ToArrayIndexZero(this InstructionWriter instructionWriter, LocalVariableSymbol array, LocalVariableSymbol value) { instructionWriter.AssignValue_ToArrayIndexZero( array, () => instructionWriter.Get_LocalVariable(value)); }
public static void AssignValue_LocalVariable(this InstructionWriter instructionWriter, LocalVariableSymbol symbol, Action argument) { argument(); instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Stloc_S, symbol); }
public VariableUseExpression(LocalVariableSymbol symbol) : base(symbol.VariableType) { this.symbol = symbol; }
public override void Implement(TransformationContext context) { ModuleDeclaration module = this.AspectWeaver.Module; TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "AutoGeneratedValidate", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Find the base method. IMethod baseValidateMethod = null; IType baseTypeCursor = typeDef.BaseType; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new ITypeSignature[0], 0); while (baseValidateMethod == null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseValidateMethod = baseTypeCursorTypeDef.Methods.GetMethod("AutoGeneratedValidate", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseValidateMethod.Translate(typeDef.Module)); // Make an array with the boxed field values. TypeValidationAspect aspect = (TypeValidationAspect)this.AspectWeaverInstance.Aspect; LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable( module.Cache.GetType(typeof(object[])), "fieldValues"); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, aspect.Validators.Count); writer.EmitInstructionType(OpCodeNumber.Newarr, module.Cache.GetIntrinsic(IntrinsicType.Object)); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, fieldValuesArrayLocal); int i = 0; foreach (FieldValidationAttribute validator in aspect.Validators) { FieldDefDeclaration fieldDef = typeDef.Fields.GetByName(validator.TargetLocation.Name); IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitConvertToObject(fieldSpec.FieldType); writer.EmitInstruction(OpCodeNumber.Stelem_Ref); i++; } // Get the validator method. IMethod validateMethod = module.Cache.GetItem( () => module.FindMethod( typeof(TypeValidationAspect).GetMethod("Validate"), BindingOptions.Default)); // Call the validator. this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField(writer, null); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, validateMethod); writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
/// <summary> /// Emits the MSIL that calls the logging method with the specified message and exception. /// </summary> /// <param name="emitter">IL emitter.</param> /// <param name="log">Field that stores reference to the logger.</param> /// <param name="method">Logging method to use. The method must return no value and must take 2 parameters of types <see cref="string"/> and <see cref="Exception"/>.</param> /// <param name="message">Message to log.</param> /// <param name="exception">Local variable where reference to the exception is stored.</param> /// <exception cref="ArgumentNullException"><paramref name="emitter"/>, <paramref name="log"/>, <paramref name="method"/>, <paramref name="message"/> or <paramref name="exception"/> is <see langword="null"/>.</exception> /// <remarks> /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack /// and it leaves the stack unmodified.</para> /// </remarks> private static void EmitLogStringException(InstructionWriter emitter, FieldDefDeclaration log, IMethod method, string message, LocalVariableSymbol exception) { if (emitter == null) { throw new ArgumentNullException("emitter"); } if (log == null) { throw new ArgumentNullException("log"); } if (method == null) { throw new ArgumentNullException("method"); } if (message == null) { throw new ArgumentNullException("message"); } if (exception == null) { throw new ArgumentNullException("exception"); } emitter.EmitInstructionField(OpCodeNumber.Ldsfld, GenericHelper.GetCanonicalGenericInstance(log)); emitter.EmitInstructionString(OpCodeNumber.Ldstr, message); emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc_S, exception); emitter.EmitInstructionMethod(OpCodeNumber.Callvirt, method); }
public static void Get_AddressOf(this InstructionWriter instructionWriter, LocalVariableSymbol localVariable) { instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloca, localVariable); }