Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
35ca9fc
Alloc-free verification prototype
natgavrilenko Dec 10, 2024
3940bb8
Using stack pointer in alloc tests
natgavrilenko Jan 20, 2025
a4b8f1d
Support alloc-free dev (#794)
CapZTr Mar 11, 2025
20e84e4
Init setup
Apr 10, 2025
ddc0e11
Add Alloc and MemFree to witness for debugging
Apr 10, 2025
8631ddc
Modified some memory models and tests
Apr 30, 2025
44ead61
Fix event and relation extraction of alloc-free for witness
May 7, 2025
e5d6a28
Modify some relation and constraint definitions
May 13, 2025
8ff67e2
Merge development into this branch
May 13, 2025
5f7440f
Remove unnecessary definition
May 13, 2025
9803e52
Clean c11 and rc11
May 14, 2025
0659c5e
Modify as comments
May 14, 2025
616dfda
Clean code to prepare rebase
Jun 26, 2025
ec9717e
Merge remote-tracking branch 'upstream/development' into alloc-free-dev
Jun 26, 2025
4de382e
Fix merging
Jul 3, 2025
fd2593f
Merge remote-tracking branch 'upstream/development' into alloc-free-dev
Jul 3, 2025
d752cab
Fix CI tests: Attempt 1
Jul 11, 2025
89a4219
By Natalia: Add Termination event
Jul 17, 2025
5d21aee
Fix CI tests
Jul 17, 2025
cd4a5c1
Fix CI tests
Jul 18, 2025
702527a
Merge remote-tracking branch 'upstream/development' into alloc-free-dev
Jul 24, 2025
f21d510
Fix bugs from merge
Jul 24, 2025
02998bb
Add AllocPtrGraph & AllocMemGraph, modify as comments
Aug 1, 2025
9143013
Add Intrinsics pthread_detach (#905)
xeren Aug 7, 2025
1cdc4c3
Reverse vmm.cat
Aug 7, 2025
5f715e1
Merge remote-tracking branch 'upstream/development' into alloc-free-dev
Aug 7, 2025
01e6ac1
Fix bugs from merge
Aug 7, 2025
e602036
Remove vmm from AllocFreeTest
Aug 7, 2025
3a08b77
Add DI source location for frees
Aug 7, 2025
2b60b6c
Add MemAlloc & MemFree to witness
Aug 8, 2025
f4ca35d
Remove unused imports
Aug 8, 2025
8eebe94
Remove obsolete pthread mutex events. (#921)
xeren Aug 11, 2025
e48a53f
Merge remote-tracking branch 'upstream/development' into alloc-free-dev
Aug 14, 2025
8d8ca49
Make MemAlloc and MemFree extend GenericMemoryEvent
Aug 21, 2025
efa54cc
Remove M tag when copy alloc
Aug 21, 2025
4c531d7
Add HeapAlloc
Aug 22, 2025
944045f
Add HeapAlloc class
Aug 28, 2025
946bf92
Revert to efa54cc18
Aug 29, 2025
f1a05c6
Make MemAlloc & MemFree extend AbstractMemoryCoreEvent
Aug 29, 2025
1d49035
Use LazyEventGraph for loc and allocMem in LazyRelationAnalysis
Aug 29, 2025
2404a04
Fix EqualityAliasAnalysis
Aug 29, 2025
5d28e57
Fix EqualityAliasAnalysis
Aug 29, 2025
d7b7b4e
Small change to LazyRelationAnalysis
Aug 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,6 @@ public BooleanFormula sameValue(MemoryCoreEvent first, MemoryCoreEvent second) {
return addresses.get(event);
}

public TypedFormula<?, ?> address(MemFree free) {
return addresses.get(free);
}

public TypedFormula<?, ?> address(MemoryObject memoryObject) { return objAddress.get(memoryObject); }

public TypedFormula<IntegerType, ?> size(MemoryObject memoryObject) {
Expand Down Expand Up @@ -332,9 +328,6 @@ private void initialize() {
values.put(e, exprEncoder.encodeAt(store.getMemValue(), e));
}
}
if (e instanceof MemFree free) {
addresses.put(e, exprEncoder.encodeAt(free.getAddress(), free));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.dat3m.dartagnan.program.event.RegWriter;
import com.dat3m.dartagnan.program.event.core.Assert;
import com.dat3m.dartagnan.program.event.core.CondJump;
import com.dat3m.dartagnan.program.event.core.MemFree;
import com.dat3m.dartagnan.program.event.core.MemoryCoreEvent;
import com.dat3m.dartagnan.program.memory.MemoryObject;
import com.dat3m.dartagnan.smt.ModelExt;
Expand Down Expand Up @@ -97,10 +96,6 @@ public boolean isAllocated(MemoryObject memObj) {
return evaluateAt(ctx.address(e), e);
}

public TypedValue<?, ?> address(MemFree e) {
return evaluateAt(ctx.address(e), e);
}

public TypedValue<?, ?> address(MemoryObject e) {
return evaluate(ctx.address(e));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.dat3m.dartagnan.expression.type.TypeFactory;
import com.dat3m.dartagnan.program.Program;
import com.dat3m.dartagnan.program.Thread;
import com.dat3m.dartagnan.program.event.Event;
import com.dat3m.dartagnan.program.event.core.*;
import com.dat3m.dartagnan.program.event.metadata.SourceLocation;
import com.dat3m.dartagnan.utils.Utils;
Expand All @@ -23,6 +22,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.dat3m.dartagnan.GlobalSettings.getOrCreateOutputDirectory;
import static com.dat3m.dartagnan.configuration.OptionNames.*;
Expand All @@ -31,13 +31,13 @@ public interface AliasAnalysis {

Logger logger = LogManager.getLogger(AliasAnalysis.class);

boolean mustAlias(Event a, Event b);
boolean mustAlias(MemoryCoreEvent a, MemoryCoreEvent b);

boolean mayAlias(Event a, Event b);
boolean mayAlias(MemoryCoreEvent a, MemoryCoreEvent b);

boolean mustObjectAlias(Event a, Event b);
boolean mustObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b);

boolean mayObjectAlias(Event a, Event b);
boolean mayObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b);

/**
* Returns an overapproximation of the MSA points in the byte range of the specified event.
Expand Down Expand Up @@ -135,22 +135,22 @@ private CombinedAliasAnalysis(AliasAnalysis a1, AliasAnalysis a2) {
}

@Override
public boolean mustAlias(Event a, Event b) {
public boolean mustAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
return a1.mustAlias(a, b) || a2.mustAlias(a, b);
}

@Override
public boolean mayAlias(Event a, Event b) {
public boolean mayAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
return a1.mayAlias(a, b) && a2.mayAlias(a, b);
}

@Override
public boolean mustObjectAlias(Event a, Event b) {
public boolean mustObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
return a1.mustObjectAlias(a, b) || a2.mustObjectAlias(a, b);
}

@Override
public boolean mayObjectAlias(Event a, Event b) {
public boolean mayObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
return a1.mayObjectAlias(a, b) && a2.mayObjectAlias(a, b);
}

Expand Down Expand Up @@ -178,17 +178,18 @@ default Graphviz getGraphVisualization() {
}

private void populateAddressGraph(Map<String, Set<String>> may, Map<String, Set<String>> must,
List<? extends Event> list1, List<? extends Event> list2, Config configuration) {
for (final Event event1 : list1) {
List<? extends MemoryCoreEvent> list1, List<? extends MemoryCoreEvent> list2,
Config configuration) {
for (final MemoryCoreEvent event1 : list1) {
final String node1 = repr(event1, configuration);
if (node1 == null) {
continue;
}
final Set<String> maySet = may.computeIfAbsent(node1, k -> new HashSet<>());
final Set<String> mustSet = must.computeIfAbsent(node1, k -> new HashSet<>());
for (final Event event2 : list2) {
for (final MemoryCoreEvent event2 : list2) {
final String node2 = repr(event2, configuration);
if ((event1 instanceof MemoryCoreEvent && event2 instanceof MemoryCoreEvent)
if ((!(event1 instanceof MemFree) && !(event2 instanceof MemFree))
|| (event1 instanceof MemFree && event2 instanceof MemFree)) {
if (event1.getGlobalId() - event2.getGlobalId() >= 0) {
continue;
Expand Down Expand Up @@ -229,7 +230,9 @@ private Graphviz defaultGraph(Program program, Config configuration) {
// A dashed orange line marks the existence of events that may object-alias.
final Map<String, Set<String>> mayObjectGraph = new HashMap<>();

final List<MemoryCoreEvent> events = program.getThreadEvents(MemoryCoreEvent.class);
final List<MemoryCoreEvent> events = program.getThreadEvents(MemoryCoreEvent.class)
.stream().filter(e -> !(e instanceof MemFree) && !(e instanceof MemAlloc))
.collect(Collectors.toList());
final List<MemAlloc> allocs = program.getThreadEvents(MemAlloc.class);
final List<MemFree> frees = program.getThreadEvents(MemFree.class);

Expand All @@ -242,22 +245,16 @@ private Graphviz defaultGraph(Program program, Config configuration) {
// Generates the graphs
final var graphviz = new Graphviz();
graphviz.beginGraph("alias");
// Group events
for (final Thread thread : program.getThreads()) {
graphviz.beginSubgraph("Thread" + thread.getId());
graphviz.setEdgeAttributes("weight=100", "style=invis");
final List<Event> grouped = new ArrayList<>();
for (final Event event : thread.getEvents()) {
if (event instanceof MemoryCoreEvent || event instanceof MemAlloc || event instanceof MemFree) {
if (!configuration.graphvizShowAll && event instanceof Init) {
continue;
}
grouped.add(event);
final List<MemoryCoreEvent> memEvents = thread.getEvents(MemoryCoreEvent.class);
for (int i = 1; i < memEvents.size(); i++) {
final String node1 = repr(memEvents.get(i - 1), configuration);
final String node2 = repr(memEvents.get(i), configuration);
if (node1 == null || node2 == null) {
continue;
}
}
for (int i = 1; i < grouped.size(); i++) {
final String node1 = repr(grouped.get(i - 1), configuration);
final String node2 = repr(grouped.get(i), configuration);
graphviz.addEdge(node1, node2);
}
graphviz.end();
Expand Down Expand Up @@ -301,7 +298,7 @@ private void generateGraph(Program program, Config configuration) {
}
}

private static String repr(Event event, Config configuration) {
private static String repr(MemoryCoreEvent event, Config configuration) {
if (!configuration.graphvizShowAll && event instanceof Init) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.dat3m.dartagnan.program.Program;
import com.dat3m.dartagnan.program.Register;
import com.dat3m.dartagnan.program.analysis.SyntacticContextAnalysis;
import com.dat3m.dartagnan.program.event.Event;
import com.dat3m.dartagnan.program.event.MemoryEvent;
import com.dat3m.dartagnan.program.event.RegWriter;
import com.dat3m.dartagnan.program.event.core.*;
Expand Down Expand Up @@ -54,7 +53,7 @@ public class AndersenAliasAnalysis implements AliasAnalysis {
private final Map<Object, Set<Location>> addresses = new HashMap<>();
private final Map<Register, Set<MemoryEvent>> events = new HashMap<>();
private final Map<Register, Set<Location>> targets = new HashMap<>();
private final Map<Event, ImmutableSet<Location>> eventAddressSpaceMap = new HashMap<>();
private final Map<MemoryCoreEvent, ImmutableSet<Location>> eventAddressSpaceMap = new HashMap<>();
// Maps memory events to additional offsets inside their byte range, which may match other accesses' bounds.
private final Map<MemoryCoreEvent, List<Integer>> mixedAccesses = new HashMap<>();

Expand Down Expand Up @@ -86,23 +85,23 @@ public static AndersenAliasAnalysis fromConfig(Program program, Config config) {
// ================================ API ================================

@Override
public boolean mayAlias(Event x, Event y) {
public boolean mayAlias(MemoryCoreEvent x, MemoryCoreEvent y) {
return !Sets.intersection(getMaxAddressSet(x), getMaxAddressSet(y)).isEmpty();
}

@Override
public boolean mustAlias(Event x, Event y) {
public boolean mustAlias(MemoryCoreEvent x, MemoryCoreEvent y) {
Set<Location> lx = getMaxAddressSet(x);
return lx.size() == 1 && lx.equals(getMaxAddressSet(y));
}

@Override
public boolean mayObjectAlias(Event a, Event b) {
public boolean mayObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
return !Sets.intersection(getAccessibleObjects(a), getAccessibleObjects(b)).isEmpty();
}

@Override
public boolean mustObjectAlias(Event a, Event b) {
public boolean mustObjectAlias(MemoryCoreEvent a, MemoryCoreEvent b) {
Set<MemoryObject> objsA = getAccessibleObjects(a);
return objsA.size() == 1 && objsA.equals(getAccessibleObjects(b));
}
Expand All @@ -117,11 +116,11 @@ public List<Integer> mayMixedSizeAccesses(MemoryCoreEvent event) {
return IntStream.range(1, bytes).boxed().toList();
}

private ImmutableSet<Location> getMaxAddressSet(Event e) {
private ImmutableSet<Location> getMaxAddressSet(MemoryCoreEvent e) {
return eventAddressSpaceMap.get(e);
}

private Set<MemoryObject> getAccessibleObjects(Event e) {
private Set<MemoryObject> getAccessibleObjects(MemoryCoreEvent e) {
Set<MemoryObject> objs = new HashSet<>();
Set<Location> locs = getMaxAddressSet(e);
if (locs != null) {
Expand All @@ -137,8 +136,8 @@ private void detectMixedSizeAccesses() {
return;
}
final List<MemoryCoreEvent> events = eventAddressSpaceMap.keySet().stream()
.filter(e -> e instanceof MemoryCoreEvent)
.map(e -> (MemoryCoreEvent) e).collect(Collectors.toList());
.filter(e -> !(e instanceof MemAlloc) && !(e instanceof MemFree))
.collect(Collectors.toList());
final List<Set<Integer>> offsets = new ArrayList<>();
for (int i = 0; i < events.size(); i++) {
final var set0 = new HashSet<Integer>();
Expand Down Expand Up @@ -176,9 +175,6 @@ private void fetchMixedOffsets(Set<Integer> setX, Set<Location> addressesX, int
private void run(Program program) {
List<MemoryCoreEvent> memEvents = program.getThreadEvents(MemoryCoreEvent.class);
List<Local> locals = program.getThreadEvents(Local.class);
for (MemAlloc a : program.getThreadEvents(MemAlloc.class)) {
processAllocs(a);
}
for (MemoryCoreEvent e : memEvents) {
processLocs(e);
}
Expand All @@ -191,22 +187,22 @@ private void run(Program program) {
processResults(e);
}
for (MemoryCoreEvent e : memEvents) {
eventAddressSpaceMap.put(e, ImmutableSet.copyOf(getAddressSpace(e)));
}
for (MemFree f : program.getThreadEvents(MemFree.class)) {
eventAddressSpaceMap.put(f, ImmutableSet.copyOf(getAddressSpace(f)));
processResults(e);
}
}

private void processAllocs(MemAlloc a) {
Register r = a.getResultRegister();
Location base = new Location(a.getAllocatedObject(), 0);
eventAddressSpaceMap.put(a, ImmutableSet.of(base));
addAddress(r, base);
variables.add(r);
}

private void processLocs(MemoryCoreEvent e) {
if (e instanceof MemFree) {
return;
}
if (e instanceof MemAlloc a) {
Register r = a.getResultRegister();
Location base = new Location(a.getAllocatedObject(), 0);
eventAddressSpaceMap.put(a, ImmutableSet.of(base));
addAddress(r, base);
variables.add(r);
return;
}
Expression address = e.getAddress();
// Collect for each v events of form: p = *v, *v = q
if (address instanceof Register register) {
Expand Down Expand Up @@ -341,32 +337,29 @@ private void processResults(Local e) {
}
}

private Set<Location> getAddressSpace(Event e) {
Expression addrExpr;
if (e instanceof MemoryCoreEvent mce) {
addrExpr = mce.getAddress();
} else {
assert e instanceof MemFree;
addrExpr = ((MemFree) e).getAddress();
private void processResults(MemoryCoreEvent e) {
if (e instanceof MemAlloc) {
return;
}
Expression address = e.getAddress();
Set<Location> addresses;
if (addrExpr instanceof Register) {
Set<Location> target = targets.get(addrExpr);
addresses = target != null ? target : getAddresses(addrExpr);
if (address instanceof Register) {
Set<Location> target = targets.get(address);
addresses = target != null ? target : getAddresses(address);
} else {
Constant addressConstant = new Constant(addrExpr);
Constant addressConstant = new Constant(address);
if (addressConstant.failed) {
addresses = maxAddressSet;
} else {
Verify.verify(addressConstant.location != null, "accessing a pure constant address");
Verify.verify(addressConstant.location != null, "memory event accessing a pure constant address");
addresses = ImmutableSet.of(addressConstant.location);
}
}
if (addresses.isEmpty()) {
logger.warn("Empty pointer set for {}", synContext.get().getContextInfo(e));
addresses = maxAddressSet;
}
return addresses;
eventAddressSpaceMap.put(e, ImmutableSet.copyOf(addresses));
}

private static final class Constant {
Expand Down
Loading
Loading