protected void ReturnArray(CodeGenContext context)
 {
     // Ruby.Eval.Return(array, caller);
     array.GenCode(context);
     context.ldloc(0);
     context.call(Runtime.Eval.Return);
 }
        internal override void Assign(CodeGenContext context, Node rhs)
        {
            // Gen right hand sides
            ListGen mrhs;
            if (rhs is ListGen && !(rhs is MultipleRHS))
                mrhs = (ListGen)rhs;
            else
                mrhs = new ARGS(null, null, rhs, null, location, true);

            bool created;
            ISimple list = mrhs.GenArgList(context, out created);
            list.GenSimple(context);
            context.callvirt(Runtime.ArgList.CheckSingleRHS);
            int array = context.StoreInTemp("mrhs", Runtime.ArgListRef, location);

            context.ReleaseLocal(list, created);

            // Gen assignments to left hand sides
            for (LVALUE l = elements; l != null; l = (LVALUE)l.nd_next)
            {
                l.Assign(context, new MultipleRHS(array, l.location));
                context.pop();
            }

            context.ldloc(array);
            context.callvirt(Runtime.ArgList.ToRubyArray);

            context.ReleaseLocal(array, true);
        }
Beispiel #3
0
        internal override void GenCode0(CodeGenContext context)
        {
            // String.Concat(String.Concat(arg1, arg2), args, ...);

            head.GenCode0(context);

            if (head.nd_next != null)
            {
                int first = context.StoreInTemp("head", Runtime.StringRef, head.location);

                for (Node n = head.nd_next; n != null; n = n.nd_next)
                {
                    n.GenCode0(context);
                    int second = context.StoreInTemp("tail", Runtime.StringRef, n.location);

                    context.ldloc(first);
                    context.ldloc(second);
                    context.callvirt(Runtime.String.Concat);
                    context.stloc(first);

                    context.ReleaseLocal(second, true);
                }

                context.ldloc(first);

                context.ReleaseLocal(first, true);
            }
        }
Beispiel #4
0
 internal override void Defined(CodeGenContext context)
 {
     if (args != null)
         new AND(new ProxyNode(MethodDefined, location), new ProxyNode(((Node)args).Defined, location), location).GenCode(context);
     else
         MethodDefined(context);
 }
Beispiel #5
0
        internal void GenCall(CodeGenContext context)
        {
            int result = context.CreateLocal("result", PrimitiveType.Object);

            PERWAPI.CILLabel endLabel = context.NewLabel();
            PERWAPI.CILLabel retryLabel = context.NewLabel();

            context.CodeLabel(retryLabel);

            context.StartBlock(Clause.Try);
            {
                // object result = Call(...)
                GenCall0(context);
                context.stloc(result);

                context.Goto(endLabel);
            }
            PERWAPI.TryBlock tryBlock = context.EndTryBlock();
            context.StartBlock(Clause.Catch);
            {
                CatchBreakException(context, result, endLabel);
            }
            context.EndCatchBlock(Runtime.BreakExceptionRef, tryBlock);
            context.StartBlock(Clause.Catch);
            {
                CatchRetryException(context, retryLabel);
            }
            context.EndCatchBlock(Runtime.RetryExceptionRef, tryBlock);

            context.CodeLabel(endLabel);
            context.ldloc(result);

            context.ReleaseLocal(result, true);
        }
Beispiel #6
0
        internal override void GenCode0(CodeGenContext context)
        {
            // hash = new Hash();
            context.newobj(Runtime.Hash.ctor);
            int hash = context.StoreInTemp("hash", Runtime.HashRef, location);

            Node entry = elements;
            while (entry != null)
            {
                bool key_created, value_created;

                ISimple key = context.PreCompute0(entry, "key", out key_created);
                entry = entry.nd_next;
                ISimple value = context.PreCompute0(entry, "value", out value_created);
                entry = entry.nd_next;

                // hash.Add(key, value);
                context.ldloc(hash);
                key.GenSimple(context);
                value.GenSimple(context);
                context.callvirt(Runtime.Hash.Add);

                context.ReleaseLocal(key, key_created);
                context.ReleaseLocal(value, value_created);
            }

            context.ldloc(hash);

            context.ReleaseLocal(hash, true);
        }
Beispiel #7
0
        protected new PERWAPI.MethodDef GenerateClassForMethod(CodeGenContext context)
        {
            // public class Eval: IEval {
            evalClass = context.CreateGlobalClass("_Internal", "Eval", Runtime.SystemObjectRef);
            evalClass.AddImplementedInterface(Runtime.IEvalRef);

            if (context.CurrentRubyClass == null)
            {
                context.CurrentRubyClass = CodeGenContext.AddField(evalClass, PERWAPI.FieldAttr.PublicStatic, "myRubyClass", Runtime.ClassRef);

                CodeGenContext cctor = context.CreateStaticConstructor(evalClass);

                cctor.ldsfld(Runtime.Init.rb_cObject);
                cctor.stsfld(context.CurrentRubyClass);
                cctor.ret();
                cctor.Close();
            }

            MethodDef constructor = GenConstructor(evalClass, context);

            GenInvokeMethod(evalClass, context);

            return constructor;
            // }
        }
		public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
		{
			// arg0: Serializer, arg1: Stream, arg2: value

			var fields = Helpers.GetFieldInfos(type);

			foreach (var field in fields)
			{
				// Note: the user defined value type is not passed as reference. could cause perf problems with big structs

				var fieldType = field.FieldType;

				var data = ctx.GetTypeDataForCall(fieldType);

				if (data.NeedsInstanceParameter)
					il.Emit(OpCodes.Ldarg_0);

				il.Emit(OpCodes.Ldarg_1);
				if (type.IsValueType)
					il.Emit(OpCodes.Ldarga_S, 2);
				else
					il.Emit(OpCodes.Ldarg_2);
				il.Emit(OpCodes.Ldfld, field);

				il.Emit(OpCodes.Call, data.WriterMethodInfo);
			}

			il.Emit(OpCodes.Ret);
		}
Beispiel #9
0
 internal virtual void GenCode0(CodeGenContext context)
 {
     if (this is ISimple)
         ((ISimple)this).GenSimple(context);
     else
         throw new NotImplementedException(GetType().ToString());
 }
		public void GenerateWriterMethod(Type obtype, CodeGenContext ctx, ILGenerator il)
		{
			var getTypeIDMethodInfo = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Instance, null,
				new Type[] { typeof(object) }, null);

			var map = ctx.TypeMap;

			// arg0: Serializer, arg1: Stream, arg2: object

			var idLocal = il.DeclareLocal(typeof(ushort));

			// get TypeID from object's Type
			il.Emit(OpCodes.Ldarg_0);
			il.Emit(OpCodes.Ldarg_2);
			il.Emit(OpCodes.Call, getTypeIDMethodInfo);
			il.Emit(OpCodes.Stloc_S, idLocal);

			// write typeID
			il.Emit(OpCodes.Ldarg_1);
			il.Emit(OpCodes.Ldloc_S, idLocal);
			il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)));

			// +1 for 0 (null)
			var jumpTable = new Label[map.Count + 1];
			jumpTable[0] = il.DefineLabel();
			foreach (var kvp in map)
				jumpTable[kvp.Value.TypeID] = il.DefineLabel();

			il.Emit(OpCodes.Ldloc_S, idLocal);
			il.Emit(OpCodes.Switch, jumpTable);

			il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo);
			il.Emit(OpCodes.Throw);

			/* null case */
			il.MarkLabel(jumpTable[0]);
			il.Emit(OpCodes.Ret);

			/* cases for types */
			foreach (var kvp in map)
			{
				var type = kvp.Key;
				var data = kvp.Value;

				il.MarkLabel(jumpTable[data.TypeID]);

				if (data.NeedsInstanceParameter)
					il.Emit(OpCodes.Ldarg_0);

				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Ldarg_2);
				il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

				il.Emit(OpCodes.Tailcall);
				il.Emit(OpCodes.Call, data.WriterMethodInfo);

				il.Emit(OpCodes.Ret);
			}
		}
Beispiel #11
0
        internal override void GenCode0(CodeGenContext context)
        {
            bool created;
            ISimple list = GenArgList(context, out created);
            list.GenSimple(context);
            context.callvirt(Runtime.ArgList.ToRubyObject);

            context.ReleaseLocal(list, created);
        }
Beispiel #12
0
 internal void GenCode(CodeGenContext context)
 {
     for (Node stmt = this; stmt != null; stmt = stmt.nd_next)
     {
         stmt.GenCode0(context);
         if (stmt.nd_next != null && context.Reachable())
             context.pop();
     }
 }
Beispiel #13
0
        internal override void GenCode0(CodeGenContext context)
        {
            bool created;
            ISimple left = context.PreCompute(lhs, "lhs", out created);

            new COND((Node)left, (Node)left, rhs, location).GenCode(context);

            context.ReleaseLocal(left, created);
        }
		public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
		{
			// arg0: Serializer, arg1: stream, arg2: out value

			if (type.IsClass)
			{
				// instantiate empty class
				il.Emit(OpCodes.Ldarg_2);

				var gtfh = typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static);
				var guo = typeof(System.Runtime.Serialization.FormatterServices).GetMethod("GetUninitializedObject", BindingFlags.Public | BindingFlags.Static);
				il.Emit(OpCodes.Ldtoken, type);
				il.Emit(OpCodes.Call, gtfh);
				il.Emit(OpCodes.Call, guo);
				il.Emit(OpCodes.Castclass, type);

				il.Emit(OpCodes.Stind_Ref);
			}

			var fields = Helpers.GetFieldInfos(type);

			foreach (var field in fields)
			{
				var fieldType = field.FieldType;

				var data = ctx.GetTypeDataForCall(fieldType);

				if (data.NeedsInstanceParameter)
					il.Emit(OpCodes.Ldarg_0);

				il.Emit(OpCodes.Ldarg_1);
				il.Emit(OpCodes.Ldarg_2);
				if (type.IsClass)
					il.Emit(OpCodes.Ldind_Ref);
				il.Emit(OpCodes.Ldflda, field);

				il.Emit(OpCodes.Call, data.ReaderMethodInfo);
			}

			if (typeof(System.Runtime.Serialization.IDeserializationCallback).IsAssignableFrom(type))
			{
				var miOnDeserialization = typeof(System.Runtime.Serialization.IDeserializationCallback).GetMethod("OnDeserialization",
										BindingFlags.Instance | BindingFlags.Public,
										null, new[] { typeof(Object) }, null);

				il.Emit(OpCodes.Ldarg_2);
				il.Emit(OpCodes.Ldnull);
				il.Emit(OpCodes.Constrained, type);
				il.Emit(OpCodes.Callvirt, miOnDeserialization);
			}

			il.Emit(OpCodes.Ret);
		}
 private ISimple PushScope(CodeGenContext context, out bool created)
 {
     if (name != null && name.scope != null)
         return context.PreCompute(name.scope, "scope", out created);
     else
     {
         created = false;
         if (context.CurrentRubyClass != null)
             return new StaticField(context.CurrentRubyClass, name.location);
         else
             return new StaticField(Runtime.Init.rb_cObject, name.location);
     }
 }
Beispiel #16
0
        internal PERWAPI.PEFile GenerateCode(Field CurrentRubyClass)
        {
            CodeGenContext context = new CodeGenContext();
            context.CurrentRubyClass = CurrentRubyClass;

            string name = "Eval_" + System.Guid.NewGuid().ToString("N");

            context.CreateAssembly("./", name + ".dll", name, false);

            GenerateClassForMethod(context);
                      
            return context.Assembly;
        }
Beispiel #17
0
        internal override void GenCode0(CodeGenContext context)
        {
            if (args != null)
            {
                bool created;
                ISimple list = args.GenArgList(context, out created);
                list.GenSimple(context);
                context.callvirt(Runtime.ArgList.ToRubyArray);

                context.ReleaseLocal(list, created);
            }
            else
                context.newobj(Runtime.Array.ctor);
        }
Beispiel #18
0
        internal override void GenCode0(CodeGenContext context)
        {
            PERWAPI.CILLabel elseLabel = context.NewLabel();
            PERWAPI.CILLabel endLabel = context.NewLabel();

            // if (Eval.Test(cond))
            cond.GenCode(context);
            context.call(Runtime.Eval.Test);
            context.brfalse(elseLabel);
            body.GenCode(context);
            context.br(endLabel);
            context.CodeLabel(elseLabel);
            _else.GenCode(context);
            context.CodeLabel(endLabel);
        }
        internal override void GenCode0(CodeGenContext context)
        {
            PERWAPI.CILLabel finalLabel = context.NewLabel();

            int RescueTemp = context.CreateLocal("rescueTemp", PERWAPI.PrimitiveType.Object);
            context.ldnull();
            context.stloc(RescueTemp);

            if (ensure != null)
            {
                context.StartBlock(Clause.Try); // outer try block with finally

                context.StartBlock(Clause.Try); // inner try block with catch
            }

            GenInnerBlock(context, RescueTemp);

            if (ensure != null)
            {
                context.Goto(finalLabel);

                PERWAPI.TryBlock innerTry = context.EndTryBlock();

                context.StartBlock(Clause.Catch);
                GenRescue(context, null, 0, null);
                context.EndCatchBlock(Runtime.SystemExceptionRef, innerTry);

                PERWAPI.TryBlock outerTry = context.EndTryBlock();
                
                // Fixme: reset labels to prevent branches out of finally block.    
                context.StartBlock(Clause.Finally);
                ensure.GenCode(context);
                if (context.Reachable())
                    context.pop();
                context.endfinally();
                context.EndFinallyBlock(outerTry);

                context.CodeLabel(finalLabel);
                context.newEndPoint(location);
            }

            context.ldloc(RescueTemp);

            context.ReleaseLocal(RescueTemp, true);
        }
Beispiel #20
0
        internal void CopySimple(CodeGenContext context, Scope scope)
        {
            if (block != null)
            {
                // locals.block = block;
                string bname = ID.ToDotNetName(block.vid);
                context.ldloc(0);
                LoadBlock(context);
                context.stfld(scope.GetFrameField(bname));
            }

            for (Node f = normal; f != null; f = f.nd_next)
            {
                string fname = ID.ToDotNetName(((VAR)f).vid);

                // local.f = f;
                context.ldloc(0);
                context.ldarg(fname);
                context.stfld(scope.GetFrameField(fname));
            }
        }
Beispiel #21
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            // arg0: buffer, arg1: value

            var fields = Helpers.GetFieldInfos(type);

            foreach (var field in fields)
            {
                // Note: the user defined value type is not passed as reference. could cause perf problems with big structs

                il.Emit(OpCodes.Ldarg_0);
                if (type.IsValueType)
                    il.Emit(OpCodes.Ldarga_S, 1);
                else
                    il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldfld, field);

                Helpers.GenSerializerCall(ctx, il, field.FieldType);
            }

            il.Emit(OpCodes.Ret);
        }
Beispiel #22
0
        public void GenSimple(CodeGenContext context)
        {
            if (value is string)// T_STRING,
            {
                context.ldstr((string)(value));
                context.newobj(Runtime.String.ctor);
                return;
            }
            if (value is int)   // T_FIXNUM
            {
                context.ldc_i4((int)(value));
                context.box(PrimitiveType.Int32);
                return;
            }
            if (value is double)// T_FLOAT
            {
                context.ldc_r8((double)(value));
                context.newobj(Runtime.Float.ctor);
                return;
            }
            if (value is ID)    // T_SYMBOL
            {
                context.ldstr(((ID)value).ToString());
                context.newobj(Runtime.Symbol.ctor);
                return;
            }
            if (value is BigNum)
            {
                BigNum num = (BigNum) value;
                context.ldc_i4(num.sign);
                context.ldstr(num.ToString());
                context.ldc_i4(num.bas);
                context.newobj(Runtime.Bignum.ctor);
                return;
            }

            throw new System.NotImplementedException("VALUE " + value.GetType().ToString());
        }
Beispiel #23
0
        internal override void GenCode0(CodeGenContext context)
        {
            PERWAPI.CILLabel elseLabel = context.NewLabel();
            PERWAPI.CILLabel endLabel = context.NewLabel();

            // if (Eval.Test(cond))
            context.newLine(cond.location);
            cond.GenCode(context);
            context.call(Runtime.Eval.Test);
            context.brfalse(elseLabel);

            if (body != null)
            {
                context.newStartPoint(body.location);
                body.GenCode(context);
            }
            else
                context.ldnull();

            if (context.Reachable())
                context.br(endLabel);

            context.CodeLabel(elseLabel);


            if (_else != null)
            {
                context.newStartPoint(_else.location);
                _else.GenCode(context);
            }
            else
                context.ldnull();

            context.CodeLabel(endLabel);
            context.newEndPoint(location);
        }
Beispiel #24
0
        public void GenerateReaderMethod(Type obtype, CodeGenContext ctx, ILGenerator il)
        {
            var map = ctx.TypeMap;

            // arg0: Serializer, arg1: stream, arg2: out object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // read typeID
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloca_S, idLocal);
            il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(ushort)));

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];

            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
            {
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();
            }

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                var local = il.DeclareLocal(type);

                // call deserializer for this typeID
                if (data.NeedsInstanceParameter)
                {
                    il.Emit(OpCodes.Ldarg_0);
                }

                il.Emit(OpCodes.Ldarg_1);
                if (local.LocalIndex < 256)
                {
                    il.Emit(OpCodes.Ldloca_S, local);
                }
                else
                {
                    il.Emit(OpCodes.Ldloca, local);
                }

                il.Emit(OpCodes.Call, data.ReaderMethodInfo);

                // write result object to out object
                il.Emit(OpCodes.Ldarg_2);
                if (local.LocalIndex < 256)
                {
                    il.Emit(OpCodes.Ldloc_S, local);
                }
                else
                {
                    il.Emit(OpCodes.Ldloc, local);
                }
                if (type.IsValueType)
                {
                    il.Emit(OpCodes.Box, type);
                }
                il.Emit(OpCodes.Stind_Ref);

                il.Emit(OpCodes.Ret);
            }
        }
Beispiel #25
0
        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); 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}\".");
        }
Beispiel #26
0
        public void GenerateWriterMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var notNullLabel = il.DefineLabel();

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            // if value == null, write 0
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Tailcall);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            // write array len + 1
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(uint)));

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel  = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            var data = ctx.GetTypeDataForCall(elemType);

            if (data.NeedsInstanceParameter)
            {
                il.Emit(OpCodes.Ldarg_0);
            }

            // write element at index i
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelem, elemType);

            il.Emit(OpCodes.Call, data.WriterMethodInfo);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);

            il.Emit(OpCodes.Ret);
        }
Beispiel #27
0
        public void GenerateWriterMethod(Type obtype, CodeGenContext ctx, ILGenerator il)
        {
            var getTypeIDMethodInfo = typeof(Serializer).GetMethod("GetTypeID", BindingFlags.NonPublic | BindingFlags.Instance, null,
                                                                   new Type[] { typeof(object) }, null);

            var map = ctx.TypeMap;

            // arg0: Serializer, arg1: Stream, arg2: object

            var idLocal = il.DeclareLocal(typeof(ushort));

            // get TypeID from object's Type
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Call, getTypeIDMethodInfo);
            il.Emit(OpCodes.Stloc_S, idLocal);

            // write typeID
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Call, ctx.GetWriterMethodInfo(typeof(ushort)));

            // +1 for 0 (null)
            var jumpTable = new Label[map.Count + 1];

            jumpTable[0] = il.DefineLabel();
            foreach (var kvp in map)
            {
                jumpTable[kvp.Value.TypeID] = il.DefineLabel();
            }

            il.Emit(OpCodes.Ldloc_S, idLocal);
            il.Emit(OpCodes.Switch, jumpTable);

            il.Emit(OpCodes.Newobj, Helpers.ExceptionCtorInfo);
            il.Emit(OpCodes.Throw);

            /* null case */
            il.MarkLabel(jumpTable[0]);
            il.Emit(OpCodes.Ret);

            /* cases for types */
            foreach (var kvp in map)
            {
                var type = kvp.Key;
                var data = kvp.Value;

                il.MarkLabel(jumpTable[data.TypeID]);

                if (data.NeedsInstanceParameter)
                {
                    il.Emit(OpCodes.Ldarg_0);
                }

                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Ldarg_2);
                il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);

                il.Emit(OpCodes.Tailcall);
                il.Emit(OpCodes.Call, data.WriterMethodInfo);

                il.Emit(OpCodes.Ret);
            }
        }
Beispiel #28
0
 public Instruction GetNextLabelAutoIncrement(CodeGenContext context)
 {
     return(GetLabel(context, _entryCount++));
 }
Beispiel #29
0
        public void GenerateReaderMethod(Type type, CodeGenContext ctx, ILGenerator il)
        {
            var elemType = type.GetElementType();

            var lenLocal = il.DeclareLocal(typeof(uint));

            // read array len
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloca_S, lenLocal);
            il.Emit(OpCodes.Call, ctx.GetReaderMethodInfo(typeof(uint)));

            var notNullLabel = il.DefineLabel();

            /* if len == 0, return null */
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Brtrue_S, notNullLabel);

            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stind_Ref);
            il.Emit(OpCodes.Ret);

            il.MarkLabel(notNullLabel);

            var arrLocal = il.DeclareLocal(type);

            // create new array with len - 1
            il.Emit(OpCodes.Ldloc_S, lenLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Sub);
            il.Emit(OpCodes.Newarr, elemType);
            il.Emit(OpCodes.Stloc_S, arrLocal);

            // declare i
            var idxLocal = il.DeclareLocal(typeof(int));

            // i = 0
            il.Emit(OpCodes.Ldc_I4_0);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            var loopBodyLabel  = il.DefineLabel();
            var loopCheckLabel = il.DefineLabel();

            il.Emit(OpCodes.Br_S, loopCheckLabel);

            // loop body
            il.MarkLabel(loopBodyLabel);

            // read element to arr[i]

            var data = ctx.GetTypeDataForCall(elemType);

            if (data.NeedsInstanceParameter)
            {
                il.Emit(OpCodes.Ldarg_0);
            }

            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldelema, elemType);

            il.Emit(OpCodes.Call, data.ReaderMethodInfo);

            // i = i + 1
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldc_I4_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_S, idxLocal);

            il.MarkLabel(loopCheckLabel);

            // loop condition
            il.Emit(OpCodes.Ldloc_S, idxLocal);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Ldlen);
            il.Emit(OpCodes.Conv_I4);
            il.Emit(OpCodes.Clt);
            il.Emit(OpCodes.Brtrue_S, loopBodyLabel);


            // store new array to the out value
            il.Emit(OpCodes.Ldarg_2);
            il.Emit(OpCodes.Ldloc_S, arrLocal);
            il.Emit(OpCodes.Stind_Ref);

            il.Emit(OpCodes.Ret);
        }
 protected override void GenerateCodeForConditionalBranch(CodeGenContext context, BranchTargetLabel label, bool reverse)
 {
     Left.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
     Right.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
     context.GenerateBinaryCompareConditionalBranch(Op, label, reverse);
 }
Beispiel #31
0
 public Instruction GetNextLabel(CodeGenContext context)
 {
     return(GetLabel(context, _entryCount));
 }
Beispiel #32
0
        public static string ImageLoadOrStore(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;

            bool isArray   = (texOp.Type & SamplerType.Array) != 0;
            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;

            string texCall = texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore";

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + imageName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount + (isArray ? 1 : 0);

            void Append(string str)
            {
                texCall += ", " + str;
            }

            if (pCount > 1)
            {
                string[] elems = new string[pCount];

                for (int index = 0; index < pCount; index++)
                {
                    elems[index] = Src(VariableType.S32);
                }

                Append("ivec" + pCount + "(" + string.Join(", ", elems) + ")");
            }
            else
            {
                Append(Src(VariableType.S32));
            }

            if (texOp.Inst == Instruction.ImageStore)
            {
                VariableType type = texOp.Format.GetComponentType();

                string[] cElems = new string[4];

                for (int index = 0; index < 4; index++)
                {
                    if (srcIndex < texOp.SourcesCount)
                    {
                        cElems[index] = Src(type);
                    }
                    else
                    {
                        cElems[index] = type switch
                        {
                            VariableType.S32 => NumberFormatter.FormatInt(0),
                            VariableType.U32 => NumberFormatter.FormatUint(0),
                            _ => NumberFormatter.FormatFloat(0)
                        };
                    }
                }

                string prefix = type switch
                {
                    VariableType.S32 => "i",
                    VariableType.U32 => "u",
                    _ => string.Empty
                };

                Append(prefix + "vec4(" + string.Join(", ", cElems) + ")");
            }

            texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : "");

            return(texCall);
        }
Beispiel #33
0
        public static string TextureSample(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless    = (texOp.Flags & TextureFlags.Bindless) != 0;
            bool isGather      = (texOp.Flags & TextureFlags.Gather) != 0;
            bool intCoords     = (texOp.Flags & TextureFlags.IntCoords) != 0;
            bool hasLodBias    = (texOp.Flags & TextureFlags.LodBias) != 0;
            bool hasLodLevel   = (texOp.Flags & TextureFlags.LodLevel) != 0;
            bool hasOffset     = (texOp.Flags & TextureFlags.Offset) != 0;
            bool hasOffsets    = (texOp.Flags & TextureFlags.Offsets) != 0;
            bool isArray       = (texOp.Type & TextureType.Array) != 0;
            bool isMultisample = (texOp.Type & TextureType.Multisample) != 0;
            bool isShadow      = (texOp.Type & TextureType.Shadow) != 0;

            string texCall = intCoords ? "texelFetch" : "texture";

            if (isGather)
            {
                texCall += "Gather";
            }
            else if (hasLodLevel && !intCoords)
            {
                texCall += "Lod";
            }

            if (hasOffset)
            {
                texCall += "Offset";
            }
            else if (hasOffsets)
            {
                texCall += "Offsets";
            }

            string samplerName = OperandManager.GetSamplerName(context.Config.Type, texOp);

            texCall += "(" + samplerName;

            int coordsCount = texOp.Type.GetCoordsCount();

            int pCount = coordsCount;

            int arrayIndexElem = -1;

            if (isArray)
            {
                arrayIndexElem = pCount++;
            }

            // The sampler 1D shadow overload expects a
            // dummy value on the middle of the vector, who knows why...
            bool hasDummy1DShadowElem = texOp.Type == (TextureType.Texture1D | TextureType.Shadow);

            if (hasDummy1DShadowElem)
            {
                pCount++;
            }

            if (isShadow && !isGather)
            {
                pCount++;
            }

            // On textureGather*, the comparison value is
            // always specified as an extra argument.
            bool hasExtraCompareArg = isShadow && isGather;

            if (pCount == 5)
            {
                pCount = 4;

                hasExtraCompareArg = true;
            }

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            void Append(string str)
            {
                texCall += ", " + str;
            }

            VariableType coordType = intCoords ? VariableType.S32 : VariableType.F32;

            string AssemblePVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        if (arrayIndexElem == index)
                        {
                            elems[index] = Src(VariableType.S32);

                            if (!intCoords)
                            {
                                elems[index] = "float(" + elems[index] + ")";
                            }
                        }
                        else if (index == 1 && hasDummy1DShadowElem)
                        {
                            elems[index] = NumberFormatter.FormatFloat(0);
                        }
                        else
                        {
                            elems[index] = Src(coordType);
                        }
                    }

                    string prefix = intCoords ? "i" : string.Empty;

                    return(prefix + "vec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(coordType));
                }
            }

            Append(AssemblePVector(pCount));

            if (hasExtraCompareArg)
            {
                Append(Src(VariableType.F32));
            }

            if (isMultisample)
            {
                Append(Src(VariableType.S32));
            }
            else if (hasLodLevel)
            {
                Append(Src(coordType));
            }

            string AssembleOffsetVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        elems[index] = Src(VariableType.S32);
                    }

                    return("ivec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(VariableType.S32));
                }
            }

            if (hasOffset)
            {
                Append(AssembleOffsetVector(coordsCount));
            }
            else if (hasOffsets)
            {
                texCall += $", ivec{coordsCount}[4](";

                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ")";
            }

            if (hasLodBias)
            {
                Append(Src(VariableType.F32));
            }

            // textureGather* optional extra component index,
            // not needed for shadow samplers.
            if (isGather && !isShadow)
            {
                Append(Src(VariableType.S32));
            }

            texCall += ")" + (isGather || !isShadow ? GetMask(texOp.ComponentMask) : "");

            return(texCall);
        }
        protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose)
        {
            // NB: a C string's value is its address.
            //	(There is no notion of a string's address as that would be an address of an address.)
            switch (purpose)
            {
            case EvaluationIntention.Value:
            case EvaluationIntention.ValueOrNode:
                // might be a case of *(p+i), which can be done as p[i];
                if (Arg is AddressOfTreeNode addrOf1)
                {
                    // 3404
                    // 3401: collapse *&(expr) on RHS and just generate code for the underlying expr
                    context.SetPrettyPrintProlog("<skipped> ");
                    context.PrettyPrint(Arg);
                    return(addrOf1.Arg.GenerateCodeForValueWithPrettyPrint(context, purpose));
                }
                else
                {
                    if (Arg is AdditionTreeNode addition)
                    {
                        context.SetPrettyPrintProlog("<skipped> ");
                        context.PrettyPrint(Arg);
                        addition.Left.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
                        addition.Right.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
                        context.GenerateInstruction("Subscript");
                    }
                    else
                    {
                        Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
                        context.GenerateInstruction("Indirection");
                    }
                }
                break;

            case EvaluationIntention.SideEffectsOnly:
                Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly);
                break;

            case EvaluationIntention.AddressOrNode:
                if (Arg is AddressOfTreeNode addrOf2)
                {
                    // 3401: collapse *&(expr) on LHS and just generate code for the underlying expr
                    context.SetPrettyPrintProlog("<skipped> ");
                    context.PrettyPrint(Arg);
                    return(addrOf2.Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode));
                }
                else
                {
                    // NB: if we did ValueOrNode here, we'd have to handle Node results specially
                    //	as we cannot allow a Node from ValueOrNode unmodified as AddressOrNode
                    Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value);
                }
                break;

            default:
                throw new AssertionFailedException("unexpected evaluation intention" + purpose);
            }

            return(null);
        }
Beispiel #35
0
        internal void AddScopeBody(CodeGenContext context)
        {
            returnTemp = context.CreateLocal("returnTemp", PrimitiveType.Object);

            context.labels = new Labels();
            context.labels.Redo = context.NewLabel();
            context.labels.Return = context.NewLabel();

            // try { ... }
            context.StartBlock(Clause.Try);
            {
                if (BEGIN != null)
                    BEGIN.GenCode(context);

                context.CodeLabel(context.labels.Redo);

                if (body != null)
                {
                    body.GenCode(context);

                    if (context.Reachable())
                        context.stloc(returnTemp);
                }

                context.Goto(context.labels.Return);
            }
            PERWAPI.TryBlock tryBlock = context.EndTryBlock();        

            CatchReturnException(context, tryBlock);

            // ReturnLabel:
            //    return returnTemp;
            context.CodeLabel(context.labels.Return);
            context.newEndPoint(location);
            if (context.Method.GetRetType() != PERWAPI.PrimitiveType.Void)
                context.ldloc(returnTemp);
            context.ret();

            context.ReleaseLocal(returnTemp, true);
        }
Beispiel #36
0
 private void CreateLastClassMethod(ClassDef Class, CodeGenContext context)
 {
     CodeGenContext lastClass = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "lastClass", Runtime.ClassRef);
     lastClass.startMethod(this.location);
     int frame = lastClass.CreateLocal("frame", Runtime.FrameRef);
     lastClass.ldarg(0);
     lastClass.stloc(frame);
     lastClass.LastClass(this, true);
     lastClass.ret();
     lastClass.ReleaseLocal(frame, true);
     lastClass.Close();
 }
Beispiel #37
0
 internal override void GenCode0(CodeGenContext context)
 {
     base.GenCode0(context);
     context.call(Runtime.Program.End);
 }
Beispiel #38
0
 protected override void GenerateCodeForConditionalBranch(CodeGenContext context, BranchTargetLabel label, bool reverse)
 {
     Arg.GenerateCodeForConditionalBranchWithPrettyPrint(context, label, !reverse);
 }
Beispiel #39
0
        public static string ImageStore(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;

            bool isArray   = (texOp.Type & SamplerType.Array) != 0;
            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;

            string texCall = "imageStore";

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + imageName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount;

            int arrayIndexElem = -1;

            if (isArray)
            {
                arrayIndexElem = pCount++;
            }

            void Append(string str)
            {
                texCall += ", " + str;
            }

            if (pCount > 1)
            {
                string[] elems = new string[pCount];

                for (int index = 0; index < pCount; index++)
                {
                    elems[index] = Src(VariableType.S32);
                }

                Append("ivec" + pCount + "(" + string.Join(", ", elems) + ")");
            }
            else
            {
                Append(Src(VariableType.S32));
            }

            string[] cElems = new string[4];

            for (int index = 0; index < 4; index++)
            {
                if (srcIndex < texOp.SourcesCount)
                {
                    cElems[index] = Src(VariableType.F32);
                }
                else
                {
                    cElems[index] = NumberFormatter.FormatFloat(0);
                }
            }

            Append("vec4(" + string.Join(", ", cElems) + ")");

            texCall += ")";

            return(texCall);
        }
Beispiel #40
0
 public static string StoreShared(CodeGenContext context, AstOperation operation)
 {
     return(StoreLocalOrShared(context, operation, DefaultNames.SharedMemoryName));
 }
Beispiel #41
0
 public static string LoadLocal(CodeGenContext context, AstOperation operation)
 {
     return(LoadLocalOrShared(context, operation, DefaultNames.LocalMemoryName));
 }
Beispiel #42
0
        void Test(int testNum, string exprToParse, int terminatingChar = -1)
        {
            ++_testsRun;
            var testName = string.Format("results-test-{0}.txt", testNum);

            using (var tw = File.CreateText(_testDir + testName)) {
                string tc = terminatingChar >= 0 ? ((char)terminatingChar).ToString() : "";
                tw.WriteLine("------ Test: {0} ------\t{1}\t{2}", testNum, tc, exprToParse.Replace("\n", "\r\n"));
                tw.WriteLine();
                var utf8Stream  = CodePointStream.FromString(exprToParse);
                var scanner     = new ScanIt(utf8Stream, testName, tw);
                var symbolTable = new SimpleSymbolTable();
                var parser      = new StatementParser(scanner, symbolTable);
                var result      = parser.TryParse();
                scanner.Message("Parse End");
                tw.WriteLine();
                result.Dump(tw);
                tw.WriteLine();
                if (!result.HasErrors)
                {
                    using (var context = new CodeGenContext(tw)) {
                        try
                        {
                            Dump.CommentFormat();
                            symbolTable.GenerateVariables(context);
                            //result.Result.PrettyPrint ();
                            result.Result.GenerateCodeWithPrettyPrint(context);
                        } catch (Exception ex) {
                            System.Console.WriteLine(ex);
                        }
                    }
                }
                tw.WriteLine();
            }

            using (var tr = new StreamReader(File.OpenRead(_testDir + testName))) {
                var trBytes = tr.ReadToEnd();
                System.Console.WriteLine();
                System.Console.WriteLine();
                System.Console.WriteLine(trBytes);
                StreamReader mr = null;
                try {
                    mr = new StreamReader(File.OpenRead(_masterDir + testName));
                    using ( mr ) {
                        var mrBytes = mr.ReadToEnd();
                        int len     = mrBytes.Length;
                        if (len != trBytes.Length)
                        {
                            System.Console.WriteLine("Test {0} FAILURE: lengths differ!!!!", testNum);
                            return;
                        }
                        for (int i = 0; i < len; i++)
                        {
                            if (trBytes [i] != mrBytes [i])
                            {
                                System.Console.WriteLine("Test {0} FAILURE: bytes differ!!!!", testNum);
                                return;
                            }
                        }
                    }
                } catch (System.Exception) {
                    System.Console.WriteLine("Test {0}: No Master!!!", testNum);
                    return;
                }
            }

            System.Console.WriteLine("Test {0}: SUCCESS!!", testNum);
            ++_testsPassed;
        }
Beispiel #43
0
        public static string TextureSample(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless     = (texOp.Flags & TextureFlags.Bindless) != 0;
            bool isGather       = (texOp.Flags & TextureFlags.Gather) != 0;
            bool hasDerivatives = (texOp.Flags & TextureFlags.Derivatives) != 0;
            bool intCoords      = (texOp.Flags & TextureFlags.IntCoords) != 0;
            bool hasLodBias     = (texOp.Flags & TextureFlags.LodBias) != 0;
            bool hasLodLevel    = (texOp.Flags & TextureFlags.LodLevel) != 0;
            bool hasOffset      = (texOp.Flags & TextureFlags.Offset) != 0;
            bool hasOffsets     = (texOp.Flags & TextureFlags.Offsets) != 0;

            bool isArray       = (texOp.Type & SamplerType.Array) != 0;
            bool isIndexed     = (texOp.Type & SamplerType.Indexed) != 0;
            bool isMultisample = (texOp.Type & SamplerType.Multisample) != 0;
            bool isShadow      = (texOp.Type & SamplerType.Shadow) != 0;

            // This combination is valid, but not available on GLSL.
            // For now, ignore the LOD level and do a normal sample.
            // TODO: How to implement it properly?
            if (hasLodLevel && isArray && isShadow)
            {
                hasLodLevel = false;
            }

            string texCall = intCoords ? "texelFetch" : "texture";

            if (isGather)
            {
                texCall += "Gather";
            }
            else if (hasDerivatives)
            {
                texCall += "Grad";
            }
            else if (hasLodLevel && !intCoords)
            {
                texCall += "Lod";
            }

            if (hasOffset)
            {
                texCall += "Offset";
            }
            else if (hasOffsets)
            {
                texCall += "Offsets";
            }

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string samplerName = OperandManager.GetSamplerName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + samplerName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount;

            int arrayIndexElem = -1;

            if (isArray)
            {
                arrayIndexElem = pCount++;
            }

            // The sampler 1D shadow overload expects a
            // dummy value on the middle of the vector, who knows why...
            bool hasDummy1DShadowElem = texOp.Type == (SamplerType.Texture1D | SamplerType.Shadow);

            if (hasDummy1DShadowElem)
            {
                pCount++;
            }

            if (isShadow && !isGather)
            {
                pCount++;
            }

            // On textureGather*, the comparison value is
            // always specified as an extra argument.
            bool hasExtraCompareArg = isShadow && isGather;

            if (pCount == 5)
            {
                pCount = 4;

                hasExtraCompareArg = true;
            }

            void Append(string str)
            {
                texCall += ", " + str;
            }

            VariableType coordType = intCoords ? VariableType.S32 : VariableType.F32;

            string AssemblePVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        if (arrayIndexElem == index)
                        {
                            elems[index] = Src(VariableType.S32);

                            if (!intCoords)
                            {
                                elems[index] = "float(" + elems[index] + ")";
                            }
                        }
                        else if (index == 1 && hasDummy1DShadowElem)
                        {
                            elems[index] = NumberFormatter.FormatFloat(0);
                        }
                        else
                        {
                            elems[index] = Src(coordType);
                        }
                    }

                    string prefix = intCoords ? "i" : string.Empty;

                    return(prefix + "vec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(coordType));
                }
            }

            string ApplyScaling(string vector)
            {
                if (intCoords)
                {
                    int index = context.FindTextureDescriptorIndex(texOp);

                    if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
                        (texOp.Flags & TextureFlags.Bindless) == 0 &&
                        texOp.Type != SamplerType.Indexed &&
                        pCount == 2)
                    {
                        return("Helper_TexelFetchScale(" + vector + ", " + index + ")");
                    }
                    else
                    {
                        // Resolution scaling cannot be applied to this texture right now.
                        // Flag so that we know to blacklist scaling on related textures when binding them.

                        TextureDescriptor descriptor = context.TextureDescriptors[index];
                        descriptor.Flags |= TextureUsageFlags.ResScaleUnsupported;
                        context.TextureDescriptors[index] = descriptor;
                    }
                }

                return(vector);
            }

            Append(ApplyScaling(AssemblePVector(pCount)));

            string AssembleDerivativesVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        elems[index] = Src(VariableType.F32);
                    }

                    return("vec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(VariableType.F32));
                }
            }

            if (hasExtraCompareArg)
            {
                Append(Src(VariableType.F32));
            }

            if (hasDerivatives)
            {
                Append(AssembleDerivativesVector(coordsCount)); // dPdx
                Append(AssembleDerivativesVector(coordsCount)); // dPdy
            }

            if (isMultisample)
            {
                Append(Src(VariableType.S32));
            }
            else if (hasLodLevel)
            {
                Append(Src(coordType));
            }

            string AssembleOffsetVector(int count)
            {
                if (count > 1)
                {
                    string[] elems = new string[count];

                    for (int index = 0; index < count; index++)
                    {
                        elems[index] = Src(VariableType.S32);
                    }

                    return("ivec" + count + "(" + string.Join(", ", elems) + ")");
                }
                else
                {
                    return(Src(VariableType.S32));
                }
            }

            if (hasOffset)
            {
                Append(AssembleOffsetVector(coordsCount));
            }
            else if (hasOffsets)
            {
                texCall += $", ivec{coordsCount}[4](";

                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ", ";
                texCall += AssembleOffsetVector(coordsCount) + ")";
            }

            if (hasLodBias)
            {
                Append(Src(VariableType.F32));
            }

            // textureGather* optional extra component index,
            // not needed for shadow samplers.
            if (isGather && !isShadow)
            {
                Append(Src(VariableType.S32));
            }

            texCall += ")" + (isGather || !isShadow ? GetMask(texOp.Index) : "");

            return(texCall);
        }
Beispiel #44
0
        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++)
                {
                    if (argIndex != 0)
                    {
                        args += ", ";
                    }

                    VariableType dstType = GetSrcVarType(inst, argIndex);

                    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); break;

                        default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\".");
                        }

                        // We use the first 2 operands above.
                        argIndex++;
                    }
                    else
                    {
                        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;

                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.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}\".");
        }
Beispiel #45
0
 public static string GetSoureExpr(CodeGenContext context, IAstNode node, VariableType dstType)
 {
     return(ReinterpretCast(context, node, OperandManager.GetNodeDestType(context, node), dstType));
 }
Beispiel #46
0
        public static string ImageLoadOrStore(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;

            // TODO: Bindless texture support. For now we just return 0/do nothing.
            if (isBindless)
            {
                switch (texOp.Inst)
                {
                    case Instruction.ImageStore:
                        return "// imageStore(bindless)";
                    case Instruction.ImageLoad:
                        NumberFormatter.TryFormat(0, texOp.Format.GetComponentType(), out string imageConst);
                        return imageConst;
                    default:
                        return NumberFormatter.FormatInt(0);
                }
            }

            bool isArray   = (texOp.Type & SamplerType.Array)   != 0;
            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;

            string texCall;

            if (texOp.Inst == Instruction.ImageAtomic)
            {
                texCall = (texOp.Flags & TextureFlags.AtomicMask) switch {
                    TextureFlags.Add        => "imageAtomicAdd",
                    TextureFlags.Minimum    => "imageAtomicMin",
                    TextureFlags.Maximum    => "imageAtomicMax",
                    TextureFlags.Increment  => "imageAtomicAdd", // TODO: Clamp value.
                    TextureFlags.Decrement  => "imageAtomicAdd", // TODO: Clamp value.
                    TextureFlags.BitwiseAnd => "imageAtomicAnd",
                    TextureFlags.BitwiseOr  => "imageAtomicOr",
                    TextureFlags.BitwiseXor => "imageAtomicXor",
                    TextureFlags.Swap       => "imageAtomicExchange",
                    TextureFlags.CAS        => "imageAtomicCompSwap",
                    _                       => "imageAtomicAdd",
                };
            }
            else
            {
                texCall = texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore";
            }

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return GetSoureExpr(context, texOp.GetSource(srcIndex++), type);
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + imageName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount + (isArray ? 1 : 0);

            void Append(string str)
            {
                texCall += ", " + str;
            }

            string ApplyScaling(string vector)
            {
                if (context.Config.Stage.SupportsRenderScale() &&
                    texOp.Inst == Instruction.ImageLoad &&
                    !isBindless &&
                    !isIndexed)
                {
                    // Image scales start after texture ones.
                    int scaleIndex = context.Config.GetTextureDescriptors().Length + context.Config.FindImageDescriptorIndex(texOp);

                    if (pCount == 3 && isArray)
                    {
                        // The array index is not scaled, just x and y.
                        vector = "ivec3(Helper_TexelFetchScale((" + vector + ").xy, " + scaleIndex + "), (" + vector + ").z)";
                    }
                    else if (pCount == 2 && !isArray)
                    {
                        vector = "Helper_TexelFetchScale(" + vector + ", " + scaleIndex + ")";
                    }
                }

                return vector;
            }

            if (pCount > 1)
            {
                string[] elems = new string[pCount];

                for (int index = 0; index < pCount; index++)
                {
                    elems[index] = Src(VariableType.S32);
                }

                Append(ApplyScaling("ivec" + pCount + "(" + string.Join(", ", elems) + ")"));
            }
            else
            {
                Append(Src(VariableType.S32));
            }

            if (texOp.Inst == Instruction.ImageStore)
            {
                VariableType type = texOp.Format.GetComponentType();

                string[] cElems = new string[4];

                for (int index = 0; index < 4; index++)
                {
                    if (srcIndex < texOp.SourcesCount)
                    {
                        cElems[index] = Src(type);
                    }
                    else
                    {
                        cElems[index] = type switch
                        {
                            VariableType.S32 => NumberFormatter.FormatInt(0),
                            VariableType.U32 => NumberFormatter.FormatUint(0),
                            _                => NumberFormatter.FormatFloat(0)
                        };
                    }
                }

                string prefix = type switch
                {
                    VariableType.S32 => "i",
                    VariableType.U32 => "u",
                    _                => string.Empty
                };

                Append(prefix + "vec4(" + string.Join(", ", cElems) + ")");
            }

            if (texOp.Inst == Instruction.ImageAtomic)
            {
                VariableType type = texOp.Format.GetComponentType();

                if ((texOp.Flags & TextureFlags.AtomicMask) == TextureFlags.CAS)
                {
                    Append(Src(type)); // Compare value.
                }

                string value = (texOp.Flags & TextureFlags.AtomicMask) switch
                {
                    TextureFlags.Increment => NumberFormatter.FormatInt(1, type), // TODO: Clamp value
                    TextureFlags.Decrement => NumberFormatter.FormatInt(-1, type), // TODO: Clamp value
                    _ => Src(type)
                };

                Append(value);

                texCall += ")";

                if (type != VariableType.S32)
                {
                    texCall = "int(" + texCall + ")";
                }
            }
            else
            {
                texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : "");
            }

            return texCall;
        }
Beispiel #47
0
        internal override void GenCode0(CodeGenContext context)
        {
            CodeGenContext Begin = context.CreateMethod(FileClass(), MethAttr.PublicStatic, "Begin" + (seq++), PrimitiveType.Object,
                    new Param(ParamAttr.Default, "recv", PrimitiveType.Object),
                    new Param(ParamAttr.Default, "caller", Runtime.FrameRef));

            Begin.startMethod(this.location);

            AddScopeLocals(Begin);

            AddScopeBody(Begin);

            Begin.ReleaseLocal(0, true);

            Begin.Close();


            // Begin(recv, caller);
            context.ldarg("recv");
            context.ldloc(0);
            context.call(Begin.Method);
            context.pop();
        }
Beispiel #48
0
        public static string ImageLoadOrStore(CodeGenContext context, AstOperation operation)
        {
            AstTextureOperation texOp = (AstTextureOperation)operation;

            bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;

            // TODO: Bindless texture support. For now we just return 0/do nothing.
            if (isBindless)
            {
                return(texOp.Inst == Instruction.ImageLoad ? NumberFormatter.FormatFloat(0) : "// imageStore(bindless)");
            }

            bool isArray   = (texOp.Type & SamplerType.Array) != 0;
            bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;

            string texCall = texOp.Inst == Instruction.ImageLoad ? "imageLoad" : "imageStore";

            int srcIndex = isBindless ? 1 : 0;

            string Src(VariableType type)
            {
                return(GetSoureExpr(context, texOp.GetSource(srcIndex++), type));
            }

            string indexExpr = null;

            if (isIndexed)
            {
                indexExpr = Src(VariableType.S32);
            }

            string imageName = OperandManager.GetImageName(context.Config.Stage, texOp, indexExpr);

            texCall += "(" + imageName;

            int coordsCount = texOp.Type.GetDimensions();

            int pCount = coordsCount + (isArray ? 1 : 0);

            void Append(string str)
            {
                texCall += ", " + str;
            }

            string ApplyScaling(string vector)
            {
                int index = context.FindImageDescriptorIndex(texOp);
                TextureUsageFlags flags = TextureUsageFlags.NeedsScaleValue;

                if ((context.Config.Stage == ShaderStage.Fragment || context.Config.Stage == ShaderStage.Compute) &&
                    texOp.Inst == Instruction.ImageLoad &&
                    !isBindless &&
                    !isIndexed)
                {
                    // Image scales start after texture ones.
                    int scaleIndex = context.TextureDescriptors.Count + index;

                    if (pCount == 3 && isArray)
                    {
                        // The array index is not scaled, just x and y.
                        vector = "ivec3(Helper_TexelFetchScale((" + vector + ").xy, " + scaleIndex + "), (" + vector + ").z)";
                    }
                    else if (pCount == 2 && !isArray)
                    {
                        vector = "Helper_TexelFetchScale(" + vector + ", " + scaleIndex + ")";
                    }
                    else
                    {
                        flags |= TextureUsageFlags.ResScaleUnsupported;
                    }
                }
                else
                {
                    flags |= TextureUsageFlags.ResScaleUnsupported;
                }

                if (!isBindless)
                {
                    context.ImageDescriptors[index] = context.ImageDescriptors[index].SetFlag(flags);
                }

                return(vector);
            }

            if (pCount > 1)
            {
                string[] elems = new string[pCount];

                for (int index = 0; index < pCount; index++)
                {
                    elems[index] = Src(VariableType.S32);
                }

                Append(ApplyScaling("ivec" + pCount + "(" + string.Join(", ", elems) + ")"));
            }
            else
            {
                Append(Src(VariableType.S32));
            }

            if (texOp.Inst == Instruction.ImageStore)
            {
                int texIndex = context.FindImageDescriptorIndex(texOp);
                context.ImageDescriptors[texIndex] = context.ImageDescriptors[texIndex].SetFlag(TextureUsageFlags.ImageStore);

                VariableType type = texOp.Format.GetComponentType();

                string[] cElems = new string[4];

                for (int index = 0; index < 4; index++)
                {
                    if (srcIndex < texOp.SourcesCount)
                    {
                        cElems[index] = Src(type);
                    }
                    else
                    {
                        cElems[index] = type switch
                        {
                            VariableType.S32 => NumberFormatter.FormatInt(0),
                            VariableType.U32 => NumberFormatter.FormatUint(0),
                            _ => NumberFormatter.FormatFloat(0)
                        };
                    }
                }

                string prefix = type switch
                {
                    VariableType.S32 => "i",
                    VariableType.U32 => "u",
                    _ => string.Empty
                };

                Append(prefix + "vec4(" + string.Join(", ", cElems) + ")");
            }

            texCall += ")" + (texOp.Inst == Instruction.ImageLoad ? GetMask(texOp.Index) : "");

            return(texCall);
        }
Beispiel #49
0
        internal void AddScopeLocals(CodeGenContext context)
        {
            // ------------------ Start new Context ----------------------------

            // [InteropMethod("MyClass")]
            // private class ActivationFrame: Ruby.Frame { ... }
            frame_def = context.CreateGlobalClass("_Internal", "Frame" + (N++), Runtime.FrameRef);

            Scope parentClass;
            for (parentClass = this; parentClass != null && !(parentClass is CLASS_OR_MODULE); parentClass = parentClass.parent_scope) ;

            string className = "";
            if (parentClass != null)
                className = ((CLASS_OR_MODULE)parentClass).internal_name;

            ClassDef fileClass = FileClass();
            string src = "";
            if (fileClass != null && fileClass.Name().StartsWith("SourceFile_"))
            {
                src = fileClass.Name().Substring(11);
                frame_def.AddCustomAttribute(Runtime.FrameAttribute.ctor, new Constant[] { new StringConst(src), new StringConst(className) });
            }

            foreach (string local in locals_list)
                CodeGenContext.AddField(frame_def, PERWAPI.FieldAttr.Public, ID.ToDotNetName(local), PrimitiveType.Object);

            // internal ActivationFrame(Frame caller): base(caller) { }
            CodeGenContext frame_ctor = context.CreateConstructor(frame_def, new Param(ParamAttr.Default, "caller", Runtime.FrameRef));
            frame_ctor.ldarg(0);
            frame_ctor.ldarg("caller");
            frame_ctor.call(Runtime.Frame.ctor);
            frame_ctor.ret();
            frame_ctor.Close();

            // internal string file() {
            CodeGenContext file = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "file", PrimitiveType.String);

            file.startMethod(this.location);
            //    return "thisfile.rb"
            file.ldstr(this.location.file);
            file.ret();
            file.Close();

            // internal override string methodName() {
            CodeGenContext methodName = context.CreateMethod(frame_def, PERWAPI.MethAttr.PublicVirtual, "methodName", PrimitiveType.String);
            methodName.startMethod(this.location);
            //    return "CurrentMethodName"
            methodName.ldstr(CurrentMethodName());
            methodName.ret();
            methodName.Close();

            CreateNestingMethod(frame_def, context);
            CreateLastClassMethod(frame_def, context);

            // ------------------ Return to Old Context ----------------------

            // ActivationFrame frame = new ActivationFrame(caller);
            context.ldarg("caller");
            context.newobj(frame_ctor.Method);
            int frame = context.StoreInTemp("frame", FrameClass, location);
            Debug.Assert(frame == 0);

            // frame.block_arg = block;
            context.ldloc(frame);
            LoadBlock0(context);
            context.stfld(Runtime.Frame.block_arg);

            if (this is BLOCK)
            {
                // frame.current_block = this;
                context.ldloc(frame);
                context.ldarg(0);
                context.stfld(Runtime.Frame.current_block);
            }
        }
        private void GenerateHelperBuildMethodFor(IManageEntityMetadata entityMetadataMgr, CodeGenContext context)
        {
            var @class = entityMetadataMgr.EntityName;

            var resourceNamespace = entityMetadataMgr.ResourceNamespace;

            if (!string.IsNullOrEmpty(resourceNamespace) && !context.NamespaceDeclaration.Usings.Contains(resourceNamespace))
                context.NamespaceDeclaration.Usings.Add(resourceNamespace);

            var @interface = entityMetadataMgr.EntityInterface;

            const string methodParameters = "XElement element, INodeSearch nodeSearch";

            var buildMethodName = "Build" + @class;

            context.ClassDeclaration
                   .OpenMethod(new MethodDeclaration("private", @interface, buildMethodName, methodParameters));

            var generateTheseMethodsRightAfterYourFinishThisMethod = new Queue<Action>();

            GenerateMethodBody(entityMetadataMgr, @class, context, @interface, generateTheseMethodsRightAfterYourFinishThisMethod);

            context.ClassDeclaration.EndMethod();

            foreach (var action in generateTheseMethodsRightAfterYourFinishThisMethod)
            {
                action();
            }
        }
Beispiel #51
0
        private void CreateNestingMethod(ClassDef Class, CodeGenContext context)
        {
            List<FieldDef> list = new List<FieldDef>();
            for (Scope parent = this; parent != null; parent = parent.parent_scope)
                if (parent is CLASS_OR_MODULE)
                    list.Add(((CLASS_OR_MODULE)parent).singletonField);

            // internal override Class[] nesting() {
            CodeGenContext nesting = context.CreateMethod(Class, PERWAPI.MethAttr.PublicVirtual, "nesting", new PERWAPI.ZeroBasedArray(Runtime.ClassRef));
            nesting.startMethod(this.location);
            //     Class[] array = new Class[list.Count];
            nesting.ldc_i4(list.Count);
            nesting.newarr(Runtime.ClassRef);
            int array = nesting.CreateLocal("array", new PERWAPI.ZeroBasedArray(Runtime.ClassRef));
            nesting.stloc(array);
            
            for (int i = 0; i < list.Count; i++)
            {
                // array[i] = list[i];
                nesting.ldloc(array);
                nesting.ldc_i4(i);
                nesting.ldsfld(list[i]);
                nesting.stelem_ref();
            }

            //     return array;
            nesting.ldloc(array);
            nesting.ret();
            nesting.ReleaseLocal(array, true);
            nesting.Close();
        }
        private void GenerateMethodBody(IManageEntityMetadata entityMetadataMgr, string @class, CodeGenContext context, string @interface, Queue<Action> delayedMethodGeneratorActions)
        {
            context.ClassDeclaration
                   .WriteLine("if (element == null) return null;")
                   .WriteLine()
                   .WriteLine("{0} entity = new {1}();", @interface, @class)
                   .WriteLine();

            context.ClassDeclaration.WriteLine("// SingleSimpleTypedProperties");
            foreach (var singleSimpleTypedProperty in entityMetadataMgr.GetSingleSimpleTypedProperties())
            {
                if (entityMetadataMgr.IsDescriptorsExtRef())
                {
                    context.ClassDeclaration.WriteLine("var namespaceValue = element.ValueOf(\"Namespace\") ?? \"\";");
                    context.ClassDeclaration.WriteLine("var codeValue = element.ValueOf(\"CodeValue\") ?? \"\";");
                    context.ClassDeclaration.WriteLine("if( string.IsNullOrEmpty(namespaceValue) || namespaceValue.EndsWith(\"/\"))");
                    context.ClassDeclaration.WriteLine("{").PushIndent();
                    context.ClassDeclaration.WriteLine("entity.{0} = namespaceValue + codeValue;", singleSimpleTypedProperty.PropertyName);
                    context.ClassDeclaration.PopIndent().WriteLine("}");
                    context.ClassDeclaration.WriteLine("else");
                    context.ClassDeclaration.WriteLine("{").PushIndent();
                    context.ClassDeclaration.WriteLine("entity.{0} = namespaceValue + \"/\" + codeValue;", singleSimpleTypedProperty.PropertyName);
                    context.ClassDeclaration.PopIndent().WriteLine("}");
                }
                else
                {
                    context.ClassDeclaration
                    .WriteLine("entity.{0} = {1};", singleSimpleTypedProperty.PropertyName, singleSimpleTypedProperty.GetAssignmentExpressionAsStringFor(@"element"));
                }
            }

            context.ClassDeclaration.WriteLine("// SingleEntityTypedProperties");
            foreach (var singleEntityTypedProperty in entityMetadataMgr.GetSingleEntityTypedProperties())
            {
                var mgr = singleEntityTypedProperty.GetMetaDataMgr(_edOrgReferenceDictionaryProvider);

                context.ClassDeclaration
                       .WriteLine(
                           @"entity.{0} = Build{1}(element.ElementOrEmpty(""{2}""), nodeSearch);",
                           singleEntityTypedProperty.PropertyName,
                           mgr.EntityName,
                           singleEntityTypedProperty.ElementName);

                delayedMethodGeneratorActions.Enqueue(() => GenerateHelperBuildMethodFor(mgr, context));
            }

            context.ClassDeclaration.WriteLine("// EntityTypedCollectionProperties");
            foreach (var entityTypedCollectionProperty in entityMetadataMgr.GetEntityTypedCollectionProperties())
            {
                var mgr = entityTypedCollectionProperty.GetMetaDataMgr(_edOrgReferenceDictionaryProvider);
                context.ClassDeclaration
                      .WriteLine(
                          @"entity.{0} = element.ElementsOrEmpty(""{1}"").Select(x => Build{2}(x, nodeSearch)).ToList();",
                          entityTypedCollectionProperty.PropertyName, entityTypedCollectionProperty.ElementName, mgr.EntityName);

                delayedMethodGeneratorActions.Enqueue(() => GenerateHelperBuildMethodFor(mgr, context));
            }

            context.ClassDeclaration.WriteLine("// InlineEntityCollectionProperties");
            foreach (var inlineEntityProperty in entityMetadataMgr.GetInlineEntityCollectionProperties())
            {
                var rightSideExpression = inlineEntityProperty.GetConvertExpression("x");

                var assignmentString = inlineEntityProperty.IsNested ? "NestedElementsOrEmpty" : "ElementsOrEmpty";
                var elementVariable = inlineEntityProperty.IsNested
                    ? string.Format(@"new []{0}""{1}"",""{2}""{3}", "{", inlineEntityProperty.ElementNames[0],
                        inlineEntityProperty.ElementNames[1], "}")
                    : string.Format(@"""{0}""", inlineEntityProperty.ElementName);

                var inlinePropertyName = inlineEntityProperty.InlinePropertyName;
                if (inlineEntityProperty.ClassName == inlineEntityProperty.InlinePropertyName)
                {
                    inlinePropertyName = inlinePropertyName + "X";
                }

                context.ClassDeclaration
                           .WriteLine(@"entity.{0} = element.{1}({2})", inlineEntityProperty.PropertyName, assignmentString, elementVariable)
                           .PushIndent().WriteLine(".Select(x => new {0}", inlineEntityProperty.ClassName)
                           .PushIndent().WriteLine("{")
                           .PushIndent().WriteLine("{0} = {1}", inlinePropertyName, rightSideExpression).PopIndent()
                           .WriteLine("})")
                           .PopIndent().WriteLine(".Cast<{0}>()", inlineEntityProperty.InterfaceName)
                           .WriteLine(".ToList();").PopIndent();
            }

            context.ClassDeclaration.WriteLine("// ForeignKeyProperties");
            foreach (var foreignKeyProperty in entityMetadataMgr.GetForeignKeyProperties())
            {
                var foundElementExpression = foreignKeyProperty.GetConvertExpression("foundElement");
                var possibleNamespaceElementExpression = foreignKeyProperty.GetConvertExpression("possibleNamespaceElement");
                var valueReferenceMap = foreignKeyProperty.SerializedReferenceMap.Replace("\"", @"""""");
                string possibleNamespaceReferenceMap = null;
                if (valueReferenceMap.Contains("CodeValue"))
                {
                    possibleNamespaceReferenceMap = valueReferenceMap.Replace("CodeValue", "Namespace");
                    //foundElementExpression = foreignKeyProperty.GetConvertExpression("possibleNamespaceElement") + " + " + foundElementExpression;
                }

                context.ClassDeclaration
                    .WriteLine("{")
                    .PushIndent()
                    .WriteLine(@"var foundElement = nodeSearch.FindForeignKeyElement(element, @""{0}"");", valueReferenceMap);

                if (possibleNamespaceReferenceMap != null)
                    context.ClassDeclaration
                        .WriteLine(
                            @"var possibleNamespaceElement = nodeSearch.FindForeignKeyElement(element, @""{0}"");",
                            possibleNamespaceReferenceMap)
                        .WriteLine(
                            @"entity.{0} = string.IsNullOrEmpty({1}) || {1}.EndsWith(""/"")?{1}+{2}:{1}+""/""+{2};",
                            foreignKeyProperty.PropertyName, possibleNamespaceElementExpression, foundElementExpression);
                else
                    context.ClassDeclaration
                        .WriteLine("entity.{0} = {1};", foreignKeyProperty.PropertyName, foundElementExpression);

                context.ClassDeclaration
                    .PopIndent()
                    .WriteLine("}");
            }

            context.ClassDeclaration.WriteLine("// MultiElementEntityCollectionProperties");
            foreach (var property in entityMetadataMgr.GetMultiElementEntityCollectionProperties())
            {
                context.ClassDeclaration
                    .WriteLine(
                        @"entity.{0} = element.AllElementsOrEmpty(new []{1}{2}{3}).Select(x => Build{4}(x, nodeSearch)).ToList();",
                        property.PropertyName, "{", property.ParticipatingElementsAsCommaDelimentedStringOfStrings, "}", property.EntityName);
                var closureSafeProperty = property;
                delayedMethodGeneratorActions.Enqueue(() => GenerateHelperBuildMethodFor(closureSafeProperty.GetEntityMetadataManager(), context));
            }

            context.ClassDeclaration
                   .WriteLine()
                   .WriteLine("return entity;");
        }
Beispiel #53
0
        internal void CatchReturnException(CodeGenContext context, PERWAPI.TryBlock tryBlock)
        {
            // catch (Ruby.ReturnException exception) { ... }
            context.StartBlock(Clause.Catch);
            {
                PERWAPI.CILLabel falseLabel = context.NewLabel();

                int exception = context.StoreInTemp("exception", Runtime.ReturnExceptionRef, location);

                // if (exception.scope == thisframe)
                context.ldloc(exception);
                context.ldfld(Runtime.ReturnException.scope);
                context.ldloc(0);
                context.bne(falseLabel);

                //     returnTemp = exception.return_value;
                context.ldloc(exception);
                context.ldfld(Runtime.ReturnException.return_value);
                context.stloc(returnTemp);
                context.Goto(context.labels.Return);

                // falseLabel:
                context.CodeLabel(falseLabel);
                // throw exception
                context.rethrow();

                context.ReleaseLocal(exception, true);
            }
            context.EndCatchBlock(Runtime.ReturnExceptionRef, tryBlock);
        }
Beispiel #54
0
        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}\".");
        }