Search in sources :

Example 1 with RegWriter

use of com.dat3m.dartagnan.program.event.core.utils.RegWriter in project Dat3M by hernanponcedeleon.

the class ConstantPropagation method getSimplifiedCopy.

// Creates a copy of the provided event, using the <propagationMap> to simplify expressions.
// Can return the original event if no simplifications are performed
private Event getSimplifiedCopy(Event ev, Map<Register, IExpr> propagationMap) {
    Event copy = ev;
    if (ev instanceof MemEvent && !ev.is(Tag.C11.PTHREAD) && !ev.is(Tag.C11.LOCK)) {
        MemEvent m = (MemEvent) ev;
        String mo = m.getMo();
        // All events for which we use reg are RegWriters
        Register reg = ev instanceof RegWriter ? ((RegWriter) ev).getResultRegister() : null;
        IExpr oldAddress = m.getAddress();
        IExpr newAddress = evaluate(oldAddress, propagationMap);
        newAddress = newAddress instanceof ITop ? oldAddress : newAddress;
        Verify.verifyNotNull(newAddress, "Expression %s got no value after constant propagation analysis", oldAddress);
        IExpr oldValue = (IExpr) ((MemEvent) ev).getMemValue();
        IExpr newValue = evaluate(oldValue, propagationMap);
        newValue = newValue instanceof ITop ? oldValue : newValue;
        Verify.verifyNotNull(newValue, "Expression %s got no value after constant propagation analysis", oldValue);
        // Atomic Events
        if (ev instanceof AtomicLoad) {
            copy = Atomic.newLoad(reg, newAddress, mo);
        } else if (ev instanceof AtomicStore) {
            copy = Atomic.newStore(newAddress, newValue, mo);
        } else if (ev instanceof AtomicCmpXchg) {
            IExpr oldExpectedAddr = ((AtomicCmpXchg) ev).getExpectedAddr();
            IExpr newExpectedAddr = evaluate(oldExpectedAddr, propagationMap);
            Verify.verifyNotNull(newExpectedAddr, "Register %s got no value after constant propagation analysis", oldExpectedAddr);
            copy = Atomic.newCompareExchange(reg, newAddress, newExpectedAddr, newValue, mo, ev.is(Tag.STRONG));
        } else if (ev instanceof AtomicXchg) {
            copy = Atomic.newExchange(reg, newAddress, newValue, mo);
        } else if (ev instanceof AtomicFetchOp) {
            copy = Atomic.newFetchOp(reg, newAddress, newValue, ((AtomicFetchOp) ev).getOp(), mo);
        } else // Linux Events
        if (ev instanceof RMWAddUnless) {
            copy = Linux.newRMWAddUnless(newAddress, reg, ((RMWAddUnless) ev).getCmp(), newValue);
        } else if (ev instanceof RMWCmpXchg) {
            copy = Linux.newRMWCompareExchange(newAddress, reg, ((RMWCmpXchg) ev).getCmp(), newValue, mo);
        } else if (ev instanceof RMWFetchOp) {
            copy = Linux.newRMWFetchOp(newAddress, reg, newValue, ((RMWFetchOp) ev).getOp(), mo);
        } else if (ev instanceof RMWOp) {
            copy = Linux.newRMWOp(newAddress, reg, newValue, ((RMWOp) ev).getOp());
        } else if (ev instanceof RMWOpAndTest) {
            copy = Linux.newRMWOpAndTest(newAddress, reg, newValue, ((RMWOpAndTest) ev).getOp());
        } else if (ev instanceof RMWOpReturn) {
            copy = Linux.newRMWOpReturn(newAddress, reg, newValue, ((RMWOpReturn) ev).getOp(), mo);
        } else if (ev instanceof RMWXchg) {
            copy = Linux.newRMWExchange(newAddress, reg, newValue, mo);
        } else // Exclusive events
        if (ev.is(Tag.EXCL)) {
            if (ev instanceof Load) {
                copy = EventFactory.newRMWLoadExclusive(reg, newAddress, mo);
            } else if (ev instanceof StoreExclusive) {
                copy = AArch64.newExclusiveStore(reg, newAddress, newValue, mo);
            } else {
                // Other EXCL events are generated during compilation (which have not yet occurred)
                throw new UnsupportedOperationException(String.format("Exclusive event %s not supported by %s", ev.getClass().getSimpleName(), getClass().getSimpleName()));
            }
        } else // Basic Events
        if (ev instanceof Load) {
            copy = EventFactory.newLoad(reg, newAddress, mo);
        } else if (ev instanceof Store) {
            copy = EventFactory.newStore(newAddress, newValue, mo);
        }
    } else // Local.initialise() which is never the case for the new Event e below.
    if (ev instanceof Local && ((Local) ev).getExpr() instanceof IExpr && !ev.is(Tag.ASSERTION)) {
        Register reg = ((Local) ev).getResultRegister();
        IExpr oldValue = (IExpr) ((Local) ev).getExpr();
        IExpr newValue = evaluate(oldValue, propagationMap);
        newValue = newValue instanceof ITop ? oldValue : newValue;
        Verify.verify(newValue != null, String.format("Expression %s got no value after constant propagation analysis", oldValue));
        copy = EventFactory.newLocal(reg, newValue);
    }
    if (copy != ev) {
        // We made a real copy
        copy.setOId(ev.getOId());
        copy.setUId(ev.getUId());
        copy.setCId(ev.getCId());
        copy.setCLine(ev.getCLine());
        copy.setThread(ev.getThread());
    }
    return copy;
}
Also used : StoreExclusive(com.dat3m.dartagnan.program.event.arch.aarch64.StoreExclusive) Register(com.dat3m.dartagnan.program.Register) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter)

Example 2 with RegWriter

use of com.dat3m.dartagnan.program.event.core.utils.RegWriter in project Dat3M by hernanponcedeleon.

the class ProgramEncoder method encodeDependencies.

/**
 * @param ctx
 * Builder of expressions and formulas.
 * @return
 * Describes that for each pair of events, if the reader uses the result of the writer,
 * then the value the reader gets from the register is exactly the value that the writer computed.
 * Also, the reader may only use the value of the latest writer that is executed.
 * Also, if no fitting writer is executed, the reader uses 0.
 */
public BooleanFormula encodeDependencies(SolverContext ctx) {
    logger.info("Encoding dependencies");
    BooleanFormulaManager bmgr = ctx.getFormulaManager().getBooleanFormulaManager();
    BooleanFormula enc = bmgr.makeTrue();
    for (Map.Entry<Event, Map<Register, Dependency.State>> e : dep.getAll()) {
        Event reader = e.getKey();
        for (Map.Entry<Register, Dependency.State> r : e.getValue().entrySet()) {
            Formula value = r.getKey().toIntFormula(reader, ctx);
            Dependency.State state = r.getValue();
            BooleanFormula overwrite = bmgr.makeFalse();
            for (Event writer : reverse(state.may)) {
                assert writer instanceof RegWriter;
                BooleanFormula edge;
                if (state.must.contains(writer)) {
                    edge = writer.exec();
                } else {
                    edge = dependencyEdgeVariable(writer, reader, bmgr);
                    enc = bmgr.and(enc, bmgr.equivalence(edge, bmgr.and(writer.exec(), reader.cf(), bmgr.not(overwrite))));
                }
                enc = bmgr.and(enc, bmgr.implication(edge, generalEqual(value, ((RegWriter) writer).getResultRegisterExpr(), ctx)));
                overwrite = bmgr.or(overwrite, writer.exec());
            }
            if (initializeRegisters && !state.initialized) {
                enc = bmgr.and(enc, bmgr.or(overwrite, bmgr.not(reader.cf()), generalEqualZero(value, ctx)));
            }
        }
    }
    return enc;
}
Also used : IntegerFormula(org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula) Register(com.dat3m.dartagnan.program.Register) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter) Event(com.dat3m.dartagnan.program.event.core.Event) Dependency(com.dat3m.dartagnan.program.analysis.Dependency)

Example 3 with RegWriter

use of com.dat3m.dartagnan.program.event.core.utils.RegWriter in project Dat3M by hernanponcedeleon.

the class ExecutionModel method trackDependencies.

private void trackDependencies(Event e) {
    while (!endIfs.isEmpty() && e.getCId() >= endIfs.peek().getCId()) {
        // We exited an If and remove the dependencies associated with it
        // We do this inside a loop just in case multiple Ifs are left simultaneously
        endIfs.pop();
        curCtrlDeps.removeAll(ifCtrlDeps.pop());
    }
    if (e instanceof MemEvent) {
        // ---- Track address dependency ----
        MemEvent memEvent = (MemEvent) e;
        HashSet<EventData> deps = new HashSet<>();
        for (Register reg : memEvent.getAddress().getRegs()) {
            deps.addAll(lastRegWrites.get(reg));
        }
        addrDepMap.put(eventMap.get(e), deps);
    }
    if (e.is(Tag.VISIBLE)) {
        // ---- Track ctrl dependency ----
        // TODO: This may be done more efficiently, as many events share the same set of ctrldeps.
        ctrlDepMap.put(eventMap.get(e), new HashSet<>(curCtrlDeps));
    }
    if (e instanceof RegReaderData) {
        // ---- Track data dependency ----
        RegReaderData reader = (RegReaderData) e;
        HashSet<EventData> deps = new HashSet<>();
        for (Register r : reader.getDataRegs()) {
            deps.addAll(lastRegWrites.getOrDefault(r, Collections.emptySet()));
        }
        if (e instanceof Store) {
            // ---- visible data dependency ----
            dataDepMap.put(eventMap.get(e), deps);
        }
        if (e instanceof RegWriter) {
            // ---- internal data dependency ----
            RegWriter writer = (RegWriter) e;
            lastRegWrites.put(writer.getResultRegister(), deps);
        }
        if (e instanceof CondJump) {
            if (e instanceof IfAsJump) {
                // Remember what dependencies were added when entering the If so we can remove them when exiting
                HashSet<EventData> addedDeps = new HashSet<>(Sets.difference(deps, curCtrlDeps));
                ifCtrlDeps.push(addedDeps);
                endIfs.push(((IfAsJump) e).getEndIf());
            }
            // Jumps add all dependencies
            curCtrlDeps.addAll(deps);
        }
    }
    if (e instanceof Load) {
        // ---- Update lastRegWrites ----
        Load load = (Load) e;
        lastRegWrites.compute(load.getResultRegister(), (k, v) -> new HashSet<>()).add(eventMap.get(e));
    }
}
Also used : java.util(java.util) CO(com.dat3m.dartagnan.wmm.relation.RelationNameRepository.CO) BooleanFormula(org.sosy_lab.java_smt.api.BooleanFormula) com.dat3m.dartagnan.program.event.core(com.dat3m.dartagnan.program.event.core) RF(com.dat3m.dartagnan.wmm.relation.RelationNameRepository.RF) Thread(com.dat3m.dartagnan.program.Thread) FilterAbstract(com.dat3m.dartagnan.program.filter.FilterAbstract) EndAtomic(com.dat3m.dartagnan.program.event.lang.svcomp.EndAtomic) Model(org.sosy_lab.java_smt.api.Model) Wmm(com.dat3m.dartagnan.wmm.Wmm) ImmutableList(com.google.common.collect.ImmutableList) SolverContext(org.sosy_lab.java_smt.api.SolverContext) Program(com.dat3m.dartagnan.program.Program) RegReaderData(com.dat3m.dartagnan.program.event.core.utils.RegReaderData) BigInteger(java.math.BigInteger) FilterBasic(com.dat3m.dartagnan.program.filter.FilterBasic) VerificationTask(com.dat3m.dartagnan.verification.VerificationTask) RelCo(com.dat3m.dartagnan.wmm.relation.base.memory.RelCo) BeginAtomic(com.dat3m.dartagnan.program.event.lang.svcomp.BeginAtomic) Relation(com.dat3m.dartagnan.wmm.relation.Relation) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) Tag(com.dat3m.dartagnan.program.event.Tag) Preconditions(com.google.common.base.Preconditions) Register(com.dat3m.dartagnan.program.Register) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter) Register(com.dat3m.dartagnan.program.Register) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter) RegReaderData(com.dat3m.dartagnan.program.event.core.utils.RegReaderData)

Example 4 with RegWriter

use of com.dat3m.dartagnan.program.event.core.utils.RegWriter in project Dat3M by hernanponcedeleon.

the class WitnessBuilder method build.

public WitnessGraph build() {
    for (Thread t : task.getProgram().getThreads()) {
        for (Event e : t.getEntry().getSuccessors()) {
            eventThreadMap.put(e, t.getId() - 1);
        }
    }
    WitnessGraph graph = new WitnessGraph();
    graph.addAttribute(UNROLLBOUND.toString(), valueOf(task.getProgram().getUnrollingBound()));
    graph.addAttribute(WITNESSTYPE.toString(), type + "_witness");
    graph.addAttribute(SOURCECODELANG.toString(), "C");
    graph.addAttribute(PRODUCER.toString(), "Dartagnan");
    graph.addAttribute(SPECIFICATION.toString(), "CHECK( init(main()), LTL(G ! call(reach_error())))");
    graph.addAttribute(PROGRAMFILE.toString(), originalProgramFilePath);
    graph.addAttribute(PROGRAMHASH.toString(), getFileSHA256(new File(originalProgramFilePath)));
    graph.addAttribute(ARCHITECTURE.toString(), "32bit");
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    // "If the timestamp is in UTC time, it ends with a 'Z'."
    // https://github.com/sosy-lab/sv-witnesses/blob/main/README-GraphML.md
    graph.addAttribute(CREATIONTIME.toString(), df.format(new Date()) + "Z");
    Node v0 = new Node("N0");
    v0.addAttribute("entry", "true");
    Node v1 = new Node("N1");
    Node v2 = new Node("N2");
    Edge edge = new Edge(v0, v1);
    edge.addAttribute(CREATETHREAD.toString(), "0");
    graph.addEdge(edge);
    edge = new Edge(v1, v2);
    edge.addAttribute(THREADID.toString(), "0");
    edge.addAttribute(ENTERFUNCTION.toString(), "main");
    graph.addEdge(edge);
    int nextNode = 2;
    int threads = 1;
    if (type.equals("correctness")) {
        return graph;
    }
    try (Model model = prover.getModel()) {
        List<Event> execution = reOrderBasedOnAtomicity(task.getProgram(), getSCExecutionOrder(model));
        for (int i = 0; i < execution.size(); i++) {
            Event e = execution.get(i);
            if (i + 1 < execution.size()) {
                Event next = execution.get(i + 1);
                if (e.getCLine() == next.getCLine() && e.getThread() == next.getThread()) {
                    continue;
                }
            }
            edge = new Edge(new Node("N" + nextNode), new Node("N" + (nextNode + 1)));
            edge.addAttribute(THREADID.toString(), valueOf(eventThreadMap.get(e)));
            edge.addAttribute(STARTLINE.toString(), valueOf(e.getCLine()));
            // CLines and thus won't create an edge (as expected)
            if (e.hasFilter(WRITE) && e.hasFilter(PTHREAD)) {
                edge.addAttribute(CREATETHREAD.toString(), valueOf(threads));
                threads++;
            }
            if (e instanceof Load) {
                RegWriter l = (RegWriter) e;
                edge.addAttribute(EVENTID.toString(), valueOf(e.getUId()));
                edge.addAttribute(LOADEDVALUE.toString(), l.getWrittenValue(e, model, ctx).toString());
            }
            if (e instanceof Store) {
                Store s = (Store) e;
                edge.addAttribute(EVENTID.toString(), valueOf(e.getUId()));
                edge.addAttribute(STOREDVALUE.toString(), s.getMemValue().getIntValue(s, model, ctx).toString());
            }
            graph.addEdge(edge);
            nextNode++;
            if (e.hasFilter(Tag.ASSERTION)) {
                break;
            }
        }
    } catch (SolverException ignore) {
    // The if above guarantees that if we reach this try, a Model exists
    }
    graph.getNode("N" + nextNode).addAttribute("violation", "true");
    return graph;
}
Also used : Load(com.dat3m.dartagnan.program.event.core.Load) Store(com.dat3m.dartagnan.program.event.core.Store) Thread(com.dat3m.dartagnan.program.Thread) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter) SimpleDateFormat(java.text.SimpleDateFormat) DateFormat(java.text.DateFormat) Model(org.sosy_lab.java_smt.api.Model) MemEvent(com.dat3m.dartagnan.program.event.core.MemEvent) Event(com.dat3m.dartagnan.program.event.core.Event) SolverException(org.sosy_lab.java_smt.api.SolverException) File(java.io.File) SimpleDateFormat(java.text.SimpleDateFormat)

Example 5 with RegWriter

use of com.dat3m.dartagnan.program.event.core.utils.RegWriter in project Dat3M by hernanponcedeleon.

the class FindSpinLoops method isSideEffectFree.

private boolean isSideEffectFree(Label loopBegin, CondJump loopEnd) {
    Event cur = loopBegin.getSuccessor();
    // Unsafe means the loop read from the registers before writing to them.
    Set<Register> unsafeRegisters = new HashSet<>();
    // Safe means the loop wrote to these register before using them
    Set<Register> safeRegisters = new HashSet<>();
    while (cur != loopEnd) {
        if (cur instanceof MemEvent) {
            if (cur.is(Tag.WRITE)) {
                // Writes always cause side effects
                return false;
            }
            MemEvent memEvent = (MemEvent) cur;
            Set<Register> addrRegs = memEvent.getAddress().getRegs();
            unsafeRegisters.addAll(Sets.difference(addrRegs, safeRegisters));
        }
        if (cur instanceof RegReaderData) {
            RegReaderData reader = (RegReaderData) cur;
            Set<Register> dataRegs = reader.getDataRegs();
            unsafeRegisters.addAll(Sets.difference(dataRegs, safeRegisters));
        }
        if (cur instanceof RegWriter) {
            RegWriter writer = (RegWriter) cur;
            if (unsafeRegisters.contains(writer.getResultRegister())) {
                return false;
            } else {
                safeRegisters.add(writer.getResultRegister());
            }
        }
        cur = cur.getSuccessor();
    }
    return true;
}
Also used : Register(com.dat3m.dartagnan.program.Register) MemEvent(com.dat3m.dartagnan.program.event.core.MemEvent) RegWriter(com.dat3m.dartagnan.program.event.core.utils.RegWriter) RegReaderData(com.dat3m.dartagnan.program.event.core.utils.RegReaderData) MemEvent(com.dat3m.dartagnan.program.event.core.MemEvent) Event(com.dat3m.dartagnan.program.event.core.Event) HashSet(java.util.HashSet)

Aggregations

RegWriter (com.dat3m.dartagnan.program.event.core.utils.RegWriter)15 Register (com.dat3m.dartagnan.program.Register)13 Event (com.dat3m.dartagnan.program.event.core.Event)9 Thread (com.dat3m.dartagnan.program.Thread)4 MemEvent (com.dat3m.dartagnan.program.event.core.MemEvent)4 RegReaderData (com.dat3m.dartagnan.program.event.core.utils.RegReaderData)4 ImmutableList (com.google.common.collect.ImmutableList)4 BigInteger (java.math.BigInteger)4 Collectors (java.util.stream.Collectors)4 Program (com.dat3m.dartagnan.program.Program)3 Dependency (com.dat3m.dartagnan.program.analysis.Dependency)3 FilterBasic (com.dat3m.dartagnan.program.filter.FilterBasic)3 ImmutableMap (com.google.common.collect.ImmutableMap)3 java.util (java.util)3 Set (java.util.Set)3 BooleanFormula (org.sosy_lab.java_smt.api.BooleanFormula)3 SolverContext (org.sosy_lab.java_smt.api.SolverContext)3 IValue (com.dat3m.dartagnan.expression.IValue)2 Utils.generalEqual (com.dat3m.dartagnan.expression.utils.Utils.generalEqual)2 ExecutionAnalysis (com.dat3m.dartagnan.program.analysis.ExecutionAnalysis)2