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;
}
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;
}
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));
}
}
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;
}
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;
}
Aggregations