Пример #1
0
        private static void CreateTableDescriptor()
        {
            var result = new Dictionary <Type, TableDescriptor>();

            // 构建表描述符。
            TableKinds.ForEach(p =>
            {
                var textName = Settings.Get <string>(p.Value);

                HelperTools.SplitTableNames(textName).ForEach(name =>
                {
                    var entityType = ConvertToEntityType(name);
                    var tableName  = ConvertToTableName(entityType);

                    if (result.ContainsKey(entityType))
                    {
                        throw new ArgumentException(string.Format("{0} 重复配置。", name));
                    }

                    result[entityType] = new TableDescriptor {
                        EntityType = entityType, Name = tableName, TableKind = p.Key
                    };
                });
            });

            TableDescriptors = new ReadOnlyDictionary <Type, TableDescriptor>(result);
        }
Пример #2
0
        public static ControlFlowGraph DoCreateCarcass(IMethodBody cil, out ReadOnlyDictionary <ControlFlowBlock, ReadOnlyCollection <IILOp> > blocks2parts)
        {
            // create the control flow graph
            var cfg = new ControlFlowGraph();

            // partition the code into blocks with continuous control flow
            // todo. support switches and protected regions
            var    targets          = new HashSet <IILOp>(cil.OfType <Branch>().Select(br => br.Target));
            var    l_partitions     = new List <ReadOnlyCollection <IILOp> >();
            var    l_partition      = new List <IILOp>();
            Action qualifyPartition = () => { if (l_partition.IsNotEmpty())
                                              {
                                                  l_partitions.Add(l_partition.ToReadOnly()); l_partition = new List <IILOp>();
                                              }
            };

            foreach (var op in cil)
            {
                if (op is Branch || op is Ret)
                {
                    qualifyPartition();
                }
                else
                {
                    if (targets.Contains(op))
                    {
                        qualifyPartition();
                    }
                    l_partition.Add(op);
                    if (op is Throw)
                    {
                        qualifyPartition();
                    }
                }
            }
            qualifyPartition();
            var partitions = l_partitions.ToReadOnly();

            // create blocks and map those to ops and partitions
            blocks2parts = partitions.ToDictionary(p => new ControlFlowBlock(), p => p).ToReadOnly();
            blocks2parts.ForEach(kvp => cfg.AddVertex(kvp.Key));
            var op2blocks = new Dictionary <IILOp, ControlFlowBlock>();

            blocks2parts.ForEach(kvp => kvp.Value.ForEach(op => op2blocks.Add(op, kvp.Key)));
            cil.ForEach(op => { if (!op2blocks.ContainsKey(op))
                                {
                                    op2blocks.Add(op, null);
                                }
                        });

            // prepare to link the blocks
            Action <IILOp, IILOp, CilPredicateType?> link = (op1, op2, cil_pred) =>
            {
                var source   = op1 == null ? cfg.Start : op2blocks[op1];
                var target   = op2 == null ? cfg.Finish : op2blocks[op2];
                var hir_pred = cil_pred == null ? (HirPredicateType?)null :
                               (HirPredicateType)Enum.Parse(typeof(HirPredicateType), cil_pred.Value.ToString());
                cfg.AddEdge(new ControlFlowEdge(source, target, hir_pred));
            };

            // link the blocks (down from 300+ LOC to this simple loop =))
            if (cil.IsEmpty())
            {
                link(null, null, null);
            }
            foreach (var op in cil)
            {
                // todo. support switches here
                if (op is Switch)
                {
                    throw AssertionHelper.Fail();
                }

                // todo. support general case of control flow
                // n0te. throw needs something on stack, so br > throw is impossible
                Func <IILOp, bool> isJmp = op1 => op1 is Ret || op1 is Branch;
                if (isJmp(op) && isJmp(op.Prev))
                {
                    continue;
                }

                if (isJmp(op))
                {
                    Func <IILOp, CilPredicateType?> pred = op1 => op1 is Ret ? null : op1 is Branch ? ((Branch)op1).PredicateType : ((Func <CilPredicateType?>)(() => { throw AssertionHelper.Fail(); }))();
                    Func <IILOp, bool>  uncond           = op1 => isJmp(op1) && pred(op1) == null;
                    Func <IILOp, bool>  cond             = op1 => isJmp(op1) && pred(op1) != null;
                    Func <IILOp, IILOp> target           = null; target = op1 =>
                                                                          op1 is Ret ? null : op1 is Branch?target(((Branch)op1).Target) : op1;

                    (target(op) is Branch).AssertFalse();
                    if (target(op) is Ret)
                    {
                        link(op.Prev, null, pred(op));
                    }
                    else
                    {
                        link(op.Prev, target(op), pred(op));
                    }

                    isJmp(op.Next).AssertImplies(uncond(op.Next));
                    if (cond(op))
                    {
                        link(op.Prev, target(op.Next), pred(op).Negate());
                    }
                }
                else if (op is Throw)
                {
                    // do nothing - throw doesn't create links
                }
                else
                {
                    if (op.Prev == null)
                    {
                        link(null, op, null);
                    }
                    if (isJmp(op.Next))
                    {
                        continue;
                    }

                    var blk      = op2blocks.GetOrDefault(op);
                    var blk_next = op2blocks.GetOrDefault(op.Next);
                    if (blk != blk_next)
                    {
                        link(op, op.Next, null);
                    }
                }
            }

            // yield control to the next step of the pipeline
            return(cfg);
        }
Пример #3
0
        public static ControlFlowGraph DoCreateCarcass(IMethodBody cil, out ReadOnlyDictionary<ControlFlowBlock, ReadOnlyCollection<IILOp>> blocks2parts)
        {
            // create the control flow graph
            var cfg = new ControlFlowGraph();

            // partition the code into blocks with continuous control flow
            // todo. support switches and protected regions
            var targets = new HashSet<IILOp>(cil.OfType<Branch>().Select(br => br.Target));
            var l_partitions = new List<ReadOnlyCollection<IILOp>>();
            var l_partition = new List<IILOp>();
            Action qualifyPartition = () => { if (l_partition.IsNotEmpty()) { l_partitions.Add(l_partition.ToReadOnly()); l_partition = new List<IILOp>(); } };
            foreach (var op in cil)
            {
                if (op is Branch || op is Ret) qualifyPartition();
                else 
                {
                    if (targets.Contains(op)) qualifyPartition();
                    l_partition.Add(op);
                    if (op is Throw) qualifyPartition();
                }
            }
            qualifyPartition();
            var partitions = l_partitions.ToReadOnly();

            // create blocks and map those to ops and partitions
            blocks2parts = partitions.ToDictionary(p => new ControlFlowBlock(), p => p).ToReadOnly();
            blocks2parts.ForEach(kvp => cfg.AddVertex(kvp.Key));
            var op2blocks = new Dictionary<IILOp, ControlFlowBlock>();
            blocks2parts.ForEach(kvp => kvp.Value.ForEach(op => op2blocks.Add(op, kvp.Key)));
            cil.ForEach(op => { if (!op2blocks.ContainsKey(op)) op2blocks.Add(op, null); });

            // prepare to link the blocks
            Action<IILOp, IILOp, CilPredicateType?> link = (op1, op2, cil_pred) =>
            {
                var source = op1 == null ? cfg.Start : op2blocks[op1];
                var target = op2 == null ? cfg.Finish : op2blocks[op2];
                var hir_pred = cil_pred == null ? (HirPredicateType?)null :
                    (HirPredicateType)Enum.Parse(typeof(HirPredicateType), cil_pred.Value.ToString());
                cfg.AddEdge(new ControlFlowEdge(source, target, hir_pred));
            };

            // link the blocks (down from 300+ LOC to this simple loop =))
            if (cil.IsEmpty()) link(null, null, null);
            foreach (var op in cil)
            {
                // todo. support switches here
                if (op is Switch) throw AssertionHelper.Fail();

                // todo. support general case of control flow
                // n0te. throw needs something on stack, so br > throw is impossible
                Func<IILOp, bool> isJmp = op1 => op1 is Ret || op1 is Branch;
                if (isJmp(op) && isJmp(op.Prev)) continue;

                if (isJmp(op))
                {
                    Func<IILOp, CilPredicateType?> pred = op1 => op1 is Ret ? null : op1 is Branch ? ((Branch)op1).PredicateType : ((Func<CilPredicateType?>)(() => { throw AssertionHelper.Fail(); }))();
                    Func<IILOp, bool> uncond = op1 => isJmp(op1) && pred(op1) == null;
                    Func<IILOp, bool> cond = op1 => isJmp(op1) && pred(op1) != null;
                    Func<IILOp, IILOp> target = null; target = op1 => 
                        op1 is Ret ? null : op1 is Branch ? target(((Branch)op1).Target) : op1;

                    (target(op) is Branch).AssertFalse();
                    if (target(op) is Ret) link(op.Prev, null, pred(op));
                    else link(op.Prev, target(op), pred(op));

                    isJmp(op.Next).AssertImplies(uncond(op.Next));
                    if (cond(op)) link(op.Prev, target(op.Next), pred(op).Negate());
                }
                else if (op is Throw)
                {
                    // do nothing - throw doesn't create links
                }
                else
                {
                    if (op.Prev == null) link(null, op, null);
                    if (isJmp(op.Next)) continue;

                    var blk = op2blocks.GetOrDefault(op);
                    var blk_next = op2blocks.GetOrDefault(op.Next);
                    if (blk != blk_next) link(op, op.Next, null);
                }
            }

            // yield control to the next step of the pipeline
            return cfg;
        }