private Class GenerateClassMethod(ZMethod zMethod, Interface x) { this.currentMethod = zMethod; Class newClass = (Class)Templates.GetTypeTemplateByName("ClassMethod"); QualifiedIdentifier qi = (x == null) ? new QualifiedIdentifier(new Identifier("Z"), new Identifier("ZingMethod")) : new QualifiedIdentifier(x.Name, zMethod.Name); Replacer.Replace(newClass, new Identifier("__Method"), qi); if (x == null) { if (!zMethod.IsStatic) GenerateThisParameter(newClass); Class interfaceClass = (Class)Templates.GetTypeTemplateByName("InterfaceMethod"); for (int i = 0, n = interfaceClass.Members.Count; i < n; i++) { newClass.Members.Add(interfaceClass.Members[i]); interfaceClass.Members[i].DeclaringType = newClass; } Class inputsClass = (Class)Templates.GetMemberByName(newClass.Members, "InputVars"); GenerateInputs(zMethod, inputsClass); Class outputsClass = (Class)Templates.GetMemberByName(newClass.Members, "OutputVars"); GenerateOutputs(zMethod, outputsClass); } Class localsClass = (Class)Templates.GetMemberByName(newClass.Members, "LocalVars"); GenerateLocals(zMethod, localsClass); Class extras = (Class)Templates.GetTypeTemplateByName(zMethod.IsStatic ? "StaticMethodExtras" : "InstanceMethodExtras"); for (int i = 0, n = extras.Members.Count; i < n; i++) { newClass.Members.Add(extras.Members[i]); extras.Members[i].DeclaringType = newClass; Property p = extras.Members[i] as Property; if (p != null) { if (p.Getter != null) p.Getter.DeclaringType = newClass; if (p.Setter != null) p.Setter.DeclaringType = newClass; } } Replacer.Replace(newClass, newClass.Name, zMethod.Name); SetTypeId(newClass); ExtendMethodConstructor(newClass, zMethod); // If this method doesn't return concrete bool, then remove the helper // property for accessing bool return values. if (zMethod.ReturnType == SystemTypes.Boolean) { Property boolRetValProp = (Property)Templates.GetTypeTemplateByName("BooleanReturnValueProperty").Members[0]; newClass.Members.Add(boolRetValProp); boolRetValProp.DeclaringType = newClass; newClass.Members.Add(boolRetValProp.Getter); boolRetValProp.Getter.DeclaringType = newClass; } // Clear the "Activated" attribute if we aren't... if (!zMethod.Activated) newClass.Attributes = new AttributeList(0); GenerateBasicBlocks(newClass, zMethod); this.currentMethod = null; return newClass; }
// // This is the primary entry point into BBSplitter. This is called from the // Splicer to do basic block analysis before using the Normalizer to do code-gen // for each basic block. // public static List<BasicBlock> SplitMethod(ZMethod method, Splicer splicer) { BBSplitter splitter = new BBSplitter(splicer); splitter.atomicBranches = new List<BasicBlock>(); splitter.scopeStack.Push(method.Body.Scope); BasicBlock finalBlock = splitter.AddBlock(new BasicBlock(null)); if (method.Atomic) { // // For summarization, we need for atomic methods to have an "extra" // terminating block. This corresponds to what happens in VisitAtomic // for regular atomic blocks. // finalBlock = splitter.AddBlock(new BasicBlock(null, finalBlock)); finalBlock.MiddleOfTransition = true; splitter.insideAtomicBlock = true; } splitter.PushContinuationStack(finalBlock); splitter.VisitStatementList(method.Body.Statements); // For each branch within the atomic block, we need to look at the target // and see if it too is within an atomic block (by definition, the same // one). If not, then we need to make the branch's block be the effective // end of the atomic execution. We can do this by resetting its atomicity // level foreach (BasicBlock b in splitter.atomicBranches) { // The actual branch target is two blocks away because branch targets // always introduce an extra block that flow atomically into "real" code. BasicBlock branchTarget; if (b.UnconditionalTarget.IsReturn) continue; Debug.Assert(b.UnconditionalTarget.UnconditionalTarget != null); branchTarget = b.UnconditionalTarget.UnconditionalTarget; // If the target isn't atomic, then we need to introduce an interleaving // just after the branch. We do this by forcing it to be the end of // the atomic block. We must also make sure such a block cannot be the entry // point of the atomic block. if (branchTarget.RelativeAtomicLevel == 0) { b.RelativeAtomicLevel = 0; b.IsAtomicEntry = false; } } BasicBlock firstBlock = splitter.PopContinuationStack(); firstBlock.IsEntryPoint = true; if (firstBlock.RelativeAtomicLevel > 0) firstBlock.IsAtomicEntry = true; return splitter.blockList; }
private InterfaceList FindMatchingInterfaces(Class c, ZMethod zMethod) { InterfaceList matches = new InterfaceList(1); if (c.Interfaces != null && c.Interfaces.Count > 0) { for (int i = 0; i < c.Interfaces.Count; i++) { Interface x = c.Interfaces[i]; if (x.GetMatchingMethod(zMethod) != null) matches.Add(x); } } return matches; }
private void GenerateBasicBlocks(Class newClass, ZMethod zMethod) { // // Split the method into basic blocks, and then do code generation // based on this analysis // if (labelString != null) basicBlockToLabel = new Hashtable(); List<BasicBlock> basicBlocks = BBSplitter.SplitMethod(zMethod, this); if (labelString != null) { string methodName = zMethod.FullName; int index = methodName.IndexOf('('); if (index < 0) AddToLabelString(methodName); else { Debug.Assert(index > 0); AddToLabelString(methodName.Substring(0, index)); } } // // Look for opportunities to combine or remove blocks // // NOTE: this breaks summarization because it removes "transition" blocks // around atomic regions that they rely on. // //basicBlocks = BBOptimizer.Optimize(basicBlocks); EnumNode enumNode = (EnumNode)Templates.GetMemberByName(newClass.Members, "Blocks"); Field entryPointField = (Field)enumNode.Members[1]; int nextBlockEnumValue = 2; // Accumulate a list of scopes for which we've generated cleanup methods. These are // scopes that contain pointers. List<Scope> nonTrivialScopes = new List<Scope>(); foreach (BasicBlock block in basicBlocks) { if (!nonTrivialScopes.Contains(block.Scope) && ScopeNeedsCleanup(block.Scope)) { nonTrivialScopes.Add(block.Scope); AddScopeCleanupMethod(newClass, block.Scope); } } foreach (BasicBlock block in basicBlocks) { // Add the blocks to the Blocks enum if (!block.IsEntryPoint) { Field f = new Field(enumNode, null, entryPointField.Flags, new Identifier(block.Name), entryPointField.Type, null); f.Initializer = new Literal(nextBlockEnumValue++, SystemTypes.UInt16); enumNode.Members.Add(f); } // Emit a method for this block AddBlockMethod(zMethod, newClass, block, nonTrivialScopes); } PatchDispatchMethod(newClass, basicBlocks); PatchRunnableMethod(newClass, basicBlocks); PatchIsAtomicEntryMethod(newClass, basicBlocks); PatchValidEndStateProperty(newClass, basicBlocks); PatchSourceContextProperty(zMethod, newClass, basicBlocks); PatchContextAttributeProperty(zMethod, newClass, basicBlocks); }
private void PatchSourceContextProperty(ZMethod zMethod, Class methodClass, List<BasicBlock> basicBlocks) { Property contextProperty = (Property)Templates.GetMemberByName(methodClass.Members, "Context"); Method contextMethod = contextProperty.Getter; Debug.Assert(contextMethod.Body.Statements[0] is System.Compiler.Switch); System.Compiler.Switch switchStmt = (System.Compiler.Switch)contextMethod.Body.Statements[0]; foreach (BasicBlock block in basicBlocks) { SourceContext ctxt = new SourceContext(null, 0, 0); //ctxt.Document = null; //ctxt.StartPos = 0; //ctxt.EndPos = 0; if (block.SourceContext.StartPos != 0 || block.SourceContext.EndPos != 0) { // If the block says something explicit about its context, take that // as final. ctxt = block.SourceContext; } else { // The block doesn't say anything, so figure it out from the statements // inside the block. BasicBlock effectiveBlock = block; // // If we only fall through to another BB without any executable code, // conditional branching, interleaving, or return - then consider our // source context to be the next "real" thing that happens. // while ((effectiveBlock.Statement == null || effectiveBlock.SkipNormalizer) && effectiveBlock.ConditionalExpression == null && effectiveBlock.SourceContext.SourceText == null && effectiveBlock.MiddleOfTransition && !effectiveBlock.IsReturn && !effectiveBlock.PropagatesException) { effectiveBlock = effectiveBlock.UnconditionalTarget; } // See which source context is the most appropriate for this block. if (effectiveBlock.Statement != null) { if (effectiveBlock.Statement.SourceContext.SourceText != null) ctxt = effectiveBlock.Statement.SourceContext; else { Block b = effectiveBlock.Statement as Block; if (b != null) { for (int i = 0, n = b.Statements.Count; i < n; i++) { if (b.Statements[i] != null) { ctxt = b.Statements[i].SourceContext; break; } } } } } else if (effectiveBlock.ConditionalExpression != null) ctxt = effectiveBlock.ConditionalExpression.SourceContext; else if (effectiveBlock.SourceContext.SourceText != null) ctxt = effectiveBlock.SourceContext; else { // For "return" blocks, show the closing brace as the source context. ctxt.Document = zMethod.SourceContext.Document; ctxt.EndPos = zMethod.SourceContext.EndPos; ctxt.StartPos = ctxt.EndPos - 1; } } if (ctxt.StartPos < 0) ctxt.StartPos = 0; SwitchCase newCase = new SwitchCase( new QualifiedIdentifier(Identifier.For("Blocks"), Identifier.For(block.Name)), new Block(new StatementList( new Return(SourceContextConstructor(ctxt)))) ); switchStmt.Cases.Add(newCase); } }
// Create a secondary constructor that provides for initialization of // the "this" pointer as well as the input parameters private void ExtendMethodConstructor(Class newClass, ZMethod zMethod) { int numAddedParams = 0; // Duplicate our basic constructor so we can make an extended version System.Compiler.Duplicator dup = new System.Compiler.Duplicator(null, null); InstanceInitializer ctor = dup.VisitInstanceInitializer((InstanceInitializer)newClass.Members[0]); if (!zMethod.IsStatic) { // For instance methods, add a "This" parameter to the constructor ctor.Parameters.Add(new Parameter(Identifier.For("This"), new TypeExpression(Identifier.For("Pointer")))); // this.This = This; ctor.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( new QualifiedIdentifier(new This(), Identifier.For("This")), Identifier.For("This")))) ); numAddedParams++; } for (int i = 0, n = zMethod.Parameters.Count; i < n; i++) { TypeNode paramType; Parameter param = zMethod.Parameters[i]; if (param == null || param.Type == null) continue; if (param.IsOut) continue; if (GetTypeClassification(param.Type) == TypeClassification.Heap) paramType = this.ZingPtrType; else if (!IsPredefinedType(param.Type)) paramType = new TypeExpression(new QualifiedIdentifier( new Identifier("Application"), param.Type.Name)); else paramType = param.Type; ctor.Parameters.Add(new Parameter(param.Name, paramType)); // inputs.foo = foo; ctor.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( new QualifiedIdentifier(Identifier.For("inputs"), param.Name), param.Name))) ); numAddedParams++; } // If we didn't actually add any parameters, then the basic constructor is // all that we need. Only add the new constructor if it's different. if (numAddedParams > 0) { newClass.Members.Add(ctor); ctor.DeclaringType = newClass; } }
private void AddBlockMethod(ZMethod zMethod, Class methodClass, BasicBlock block, List<Scope> nonTrivialScopes) { Method blockMethod = (Method)Templates.GetTypeTemplateByName("BlockMethod").Members[0]; blockMethod.Name = new Identifier(block.Name); methodClass.Members.Add(blockMethod); blockMethod.DeclaringType = methodClass; // Generate the appropriate closing statements for the block. Indicate if the // block terminates an atomic region and establish the transfer of control to // the next block(s) or out of the method. if ((ZingCompilerOptions.IsPreemtive && !block.MiddleOfTransition && !block.IsReturn) || (block.Yields)) { // p.MiddleOfTransition = false; blockMethod.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( new QualifiedIdentifier(Identifier.For("p"), Identifier.For("MiddleOfTransition")), new Literal(false, SystemTypes.Boolean) ) ) ) ); } // p.AtomicityLevel = this.SavedAtomicityLevel + X; blockMethod.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( new QualifiedIdentifier(Identifier.For("p"), Identifier.For("AtomicityLevel")), new BinaryExpression( new QualifiedIdentifier(new This(), Identifier.For("SavedAtomicityLevel")), new Literal(block.RelativeAtomicLevel, SystemTypes.Int32), NodeType.Add ) ) ) ) ); #if false // // The following code was added for summarization, but isn't quite right. It // updates the nextBlock too early for some blocks. -- Tony // // // when generating summaries of type MaxCall, we need to // know the value of nextBlock before we invoke p.Call(). // the first of the two basic blocks of a Zing method call // is guaranteed to fall through, so we only need to lift // the assignment of nextBlock for fall-through blocks. if (block.ConditionalTarget == null && block.UnconditionalTarget != null) { stmt = Templates.GetStatementTemplate("UnconditionalBlockTransfer"); Replacer.Replace(stmt, "_UnconditionalBlock", new Identifier(block.UnconditionalTarget.Name)); blockMethod.Body.Statements.Add(stmt); } #endif if (block.Attributes != null) { Duplicator duplicator = new Duplicator(null, null); for (int i = 0, n = block.Attributes.Count; i < n; i++) { if (block.Attributes[i] == null) continue; AttributeNode dupAttr = duplicator.VisitAttributeNode(block.Attributes[i]); Normalizer normalizer = new Normalizer(false); ExpressionList attrParams = normalizer.VisitExpressionList(dupAttr.Expressions); // application.Trace(_context, _contextAttr, new Z.Attributes._attrName(...) ); ExpressionStatement traceStmt = new ExpressionStatement( new MethodCall( new QualifiedIdentifier(Identifier.For("application"), Identifier.For("Trace")), new ExpressionList( SourceContextConstructor(dupAttr.SourceContext), new Literal(null, SystemTypes.Object), new Construct( new MemberBinding( null, new TypeExpression( new QualifiedIdentifier( new QualifiedIdentifier(Identifier.For("Z"), Identifier.For("Attributes")), dupAttr.Type.Name ) ) ), attrParams ) ) ) ); blockMethod.Body.Statements.Add(traceStmt); } } if (block.Statement != null) { if (block.SkipNormalizer) blockMethod.Body.Statements.Add(block.Statement); else { // Do statement-level code-gen pass on the block's statement Normalizer normalizer = new Normalizer(this, block.Attributes, block.SecondOfTwo); blockMethod.Body.Statements.Add((Statement)normalizer.Visit(block.Statement)); } } if (block.ConditionalTarget != null && block.ConditionalExpression != null) { Block trueBlock, falseBlock; // if (_conditionalExpression) // nextBlock = Blocks._conditionalTarget; // else // nextBlock = Blocks._unconditionalTarget; blockMethod.Body.Statements.Add( new If( block.ConditionalExpression, trueBlock = new Block(new StatementList( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( Identifier.For("nextBlock"), new QualifiedIdentifier( Identifier.For("Blocks"), Identifier.For(block.ConditionalTarget.Name) ) ) ) ) )), falseBlock = new Block(new StatementList( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( Identifier.For("nextBlock"), new QualifiedIdentifier( Identifier.For("Blocks"), Identifier.For(block.UnconditionalTarget.Name) ) ) ) ) )) ) ); AddScopeCleanupCalls(trueBlock.Statements, block, block.ConditionalTarget, nonTrivialScopes); AddScopeCleanupCalls(falseBlock.Statements, block, block.UnconditionalTarget, nonTrivialScopes); } else if (block.UnconditionalTarget != null) { // nextBlock = Blocks.X; blockMethod.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( Identifier.For("nextBlock"), new QualifiedIdentifier(Identifier.For("Blocks"), Identifier.For(block.UnconditionalTarget.Name)) ) ) ) ); AddScopeCleanupCalls(blockMethod.Body.Statements, block, block.UnconditionalTarget, nonTrivialScopes); } else if (block.IsReturn) { Debug.Assert(block.UnconditionalTarget == null); Statement returnCall = Templates.GetStatementTemplate("ReturnBlockTransfer"); SourceContext context; Return ret = block.Statement as Return; if (ret != null) { context = ret.SourceContext; } else { // If not a return stmt, the context is the closing brace of the method context = zMethod.SourceContext; context.StartPos = context.EndPos - 1; } Replacer.Replace(returnCall, "_context", SourceContextConstructor(context)); Replacer.Replace(returnCall, "_contextAttr", ContextAttributeConstructor(block.Attributes)); blockMethod.Body.Statements.Add(returnCall); // StateImpl.IsReturn = true; blockMethod.Body.Statements.Add( new ExpressionStatement( new AssignmentExpression( new AssignmentStatement( new QualifiedIdentifier(Identifier.For("StateImpl"), Identifier.For("IsReturn")), new Literal(true, SystemTypes.Boolean) ) ) ) ); } }
private void PatchContextAttributeProperty(ZMethod zMethod, Class methodClass, List<BasicBlock> basicBlocks) { Property contextProperty = (Property)Templates.GetMemberByName(methodClass.Members, "ContextAttribute"); Method contextMethod = contextProperty.Getter; Debug.Assert(contextMethod.Body.Statements[0] is System.Compiler.Switch); System.Compiler.Switch switchStmt = (System.Compiler.Switch)contextMethod.Body.Statements[0]; foreach (BasicBlock block in basicBlocks) { AttributeNode contextAttr = GetContextAttribute(block.Attributes); if (contextAttr == null) continue; // no context attribute found SwitchCase newCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("ContextAttributeSwitch")).Cases[0]; Replacer.Replace(newCase, "_BlockName", new Identifier(block.Name)); // TODO: for user-defined attributes, we'll need to construct a qualified identifier here Replacer.Replace(newCase, "_AttributeName", contextAttr.Type.Name); // Patch the selected context columns into the constructor template Return ret = (Return)newCase.Body.Statements[0]; Construct cons = (Construct)ret.Expression; cons.Operands = contextAttr.Expressions; switchStmt.Cases.Add(newCase); } }
private void GenerateOutputs(ZMethod zMethod, Class outputsClass) { List<Field> outputs = new List<Field>(10); Method outputsGetValue = (Method)Templates.GetMemberByName(outputsClass.Members, "GetValue"); Method outputsSetValue = (Method)Templates.GetMemberByName(outputsClass.Members, "SetValue"); System.Compiler.Switch switchOutputsGetValue = (System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoSwitch"); outputsGetValue.Body.Statements.Add(switchOutputsGetValue); System.Compiler.Switch switchOutputsSetValue = (System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoSwitch"); outputsSetValue.Body.Statements.Add(switchOutputsSetValue); Method copier = (Method)Templates.GetMemberByName(outputsClass.Members, "CopyContents"); // Create fields in Inputs or Outputs for the parameters for (int i = 0, n = zMethod.Parameters.Count; i < n; i++) { Parameter param = zMethod.Parameters[i]; if (param == null || param.Type == null || (param.Flags & ParameterFlags.Out) == 0) continue; TypeNode zingType = param.Type; zingType = ((Reference)zingType).ElementType; Field f = new Field(outputsClass, null, FieldFlags.Public, new Identifier("priv_" + param.Name.Name), param.Type, null); if (f.Type is Reference) f.Type = ((Reference)f.Type).ElementType; if (GetTypeClassification(f.Type) == TypeClassification.Heap) { f.Type = this.ZingPtrType; } else if (!IsPredefinedType(f.Type)) f.Type = new TypeExpression(new QualifiedIdentifier( new Identifier("Application"), zingType.Name), zingType.SourceContext); Identifier idFieldName = new Identifier("id_" + param.Name.Name); Field idf = new Field(outputsClass, null, FieldFlags.Public | FieldFlags.Static, idFieldName, SystemTypes.Int32, null); idf.Initializer = new Literal(i, SystemTypes.Int32); SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0]; Replacer.Replace(getCase, "_fieldId", new Literal(i, SystemTypes.Int32)); Replacer.Replace(getCase, "_fieldName", new Identifier(f.Name.Name)); switchOutputsGetValue.Cases.Add(getCase); SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0]; Replacer.Replace(setCase, "_fieldId", new Literal(i, SystemTypes.Int32)); Replacer.Replace(setCase, "_fieldName", new Identifier(f.Name.Name)); TypeExpression tn = f.Type as TypeExpression; Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name)); switchOutputsSetValue.Cases.Add(setCase); QualifiedIdentifier localInputOrOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("Output")); Property accessor = GetAccessorProperty("outputAccessor", f.Type, param.Name, f.Name, idf.Name, localInputOrOutput); outputsClass.Members.Add(f); outputsClass.Members.Add(idf); outputsClass.Members.Add(accessor); f.DeclaringType = outputsClass; idf.DeclaringType = outputsClass; accessor.DeclaringType = outputsClass; if (accessor.Getter != null) { outputsClass.Members.Add(accessor.Getter); accessor.Getter.DeclaringType = outputsClass; } if (accessor.Setter != null) { outputsClass.Members.Add(accessor.Setter); accessor.Setter.DeclaringType = outputsClass; } //for outputs create an additional lastfunction accessor QualifiedIdentifier lfcOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("LastFunctionOutput")); Identifier lfcid = new Identifier("_Lfc_" + param.Name.Name); Property lfcAccessor = GetAccessorProperty("lastFunctionOutputAccessor", f.Type, lfcid, f.Name, idf.Name, lfcOutput); outputsClass.Members.Add(lfcAccessor); lfcAccessor.DeclaringType = outputsClass; if (lfcAccessor.Getter != null) { outputsClass.Members.Add(lfcAccessor.Getter); lfcAccessor.Getter.DeclaringType = outputsClass; } if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal) collectStructAccessors(false, (Struct)zingType, f.Name, param.Name.Name, outputsClass); copier.Body.Statements.Add(GetCopyStatement(f.Name)); outputs.Add(f); } if (zMethod.ReturnType.TypeCode != TypeCode.Empty) { Field f = new Field(outputsClass, null, FieldFlags.Public, new Identifier("priv_ReturnValue"), zMethod.ReturnType, null); QualifiedIdentifier localInputOrOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("Output")); TypeNode zingType = zMethod.ReturnType; if (GetTypeClassification(f.Type) == TypeClassification.Heap) { f.Type = this.ZingPtrType; } else if (!IsPredefinedType(f.Type)) { f.Type = new TypeExpression(new QualifiedIdentifier( new Identifier("Application"), zingType.Name), zingType.SourceContext); } Identifier idFieldName = new Identifier("id_ReturnValue"); Field idf = new Field(outputsClass, null, FieldFlags.Public | FieldFlags.Static, idFieldName, SystemTypes.Int32, null); idf.Initializer = new Literal(zMethod.Parameters.Count, SystemTypes.Int32); SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0]; Replacer.Replace(getCase, "_fieldId", new Literal(zMethod.Parameters.Count, SystemTypes.Int32)); Replacer.Replace(getCase, "_fieldName", new Identifier("priv_ReturnValue")); switchOutputsGetValue.Cases.Add(getCase); SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0]; Replacer.Replace(setCase, "_fieldId", new Literal(zMethod.Parameters.Count, SystemTypes.Int32)); Replacer.Replace(setCase, "_fieldName", new Identifier("priv_ReturnValue")); TypeExpression tn = f.Type as TypeExpression; Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name)); switchOutputsSetValue.Cases.Add(setCase); Property accessor = GetAccessorProperty("outputAccessor", f.Type, new Identifier("_ReturnValue"), f.Name, idf.Name, localInputOrOutput); QualifiedIdentifier lfcOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("LastFunctionOutput")); Property lfcAccessor = GetAccessorProperty("lastFunctionOutputAccessor", f.Type, new Identifier("_Lfc_ReturnValue"), f.Name, idf.Name, lfcOutput); Identifier qualifier = new Identifier("outputs"); outputsClass.Members.Add(f); outputsClass.Members.Add(idf); outputsClass.Members.Add(accessor); outputsClass.Members.Add(lfcAccessor); f.DeclaringType = outputsClass; idf.DeclaringType = outputsClass; accessor.DeclaringType = outputsClass; lfcAccessor.DeclaringType = outputsClass; if (accessor.Getter != null) { outputsClass.Members.Add(accessor.Getter); accessor.Getter.DeclaringType = outputsClass; } if (accessor.Setter != null) { outputsClass.Members.Add(accessor.Setter); accessor.Setter.DeclaringType = outputsClass; } if (lfcAccessor.Getter != null) { outputsClass.Members.Add(lfcAccessor.Getter); lfcAccessor.Getter.DeclaringType = outputsClass; } if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal) { collectStructAccessors(false, (Struct)zingType, f.Name, "_ReturnValue", outputsClass); collectStructAccessors(false, (Struct)zingType, f.Name, "_Lfc_ReturnValue", outputsClass); } copier.Body.Statements.Add(GetCopyStatement(f.Name)); outputs.Add(f); } Method writer = (Method)Templates.GetMemberByName(outputsClass.Members, "WriteString"); Method traverser = (Method)Templates.GetMemberByName(outputsClass.Members, "TraverseFields"); for (int i = 0, n = outputs.Count; i < n; i++) { Field f = (Field)outputs[i]; writer.Body.Statements.Add (GetWriterStatement("this", f.Type, f.Name)); traverser.Body.Statements.Add(GetTraverserStatement("this", f.Type, f.Name)); } }
private void GenerateLocals(ZMethod zMethod, Class localsClass) { List<Field> locals = new List<Field>(10); Method localsGetValue = (Method)Templates.GetMemberByName(localsClass.Members, "GetValue"); Method localsSetValue = (Method)Templates.GetMemberByName(localsClass.Members, "SetValue"); System.Compiler.Switch switchLocalsGetValue = (System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoSwitch"); localsGetValue.Body.Statements.Add(switchLocalsGetValue); System.Compiler.Switch switchLocalsSetValue = (System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoSwitch"); localsSetValue.Body.Statements.Add(switchLocalsSetValue); Method copier = (Method)Templates.GetMemberByName(localsClass.Members, "CopyContents"); for (int i = 0, n = zMethod.LocalVars.Count; i < n; i++) { Field localVar = zMethod.LocalVars[i]; TypeNode zingType = localVar.Type; if (localVar.Type == null) continue; Field f = new Field(localsClass, null, FieldFlags.Public, new Identifier("priv_" + localVar.Name.Name), localVar.Type, null); if (GetTypeClassification(f.Type) == TypeClassification.Heap) f.Type = this.ZingPtrType; else if (!IsPredefinedType(f.Type)) f.Type = new TypeExpression(new QualifiedIdentifier( new Identifier("Application"), zingType.Name), zingType.SourceContext); Identifier idFieldName = new Identifier("id_" + localVar.Name.Name); Field idf = new Field(localsClass, null, FieldFlags.Public | FieldFlags.Static, idFieldName, SystemTypes.Int32, null); idf.Initializer = new Literal(i, SystemTypes.Int32); SwitchCase getCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("GetFieldInfoCase")).Cases[0]; Replacer.Replace(getCase, "_fieldId", new Literal(i, SystemTypes.Int32)); Replacer.Replace(getCase, "_fieldName", new Identifier(f.Name.Name)); switchLocalsGetValue.Cases.Add(getCase); SwitchCase setCase = ((System.Compiler.Switch)Templates.GetStatementTemplate("SetFieldInfoCase")).Cases[0]; Replacer.Replace(setCase, "_fieldId", new Literal(i, SystemTypes.Int32)); Replacer.Replace(setCase, "_fieldName", new Identifier(f.Name.Name)); TypeExpression tn = f.Type as TypeExpression; Replacer.Replace(setCase, "_fieldType", tn != null ? tn.Expression : new Identifier(f.Type.Name.Name)); switchLocalsSetValue.Cases.Add(setCase); QualifiedIdentifier localInputOrOutput = new QualifiedIdentifier(new Identifier("LocType"), new Identifier("Local")); Property accessor = GetAccessorProperty("localAccessor", f.Type, localVar.Name, f.Name, idf.Name, localInputOrOutput); Identifier qualifier = new Identifier("locals"); localsClass.Members.Add(f); localsClass.Members.Add(idf); localsClass.Members.Add(accessor); f.DeclaringType = localsClass; idf.DeclaringType = localsClass; accessor.DeclaringType = localsClass; if (accessor.Getter != null) { localsClass.Members.Add(accessor.Getter); accessor.Getter.DeclaringType = localsClass; } if (accessor.Setter != null) { localsClass.Members.Add(accessor.Setter); accessor.Setter.DeclaringType = localsClass; } if (zingType is Struct && !zingType.IsPrimitive && f.Type != SystemTypes.Decimal) collectStructAccessors(false, (Struct)zingType, f.Name, localVar.Name.Name, localsClass); copier.Body.Statements.Add(GetCopyStatement(f.Name)); locals.Add(f); } Method writer = (Method)Templates.GetMemberByName(localsClass.Members, "WriteString"); Method traverser = (Method)Templates.GetMemberByName(localsClass.Members, "TraverseFields"); for (int i = 0, n = locals.Count; i < n; i++) { Field f = (Field)locals[i]; writer.Body.Statements.Add(GetWriterStatement("this", f.Type, f.Name)); traverser.Body.Statements.Add(GetTraverserStatement("this", f.Type, f.Name)); } }
private Class GenerateInterfaceMethod(ZMethod zMethod) { this.currentMethod = zMethod; Class newClass = (Class)Templates.GetTypeTemplateByName("InterfaceMethod"); Debug.Assert(!zMethod.IsStatic); GenerateThisParameter(newClass); Class inputsClass = (Class)Templates.GetMemberByName(newClass.Members, "InputVars"); GenerateInputs(zMethod, inputsClass); Class outputsClass = (Class)Templates.GetMemberByName(newClass.Members, "OutputVars"); GenerateOutputs(zMethod, outputsClass); Replacer.Replace(newClass, newClass.Name, zMethod.Name); // If this method doesn't return concrete bool, then remove the helper // property for accessing bool return values. if (zMethod.ReturnType == SystemTypes.Boolean) { Property boolRetValProp = (Property)Templates.GetTypeTemplateByName("BooleanReturnValueProperty").Members[0]; newClass.Members.Add(boolRetValProp); boolRetValProp.DeclaringType = newClass; newClass.Members.Add(boolRetValProp.Getter); boolRetValProp.Getter.DeclaringType = newClass; } // Clear the "Activated" attribute if we aren't... if (!zMethod.Activated) newClass.Attributes = new AttributeList(0); this.currentMethod = null; return newClass; }