зеркало из https://github.com/microsoft/rudder.git
Add contant progration for string within the Range Analysis. Modify the interproc analysis to progagate ranges (or string) to callees.
This commit is contained in:
Родитель
781847b959
Коммит
903ccf79ba
|
@ -187,7 +187,7 @@ namespace ScopeProgramAnalysis
|
|||
nodeExit.Successors.Add(nodeEntry);
|
||||
nodeEntry.Predecessors.Add(nodeExit);
|
||||
|
||||
var rangeAnalysis = new RangeAnalysis(cfg);
|
||||
var rangeAnalysis = new RangeAnalysis(cfg, this.processToAnalyze.MoveNextMethod);
|
||||
var ranges = rangeAnalysis.Analyze();
|
||||
var exitRange = ranges[cfg.Exit.Id];
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ namespace ScopeProgramAnalysis
|
|||
|
||||
public IEnumerable<ProtectedRowNode> ProtectedNodes { get; set; }
|
||||
public Instruction Instruction { get; internal set; }
|
||||
}
|
||||
public VariableRangeDomain VariableRanges { get; internal set; }
|
||||
}
|
||||
public struct InterProceduralReturnInfo
|
||||
{
|
||||
public InterProceduralReturnInfo(DependencyPTGDomain state)
|
||||
|
@ -175,11 +176,15 @@ namespace ScopeProgramAnalysis
|
|||
IDictionary<IVariable, IExpression> equalities = new Dictionary<IVariable, IExpression>();
|
||||
calleeCFG.PropagateExpressions(equalities);
|
||||
|
||||
var rangesAnalysis = new RangeAnalysis(calleeCFG);
|
||||
rangesAnalysis.Analyze();
|
||||
// 2) Bind Parameters of the dependency analysis and run
|
||||
var calleeDomain = BindCallerCallee(callInfo);
|
||||
calleeDomain.PTG = calleePTG;
|
||||
// 2) Bind Parameters of the dependency analysis
|
||||
VariableRangeDomain boundVariablesRanges;
|
||||
var calleeDomain = BindCallerCallee(callInfo, out boundVariablesRanges);
|
||||
var rangesAnalysis = new RangeAnalysis(calleeCFG, callInfo.Callee, boundVariablesRanges);
|
||||
|
||||
// 4) Now we perform the analyses
|
||||
rangesAnalysis.Analyze();
|
||||
|
||||
calleeDomain.PTG = calleePTG;
|
||||
var dependencyAnalysis = new IteratorDependencyAnalysis(processToAnalyze, callInfo.Callee, calleeCFG, calleePTA, callInfo.ProtectedNodes, equalities, this, rangesAnalysis, calleeDomain, callInfo.ScopeData);
|
||||
|
||||
// If we already did the dataflow analysis for this method we recover the dataflow state
|
||||
|
@ -212,7 +217,9 @@ namespace ScopeProgramAnalysis
|
|||
// Should I need the PTG of caller and callee?
|
||||
//var exitCalleePTG = calleePTA.Result[calleeCFG.Exit.Id].Output;
|
||||
var exitCalleePTG = dependencyAnalysis.Result[calleeCFG.Exit.Id].Output.PTG;
|
||||
var exitResult = BindCalleeCaller(callInfo, calleeCFG, dependencyAnalysis);
|
||||
|
||||
|
||||
var exitResult = BindCalleeCaller(callInfo, calleeCFG, dependencyAnalysis, rangesAnalysis);
|
||||
|
||||
// Recover the frame of the original Ptg and bind ptg results
|
||||
//PointsToGraph bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, calleePTA);
|
||||
|
@ -227,33 +234,40 @@ namespace ScopeProgramAnalysis
|
|||
//return new InterProceduralReturnInfo(exitResult, bindPtg);
|
||||
}
|
||||
|
||||
private DependencyPTGDomain BindCallerCallee(InterProceduralCallInfo callInfo)
|
||||
private DependencyPTGDomain BindCallerCallee(InterProceduralCallInfo callInfo, out VariableRangeDomain initializedRanges)
|
||||
{
|
||||
initializedRanges = new VariableRangeDomain();
|
||||
|
||||
var calleeDepDomain = new DependencyPTGDomain();
|
||||
calleeDepDomain.Dependencies.IsTop = callInfo.CallerState.Dependencies.IsTop;
|
||||
// Bind parameters with arguments
|
||||
var body = MethodBodyProvider.Instance.GetBody(callInfo.Callee);
|
||||
for (int i = 0; i < body.Parameters.Count(); i++)
|
||||
{
|
||||
var arg = callInfo.CallArguments[i];
|
||||
for (int i = 0; i < body.Parameters.Count(); i++)
|
||||
{
|
||||
var arg = callInfo.CallArguments[i];
|
||||
|
||||
var param = body.Parameters[i];
|
||||
var param = body.Parameters[i];
|
||||
|
||||
arg = AdaptIsReference(arg);
|
||||
param = AdaptIsReference(param);
|
||||
arg = AdaptIsReference(arg);
|
||||
param = AdaptIsReference(param);
|
||||
|
||||
if (callInfo.CallerState.HasTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AssignTraceables(param, callInfo.CallerState.GetTraceables(arg));
|
||||
}
|
||||
if (callInfo.CallerState.HasOutputTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AddOutputTraceables(param, callInfo.CallerState.GetOutputTraceables(arg));
|
||||
}
|
||||
if (callInfo.CallerState.HasOutputControlTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AddOutputControlTraceables(param, callInfo.CallerState.GetOutputControlTraceables(arg));
|
||||
}
|
||||
if (callInfo.CallerState.HasTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AssignTraceables(param, callInfo.CallerState.GetTraceables(arg));
|
||||
}
|
||||
if (callInfo.CallerState.HasOutputTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AddOutputTraceables(param, callInfo.CallerState.GetOutputTraceables(arg));
|
||||
}
|
||||
if (callInfo.CallerState.HasOutputControlTraceables(arg))
|
||||
{
|
||||
calleeDepDomain.AddOutputControlTraceables(param, callInfo.CallerState.GetOutputControlTraceables(arg));
|
||||
}
|
||||
|
||||
// DIEGODIEGO: Do I need this?
|
||||
callInfo.ScopeData.PropagateCopy(arg, param);
|
||||
initializedRanges.AssignValue(param, callInfo.VariableRanges.GetValue(param));
|
||||
|
||||
}
|
||||
calleeDepDomain.Dependencies.A1_Escaping = callInfo.CallerState.Dependencies.A1_Escaping;
|
||||
|
||||
|
@ -280,10 +294,14 @@ namespace ScopeProgramAnalysis
|
|||
return arg;
|
||||
}
|
||||
|
||||
private DependencyPTGDomain BindCalleeCaller(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG, IteratorDependencyAnalysis depAnalysis)
|
||||
private DependencyPTGDomain BindCalleeCaller(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG,
|
||||
IteratorDependencyAnalysis depAnalysis,RangeAnalysis rangeAnalysis)
|
||||
{
|
||||
|
||||
var exitResult = depAnalysis.Result[calleeCFG.Exit.Id].Output;
|
||||
var body = MethodBodyProvider.Instance.GetBody(callInfo.Callee);
|
||||
var exitRange = rangeAnalysis.Result[calleeCFG.Exit.Id].Output;
|
||||
|
||||
var body = MethodBodyProvider.Instance.GetBody(callInfo.Callee);
|
||||
|
||||
for (int i = 0; i < body.Parameters.Count(); i++)
|
||||
{
|
||||
|
@ -349,6 +367,9 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
callInfo.CallerState.AddOutputControlTraceables(callInfo.CallLHS, exitResult.GetOutputControlTraceables(depAnalysis.ReturnVariable));
|
||||
}
|
||||
|
||||
// DIEGODIEGO: Need to propagate range of return value
|
||||
callInfo.VariableRanges.AssignValue(callInfo.CallLHS, exitRange.GetValue(rangeAnalysis.ReturnVariable));
|
||||
}
|
||||
|
||||
return callInfo.CallerState;
|
||||
|
|
|
@ -1145,7 +1145,9 @@ namespace Backend.Analyses
|
|||
CallerPTG = currentPTG,
|
||||
ScopeData = this.scopeData,
|
||||
Instruction = instruction,
|
||||
ProtectedNodes = this.iteratorDependencyAnalysis.protectedNodes
|
||||
VariableRanges = variableRanges,
|
||||
ProtectedNodes = this.iteratorDependencyAnalysis.protectedNodes
|
||||
|
||||
};
|
||||
|
||||
var interProcResult = this.iteratorDependencyAnalysis.interproceduralManager.DoInterProcWithCallee(interProcInfo);
|
||||
|
@ -2072,6 +2074,7 @@ namespace Backend.Analyses
|
|||
CallerPTG = currentPTG,
|
||||
ScopeData = this.scopeData,
|
||||
Instruction = methodCall,
|
||||
VariableRanges = this.variableRanges,
|
||||
ProtectedNodes = this.iteratorDependencyAnalysis.protectedNodes
|
||||
};
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ using Backend.Visitors;
|
|||
using Backend.Analyses;
|
||||
using Microsoft.Cci;
|
||||
using Backend.Model;
|
||||
using ScopeProgramAnalysis.Framework;
|
||||
|
||||
namespace ScopeProgramAnalysis
|
||||
{
|
||||
|
@ -16,15 +17,21 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
public static readonly RangeDomain TOP = new RangeDomain(int.MinValue, int.MinValue);
|
||||
public static readonly RangeDomain BOTTOM = new RangeDomain(0, -1);
|
||||
public static readonly string STRINGTOP = "_STRING_TOP_";
|
||||
public static readonly string STRINGBOTTOM = null;
|
||||
|
||||
public int LowerBound { get; set; }
|
||||
public int UpperBound { get; set; }
|
||||
public int LowerBound { get; private set; }
|
||||
public int UpperBound { get; private set; }
|
||||
|
||||
public bool IsTop
|
||||
public string Literal{ get; private set; }
|
||||
|
||||
private bool isString;
|
||||
|
||||
public bool IsTop
|
||||
{
|
||||
get
|
||||
{
|
||||
return LowerBound==int.MinValue && UpperBound==int.MaxValue;
|
||||
return (!isString && LowerBound==int.MinValue && UpperBound==int.MaxValue) || (isString && Literal==STRINGTOP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +39,7 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
get
|
||||
{
|
||||
return LowerBound == 0 && UpperBound == -1;
|
||||
return (!isString && LowerBound == 0 && UpperBound == -1) || (isString && Literal == STRINGBOTTOM);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,15 +47,32 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
this.LowerBound = singleton;
|
||||
this.UpperBound = singleton;
|
||||
this.Literal = null;
|
||||
this.isString = false;
|
||||
}
|
||||
|
||||
public RangeDomain(int start, int end)
|
||||
{
|
||||
this.LowerBound = start;
|
||||
this.UpperBound = end;
|
||||
}
|
||||
public RangeDomain Join(RangeDomain oth)
|
||||
this.Literal = null;
|
||||
this.isString = false;
|
||||
}
|
||||
|
||||
public RangeDomain(string literal)
|
||||
{
|
||||
this.LowerBound = 0;
|
||||
this.UpperBound = -1;
|
||||
this.Literal = literal;
|
||||
this.isString = true;
|
||||
}
|
||||
public RangeDomain Join(RangeDomain oth)
|
||||
{
|
||||
if (isString)
|
||||
{
|
||||
return oth.Literal != this.Literal ? new RangeDomain(STRINGTOP) : this;
|
||||
}
|
||||
|
||||
var prevInterval = this;
|
||||
if (prevInterval.IsBottom)
|
||||
return oth;
|
||||
|
@ -64,8 +88,12 @@ namespace ScopeProgramAnalysis
|
|||
|
||||
public RangeDomain Widening(RangeDomain prev)
|
||||
{
|
||||
// Trivial cases
|
||||
if (this.IsBottom)
|
||||
if (isString)
|
||||
{
|
||||
return prev.Literal != this.Literal ? new RangeDomain(STRINGTOP) : this;
|
||||
}
|
||||
// Trivial cases
|
||||
if (this.IsBottom)
|
||||
return prev;
|
||||
if (this.IsTop)
|
||||
return this;
|
||||
|
@ -83,33 +111,44 @@ namespace ScopeProgramAnalysis
|
|||
|
||||
public RangeDomain Clone()
|
||||
{
|
||||
if (isString) return new RangeDomain(this.Literal);
|
||||
|
||||
return new RangeDomain(this.LowerBound, this.UpperBound);
|
||||
}
|
||||
|
||||
public bool LessEqual(RangeDomain oth)
|
||||
{
|
||||
return this.LowerBound>=oth.LowerBound && this.UpperBound<=oth.UpperBound;
|
||||
if (isString) return this.Literal==oth.Literal;
|
||||
|
||||
return this.LowerBound>=oth.LowerBound && this.UpperBound<=oth.UpperBound;
|
||||
}
|
||||
|
||||
public bool Equals(RangeDomain oth)
|
||||
{
|
||||
return this.LowerBound==oth.LowerBound && this.UpperBound==oth.UpperBound;
|
||||
if (isString) return this.Literal == oth.Literal;
|
||||
|
||||
return this.LowerBound==oth.LowerBound && this.UpperBound==oth.UpperBound;
|
||||
}
|
||||
|
||||
public RangeDomain Sum(RangeDomain rangeDomain)
|
||||
{
|
||||
if (IsTop) return this;
|
||||
if (isString) return this;
|
||||
|
||||
if (IsTop) return this;
|
||||
return new RangeDomain(this.LowerBound+rangeDomain.LowerBound,this.UpperBound+rangeDomain.UpperBound);
|
||||
}
|
||||
public RangeDomain Sub(RangeDomain rangeDomain)
|
||||
{
|
||||
if (IsTop) return this;
|
||||
if (isString) return this;
|
||||
|
||||
if (IsTop) return this;
|
||||
return new RangeDomain(this.LowerBound - rangeDomain.LowerBound, this.UpperBound - rangeDomain.UpperBound);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (IsTop) return "_TOP_";
|
||||
if (isString) return this.Literal!=null?$"'{this.Literal}":"_STRING_BOTTOM_";
|
||||
if (IsTop) return "_TOP_";
|
||||
if(IsBottom)
|
||||
return "_BOTTOM_";
|
||||
var result = String.Format(CultureInfo.InvariantCulture, "[{0}..{1}]", LowerBound, UpperBound);
|
||||
|
@ -208,15 +247,22 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
|
||||
private object originalValue = null;
|
||||
private VariableRangeDomain initRange = null;
|
||||
public IVariable ReturnVariable { get; private set; }
|
||||
|
||||
public DataFlowAnalysisResult<VariableRangeDomain>[] Result { get; private set; }
|
||||
public DataFlowAnalysisResult<VariableRangeDomain>[] Result { get; private set; }
|
||||
|
||||
public RangeAnalysis(ControlFlowGraph cfg): base(cfg)
|
||||
public RangeAnalysis(ControlFlowGraph cfg, IMethodDefinition method): base(cfg)
|
||||
{
|
||||
this.ReturnVariable = new LocalVariable(method.Name + "_" + "$RV") { Type = method.Type.PlatformType.SystemObject };
|
||||
}
|
||||
public RangeAnalysis(ControlFlowGraph cfg, IMethodDefinition method, VariableRangeDomain initRange) : this(cfg, method)
|
||||
{
|
||||
this.initRange = initRange;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override DataFlowAnalysisResult<VariableRangeDomain>[] Analyze()
|
||||
public override DataFlowAnalysisResult<VariableRangeDomain>[] Analyze()
|
||||
{
|
||||
Result = base.Analyze();
|
||||
return Result;
|
||||
|
@ -236,10 +282,14 @@ namespace ScopeProgramAnalysis
|
|||
|
||||
protected override VariableRangeDomain InitialValue(CFGNode node)
|
||||
{
|
||||
return new VariableRangeDomain();
|
||||
if (this.cfg.Entry.Id == node.Id && this.initRange != null)
|
||||
{
|
||||
return this.initRange;
|
||||
}
|
||||
return new VariableRangeDomain();
|
||||
}
|
||||
|
||||
protected override VariableRangeDomain Join(VariableRangeDomain left, VariableRangeDomain right)
|
||||
protected override VariableRangeDomain Join(VariableRangeDomain left, VariableRangeDomain right)
|
||||
{
|
||||
return left.Join(right);
|
||||
}
|
||||
|
@ -257,27 +307,45 @@ namespace ScopeProgramAnalysis
|
|||
public VariableRangeDomain State { get; internal set; }
|
||||
|
||||
public override void Visit(LoadInstruction instruction)
|
||||
{
|
||||
if(instruction.Operand is Constant)
|
||||
{
|
||||
var value = ExtractConstant(instruction.Operand as Constant);
|
||||
this.State.SetValue(instruction.Result, value);
|
||||
}
|
||||
if(instruction.Operand is IVariable)
|
||||
{
|
||||
this.State.SetValue(instruction.Result, this.State.GetValue(instruction.Operand as IVariable));
|
||||
}
|
||||
}
|
||||
{
|
||||
var source = instruction.Operand;
|
||||
var dest = instruction.Result;
|
||||
Copy(source, dest);
|
||||
}
|
||||
|
||||
private void Copy(IValue source, IVariable dest)
|
||||
{
|
||||
if (source is Constant)
|
||||
{
|
||||
var value = ExtractConstant(source as Constant);
|
||||
this.State.SetValue(dest, value);
|
||||
}
|
||||
if (source is IVariable)
|
||||
{
|
||||
this.State.SetValue(dest, this.State.GetValue(source as IVariable));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Visit(ReturnInstruction instruction)
|
||||
{
|
||||
Copy(instruction.Operand, this.rangeAnalysis.ReturnVariable);
|
||||
}
|
||||
|
||||
private RangeDomain ExtractConstant(Constant K)
|
||||
{
|
||||
int value = -1;
|
||||
|
||||
if (TypeHelper.IsPrimitiveInteger(K.Type) && !(K.Value is Int64 || K.Value is UInt64))
|
||||
{
|
||||
value = (int)K.Value;
|
||||
return new RangeDomain(value, value);
|
||||
}
|
||||
if (K.Type.IsString())
|
||||
{
|
||||
var literal = (string)K.Value;
|
||||
return new RangeDomain(literal);
|
||||
}
|
||||
|
||||
private RangeDomain ExtractConstant(Constant K)
|
||||
{
|
||||
int value = -1;
|
||||
|
||||
if (TypeHelper.IsPrimitiveInteger(K.Type) && !(K.Value is Int64 || K.Value is UInt64))
|
||||
{
|
||||
value = (int)K.Value;
|
||||
return new RangeDomain(value, value);
|
||||
}
|
||||
return RangeDomain.BOTTOM;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче