/// <summary> /// Marks variable as being referenced. /// </summary> public void MarkLocalByRef(VariableHandle handle) { handle.ThrowIfInvalid(); this.FlowContext.SetReference(handle); this.SetVarInitialized(handle); _flowCtx.SetUsed(handle); }
public void SetVarInitialized(VariableHandle handle) { int varindex = handle.Slot; if (varindex >= 0 && varindex < FlowContext.BitsCount) { _initializedMask |= 1u << varindex; } }
public void SetVarUninitialized(VariableHandle handle) { var varindex = handle.Slot; if (varindex >= 0 && varindex < FlowContext.BitsCount) { _initializedMask &= ~(1u << varindex); } }
void SetConstrain(VariableHandle variable, NoteKind kind, bool set) { if (set) { AddConstrain(variable, kind); } else { RemoveConstrain(variable, kind); } }
void AddConstrain(VariableHandle variable, NoteKind kind) { if (variable.IsValid) { var notes = _notes; if (notes == null) { _notes = notes = new HashSet <NoteData>(); } notes.Add(new NoteData(variable, kind)); } }
void RemoveConstrain(VariableHandle variable, NoteKind kind) { if (variable.IsValid) { var notes = _notes; if (notes != null) { notes.Remove(new NoteData(variable, kind)); if (notes.Count == 0) { _notes = null; } } } }
/// <summary> /// Sets variable type in this state. /// </summary> /// <param name="handle">Variable handle.</param> /// <param name="tmask">Variable type. If <c>uninitialized</c>, the variable is set as not initialized in this state.</param> public void SetLocalType(VariableHandle handle, TypeRefMask tmask) { handle.ThrowIfInvalid(); if (handle >= _varsType.Length) { Array.Resize(ref _varsType, handle + 1); } _varsType[handle] = tmask; this.FlowContext.AddVarType(handle, tmask); // TODO: collect merged type information at the end of analysis // update the _initializedMask SetVarInitialized(handle); }
//#region Variable Kind //Dictionary<VariableName, VariableKind> _varKindMap; /// <summary> /// Declares variable with a specific kind (static or global). /// </summary> public void SetVarKind(VariableHandle handle, VariableKind kind) { //if (_varKindMap == null) //{ // _varKindMap = new Dictionary<VariableName, VariableKind>(); //} //else //{ // VariableKind old; // if (_varKindMap.TryGetValue(varname, out old)) // { // if (old != kind) throw new ArgumentException("redeclaration with a different kind not supported", nameof(kind)); // } //} //_varKindMap[varname] = kind; }
/// <summary> /// Gets kind of variable declaration in this state. /// </summary> public VariableKind GetVarKind(VariableHandle handle) { handle.ThrowIfInvalid(); //// explicit variable declaration //if (_varKindMap != null) //{ // VariableKind kind = VariableKind.LocalVariable; // if (_varKindMap.TryGetValue(varname, out kind)) // { // return kind; // } //} // already declared on locals label return(Routine.LocalsTable.GetVariableKind(handle.Name)); }
/// <summary> /// Sets or removes LTInt64 flag for a variable. /// </summary> public void LTInt64Max(VariableHandle handle, bool lt) { if (lt) { if (_lessThanLongMax == null) { _lessThanLongMax = new HashSet <VariableHandle>(); } _lessThanLongMax.Add(handle); } else { if (_lessThanLongMax != null) { _lessThanLongMax.Remove(handle); } } }
/// <summary> /// Sets or removes GTInt64 flag for a variable. /// </summary> public void SetGreaterThanLongMin(VariableHandle handle, bool lt) => SetConstrain(handle, NoteKind.GreaterThanLongMin, lt);
/// <summary> /// Sets variable type with byref flag in this state. /// </summary> /// <param name="handle">Variable handle.</param> public void SetLocalRef(VariableHandle handle) { SetLocalType(handle, GetLocalType(handle).WithRefFlag); }
/// <summary> /// Gets value indicating the variable is set in all code paths. /// Gets also <c>true</c> if we don't known. /// </summary> public bool IsLocalSet(VariableHandle handle) { handle.ThrowIfInvalid(); return(handle.Slot >= FlowContext.BitsCount || (_initializedMask & (1u << handle)) != 0); }
/// <summary> /// Handles use of a local variable. /// </summary> public void VisitLocal(VariableHandle handle) { handle.ThrowIfInvalid(); _flowCtx.SetUsed(handle); }
TypeRefMask GetUnknownLocalType(VariableHandle handle) { return(IsLocalSet(handle) ? TypeRefMask.AnyType.WithRefFlag // <= SetAllUnknown() called : 0); // variable was not initialized in the state yet }
/// <summary> /// Gets type of variable at this state. /// </summary> public TypeRefMask GetLocalType(VariableHandle handle) { handle.ThrowIfInvalid(); return((handle < _varsType.Length) ? _varsType[handle] : 0); }
/// <summary> /// Handles use of a local variable. /// </summary> public void VisitLocal(VariableHandle handle) { handle.ThrowIfInvalid(); FlowContext.SetUsed(handle); }
private static bool HandleTypeChecking( TypeRefMask currentType, TypeRefMask targetType, ConditionBranch branch, FlowState flowState, VariableHandle handle, bool skipTrueIfAnyType) { // Information whether this path can ever be taken bool isFeasible = true; if (branch == ConditionBranch.ToTrue) { // In the true branch the IsAnyType case can be optionally skipped if (skipTrueIfAnyType && currentType.IsAnyType) { return(isFeasible); } // Intersect the possible types with those checked by the function, always keeping the IsRef flag. // IncludesSubclasses is kept only if it is specified in targetType. TypeRefMask resultType = (currentType & (targetType | TypeRefMask.IsRefMask)); if (resultType.IsVoid) { // Clearing the type out in this branch means the variable will never be of that type. // In order to prevent errors in analysis and code generation, set the type to the one specified. resultType = targetType | (currentType & TypeRefMask.IsRefMask); isFeasible = false; } flowState.SetLocalType(handle, resultType); } else { Debug.Assert(branch == ConditionBranch.ToFalse); // In the false branch we cannot handle the IsAnyType case if (currentType.IsAnyType) { return(isFeasible); } // Remove the types and flags excluded by the fact that the function returned false TypeRefMask resultType = currentType & (~targetType); if (resultType.IsVoid) { // Clearing the type out in this branch means the variable will always be of that type // In order to prevent errors in analysis and code generation, do not alter the type in this case. isFeasible = false; } else { flowState.SetLocalType(handle, resultType); } } return(isFeasible); }
private static bool TryGetVariableHandle(BoundVariable boundvar, FlowState state, out VariableHandle varHandle) { if (boundvar.Name != null) // direct variable name { if (boundvar.VariableKind == VariableKind.LocalVariable || boundvar.VariableKind == VariableKind.Parameter || boundvar.VariableKind == VariableKind.LocalTemporalVariable) { varHandle = state.GetLocalHandle(new VariableName(boundvar.Name)); return(true); } } // varHandle = default(VariableHandle); return(false); }
/// <summary> /// Gets GTInt64 flag for a variable. /// </summary> public bool IsGreaterThanLongMin(VariableHandle handle) => HasConstrain(handle, NoteKind.GreaterThanLongMin) && TypeRefContext.IsLongOnly(GetLocalType(handle));
public NoteData(VariableHandle variable, NoteKind kind) { this.Variable = variable; this.Kind = kind; }
/// <summary> /// Gets LTInt64 flag for a variable. /// </summary> public bool IsLessThanLongMax(VariableHandle handle) => HasConstrain(handle, NoteKind.LessThanLongMax);
/// <summary> /// Sets or removes LTInt64 flag for a variable. /// </summary> public void SetLessThanLongMax(VariableHandle handle, bool lt) => SetConstrain(handle, NoteKind.LessThanLongMax, lt);
bool HasConstrain(VariableHandle variable, NoteKind kind) => _notes != null && _notes.Contains(new NoteData(variable, kind));
/// <summary> /// Gets LTInt64 flag for a variable. /// </summary> public bool IsLTInt64Max(VariableHandle handle) => _lessThanLongMax != null && _lessThanLongMax.Contains(handle);
/// <summary> /// Gets GTInt64 flag for a variable. /// </summary> public bool IsGreaterThanLongMin(VariableHandle handle) => HasConstrain(handle, NoteKind.GreaterThanLongMin);
private static bool TryGetVariableHandle(IVariableReference boundvar, FlowState state, out VariableHandle varHandle) { if (boundvar is LocalVariableReference local && local.BoundName.IsDirect) // direct variable name { if (local.VariableKind == VariableKind.LocalVariable || local.VariableKind == VariableKind.Parameter || local.VariableKind == VariableKind.LocalTemporalVariable) { varHandle = state.GetLocalHandle(local.BoundName.NameValue); return(true); } } // varHandle = default(VariableHandle); return(false); }
/// <summary> /// Gets LTInt64 flag for a variable. /// </summary> public bool IsLessThanLongMax(VariableHandle handle) => HasConstrain(handle, NoteKind.LessThanLongMax) && TypeRefContext.IsLongOnly(GetLocalType(handle));