private void VisitFunction(Function function) { Debug.Assert(function.OutParams.Count == 1); List <CommutativityHint> hints = new List <CommutativityHint>(); // First we collect all {:commutativity "first_action", "second_action"} attributes for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next) { if (kv.Key != CivlAttributes.COMMUTATIVITY) { continue; } if (kv.Params.Count == 2 && kv.Params[0] is string firstActionName && kv.Params[1] is string secondActionName) { firstAction = ctc.FindAtomicActionOrAbstraction(firstActionName); secondAction = ctc.FindAtomicActionOrAbstraction(secondActionName); if (firstAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (secondAction == null) { ctc.Error(kv, $"Could not find atomic action {secondActionName}"); } if (firstAction != null && secondAction != null) { CheckInParams(function.InParams); } hints.Add(new CommutativityHint(function, firstAction, secondAction, args)); }
private void VisitFunction(Function function) { Debug.Assert(function.OutParams.Count == 1); for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next) { if (kv.Key != CivlAttributes.WITNESS) { continue; } if (kv.Params.Count == 3 && kv.Params[0] is string witnessedVariableName && kv.Params[1] is string firstActionName && kv.Params[2] is string secondActionName) { witnessedVariable = ctc.sharedVariables.Find(v => v.Name == witnessedVariableName); if (witnessedVariable == null) { ctc.Error(kv, $"Could not find shared variable {witnessedVariableName}"); } else if (!function.OutParams[0].TypedIdent.Type.Equals(witnessedVariable.TypedIdent.Type)) { ctc.Error(function, "Result type does not match witnessed variable"); } firstAction = ctc.FindAtomicAction(firstActionName); secondAction = ctc.FindAtomicAction(secondActionName); if (firstAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (secondAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (firstAction != null && secondAction != null) { CheckInParams(function.InParams); } allWitnessFunctions.Add(new WitnessFunction(function, witnessedVariable, firstAction, secondAction, args)); }
public override Cmd VisitCallCmd(CallCmd node) { Procedure enclosingProc = civlTypeChecker.enclosingImpl.Proc; if (!civlTypeChecker.procToAtomicProcedureInfo.ContainsKey(node.Proc)) { civlTypeChecker.Error(node, "Atomic procedure can only call an atomic procedure"); return(base.VisitCallCmd(node)); } var callerInfo = civlTypeChecker.procToAtomicProcedureInfo[enclosingProc]; var calleeInfo = civlTypeChecker.procToAtomicProcedureInfo[node.Proc]; if (calleeInfo.isPure) { // do nothing } else if (callerInfo.isPure) { civlTypeChecker.Error(node, "Pure procedure can only call pure procedures"); } else if (!callerInfo.layerRange.Subset(calleeInfo.layerRange)) { civlTypeChecker.Error(node, "Caller layers must be subset of callee layers"); } return(base.VisitCallCmd(node)); }
private void LoopCheck() { var graph = new Graph <Absy>(new HashSet <Tuple <Absy, Absy> >(atomicityLabels.Keys)); graph.AddSource(initialState); graph.ComputeLoops(); var edgeToLoopHeader = new Dictionary <Tuple <Absy, Absy>, Block>(); foreach (Block header in graph.SortHeadersByDominance()) { foreach (var source in graph.BackEdgeNodes(header)) { edgeToLoopHeader[new Tuple <Absy, Absy>(source, header)] = header; foreach (var node in graph.NaturalLoops(header, source)) { if (node == header) { continue; } foreach (var pred in graph.Predecessors(node)) { var edge = new Tuple <Absy, Absy>(pred, node); if (edgeToLoopHeader.ContainsKey(edge)) { continue; } edgeToLoopHeader[edge] = header; } } } } var parentLoopHeader = new Dictionary <Block, Block>(); foreach (Block header in graph.Headers) { foreach (var pred in graph.Predecessors(header).Except(graph.BackEdgeNodes(header))) { var edge = new Tuple <Absy, Absy>(pred, header); if (edgeToLoopHeader.ContainsKey(edge)) { parentLoopHeader[header] = edgeToLoopHeader[edge]; break; } } } var yieldingLoopHeaders = new HashSet <Block>(graph.Headers.OfType <Block>() .Where(header => civlTypeChecker.IsYieldingLoopHeader(header, currLayerNum))); foreach (var header in parentLoopHeader.Keys) { var parentHeader = parentLoopHeader[header]; if (yieldingLoopHeaders.Contains(header) && !yieldingLoopHeaders.Contains(parentHeader)) { civlTypeChecker.Error(parentHeader, $"Loop header must be yielding at layer {currLayerNum}"); } } foreach (var edge in edgeToLoopHeader.Keys) { var header = edgeToLoopHeader[edge]; if (yieldingLoopHeaders.Contains(header)) { continue; } if (atomicityLabels[edge] == Y) { civlTypeChecker.Error(header, $"Loop header must be yielding at layer {currLayerNum}"); } } }
private void Error(string msg) { ctc.Error(node, msg); errorCount++; }