Skip to content

Commit

Permalink
Add support for encoding tuples (Tuple theory) (hernanponcedeleon#775)
Browse files Browse the repository at this point in the history
* Add support for AggregateTypes in encoding.
Also add new Aggregate operations EQ and NEQ

* Remove RegisterDecomposition.java
  • Loading branch information
ThomasHaas authored and Tianrui Zheng committed Nov 25, 2024
1 parent 1b8251d commit c5468bf
Show file tree
Hide file tree
Showing 19 changed files with 251 additions and 99 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.dat3m.dartagnan.encoding;

import com.dat3m.dartagnan.configuration.ProgressModel;
import com.dat3m.dartagnan.encoding.formulas.TupleFormula;
import com.dat3m.dartagnan.encoding.formulas.TupleFormulaManager;
import com.dat3m.dartagnan.expression.Expression;
import com.dat3m.dartagnan.expression.Type;
import com.dat3m.dartagnan.expression.integers.IntCmpOp;
import com.dat3m.dartagnan.expression.type.AggregateType;
import com.dat3m.dartagnan.expression.type.BooleanType;
import com.dat3m.dartagnan.expression.type.IntegerType;
import com.dat3m.dartagnan.expression.type.TypeFactory;
import com.dat3m.dartagnan.program.Register;
import com.dat3m.dartagnan.program.analysis.BranchEquivalence;
import com.dat3m.dartagnan.program.analysis.ExecutionAnalysis;
Expand Down Expand Up @@ -33,7 +37,9 @@
import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.dat3m.dartagnan.configuration.OptionNames.*;
Expand All @@ -54,6 +60,7 @@ public final class EncodingContext {
private final RelationAnalysis relationAnalysis;
private final FormulaManager formulaManager;
private final BooleanFormulaManager booleanFormulaManager;
private final TupleFormulaManager tupleFormulaManager;

@Option(
name=IDL_TO_SAT,
Expand Down Expand Up @@ -88,6 +95,7 @@ private EncodingContext(VerificationTask t, Context a, FormulaManager m) {
relationAnalysis = a.requires(RelationAnalysis.class);
formulaManager = m;
booleanFormulaManager = m.getBooleanFormulaManager();
tupleFormulaManager = new TupleFormulaManager(this);
}

public static EncodingContext of(VerificationTask task, Context analysisContext, FormulaManager formulaManager) throws InvalidConfigurationException {
Expand Down Expand Up @@ -126,6 +134,10 @@ public BooleanFormulaManager getBooleanFormulaManager() {
return booleanFormulaManager;
}

public TupleFormulaManager getTupleFormulaManager() {
return tupleFormulaManager;
}

public Formula encodeFinalExpression(Expression expression) {
return new ExpressionEncoder(this, null).encode(expression);
}
Expand Down Expand Up @@ -249,6 +261,9 @@ public BooleanFormula equal(Formula left, Formula right) {
if (left instanceof BooleanFormula l && right instanceof BooleanFormula r) {
return booleanFormulaManager.equivalence(l, r);
}
if (left instanceof TupleFormula l && right instanceof TupleFormula r) {
return tupleFormulaManager.equal(l, r);
}
throw new UnsupportedOperationException(String.format("Unknown types for equal(%s,%s)", left, right));
}

Expand Down Expand Up @@ -439,6 +454,14 @@ Formula makeVariable(String name, Type type) {
return formulaManager.getBitvectorFormulaManager().makeVariable(integerType.getBitWidth(), name);
}
}
if (type instanceof AggregateType) {
final Map<Integer, Type> primitives = TypeFactory.getInstance().decomposeIntoPrimitives(type);
final List<Formula> elements = new ArrayList<>();
for (Type eleType : primitives.values()) {
elements.add(makeVariable(name + "@" + elements.size(), eleType));
}
return tupleFormulaManager.makeTuple(elements);
}
throw new UnsupportedOperationException(String.format("Cannot encode variable of type %s.", type));
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package com.dat3m.dartagnan.encoding;

import com.dat3m.dartagnan.encoding.formulas.TupleFormula;
import com.dat3m.dartagnan.expression.Expression;
import com.dat3m.dartagnan.expression.ExpressionVisitor;
import com.dat3m.dartagnan.expression.Type;
import com.dat3m.dartagnan.expression.aggregates.AggregateCmpExpr;
import com.dat3m.dartagnan.expression.aggregates.ConstructExpr;
import com.dat3m.dartagnan.expression.aggregates.ExtractExpr;
import com.dat3m.dartagnan.expression.booleans.BoolBinaryExpr;
import com.dat3m.dartagnan.expression.booleans.BoolLiteral;
import com.dat3m.dartagnan.expression.booleans.BoolUnaryExpr;
Expand All @@ -18,6 +22,8 @@
import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Arrays.asList;
Expand Down Expand Up @@ -282,6 +288,33 @@ public Formula visitITEExpression(ITEExpr iteExpr) {
return booleanFormulaManager.ifThenElse(guard, tBranch, fBranch);
}

@Override
public Formula visitConstructExpression(ConstructExpr construct) {
final List<Formula> elements = new ArrayList<>();
for (Expression inner : construct.getOperands()) {
elements.add(encode(inner));
}
return context.getTupleFormulaManager().makeTuple(elements);
}

@Override
public Formula visitAggregateCmpExpression(AggregateCmpExpr expr) {
final Formula left = encode(expr.getLeft());
final Formula right = encode(expr.getRight());
final BooleanFormula eq = context.equal(left, right);
return switch (expr.getKind())
{
case EQ -> eq;
case NEQ -> context.getBooleanFormulaManager().not(eq);
};
}

@Override
public Formula visitExtractExpression(ExtractExpr extract) {
final TupleFormula inner = (TupleFormula) encode(extract.getOperand());
return context.getTupleFormulaManager().extract(inner, extract.getFieldIndex());
}

@Override
public Formula visitRegister(Register reg) {
String name = event == null ?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.dat3m.dartagnan.encoding.formulas;

import org.sosy_lab.java_smt.api.Formula;

import java.util.List;
import java.util.stream.Collectors;

/*
Implementation Note:
We implement JavaSMT's Formula interface so this appears like a normal formula,
however, it won't support many of JavaSMT's features like formula traversal.
*/
public class TupleFormula implements Formula {

final List<Formula> elements;

TupleFormula(List<Formula> elements) {
this.elements = elements;
}

@Override
public String toString() {
return elements.stream()
.map(Object::toString)
.collect(Collectors.joining(",", "{ ", " }"));
}

@Override
public int hashCode() {
return elements.hashCode();
}

@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else if (obj == null || obj.getClass() != this.getClass()) {
return false;
} else {
final TupleFormula other = (TupleFormula) obj;
return this.elements.equals(other.elements);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.dat3m.dartagnan.encoding.formulas;

import com.dat3m.dartagnan.encoding.EncodingContext;
import com.google.common.base.Preconditions;
import org.sosy_lab.java_smt.api.BooleanFormula;
import org.sosy_lab.java_smt.api.BooleanFormulaManager;
import org.sosy_lab.java_smt.api.Formula;

import java.util.ArrayList;
import java.util.List;


/*
Note: This class cannot actually create variables of tuple type and merely gives the illusion of
a proper tuple theory.
To simulate tuple variables, the user instead has to construct tuples of variables.
*/
public final class TupleFormulaManager {

private final EncodingContext context;

public TupleFormulaManager(EncodingContext context) {
this.context = context;

}

public BooleanFormula equal(TupleFormula x, TupleFormula y) {
Preconditions.checkArgument(x.elements.size() == y.elements.size());
final BooleanFormulaManager bmgr = context.getBooleanFormulaManager();
final List<BooleanFormula> enc = new ArrayList<>();
for (int i = 0; i < x.elements.size(); i++) {
enc.add(context.equal(x.elements.get(i), y.elements.get(i)));;
}
return bmgr.and(enc);
}

public Formula extract(TupleFormula f, int index) {
Preconditions.checkArgument(0 <= index && index < f.elements.size());
return f.elements.get(index);
}

public TupleFormula makeTuple(List<Formula> elements) {
return new TupleFormula(elements);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.dat3m.dartagnan.expression;

import com.dat3m.dartagnan.expression.aggregates.AggregateCmpExpr;
import com.dat3m.dartagnan.expression.aggregates.AggregateCmpOp;
import com.dat3m.dartagnan.expression.aggregates.ConstructExpr;
import com.dat3m.dartagnan.expression.aggregates.ExtractExpr;
import com.dat3m.dartagnan.expression.booleans.*;
import com.dat3m.dartagnan.expression.floats.*;
import com.dat3m.dartagnan.expression.integers.*;
import com.dat3m.dartagnan.expression.misc.ConstructExpr;
import com.dat3m.dartagnan.expression.misc.ExtractExpr;
import com.dat3m.dartagnan.expression.misc.GEPExpr;
import com.dat3m.dartagnan.expression.misc.ITEExpr;
import com.dat3m.dartagnan.expression.type.*;
Expand Down Expand Up @@ -271,6 +273,10 @@ public Expression makeExtract(int fieldIndex, Expression object) {
return new ExtractExpr(fieldIndex, object);
}

public Expression makeAggregateCmp(Expression x, AggregateCmpOp op, Expression y) {
return new AggregateCmpExpr(booleanType, x, op, y);
}

// -----------------------------------------------------------------------------------------------------------------
// Pointers

Expand Down Expand Up @@ -345,6 +351,8 @@ public Expression makeEQ(Expression leftOperand, Expression rightOperand) {
} else if (type instanceof FloatType) {
// TODO: Decide on a default semantics for float equality?
return makeFloatCmp(leftOperand, FloatCmpOp.OEQ, rightOperand);
} else if (type instanceof AggregateType) {
return makeAggregateCmp(leftOperand, AggregateCmpOp.EQ, rightOperand);
}
throw new UnsupportedOperationException("Equality not supported on type: " + type);
}
Expand All @@ -358,6 +366,8 @@ public Expression makeNEQ(Expression leftOperand, Expression rightOperand) {
} else if (type instanceof FloatType) {
// TODO: Decide on a default semantics for float equality?
return makeFloatCmp(leftOperand, FloatCmpOp.ONEQ, rightOperand);
} else if (type instanceof AggregateType) {
return makeAggregateCmp(leftOperand, AggregateCmpOp.NEQ, rightOperand);
}
throw new UnsupportedOperationException("Disequality not supported on type: " + type);
}
Expand Down Expand Up @@ -391,6 +401,8 @@ public Expression makeCompare(Expression x, ExpressionKind cmpOp, Expression y)
return makeIntCmp(x, intCmpOp, y);
} else if (cmpOp instanceof FloatCmpOp floatOp) {
return makeFloatCmp(x, floatOp, y);
} else if (cmpOp instanceof AggregateCmpOp aggrCmpOp) {
return makeAggregateCmp(x, aggrCmpOp, y);
}
throw new UnsupportedOperationException(String.format("Expression kind %s is no comparison operator.", cmpOp));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.dat3m.dartagnan.expression;

import com.dat3m.dartagnan.expression.aggregates.ConstructExpr;
import com.dat3m.dartagnan.expression.aggregates.ExtractExpr;
import com.dat3m.dartagnan.expression.booleans.BoolBinaryOp;
import com.dat3m.dartagnan.expression.booleans.BoolUnaryOp;
import com.dat3m.dartagnan.expression.floats.FloatSizeCast;
Expand All @@ -8,8 +10,6 @@
import com.dat3m.dartagnan.expression.integers.IntBinaryOp;
import com.dat3m.dartagnan.expression.integers.IntSizeCast;
import com.dat3m.dartagnan.expression.integers.IntUnaryOp;
import com.dat3m.dartagnan.expression.misc.ConstructExpr;
import com.dat3m.dartagnan.expression.misc.ExtractExpr;
import com.dat3m.dartagnan.expression.misc.GEPExpr;
import com.dat3m.dartagnan.expression.misc.ITEExpr;
import com.dat3m.dartagnan.program.Register;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.dat3m.dartagnan.expression;

import com.dat3m.dartagnan.expression.aggregates.AggregateCmpExpr;
import com.dat3m.dartagnan.expression.aggregates.ConstructExpr;
import com.dat3m.dartagnan.expression.aggregates.ExtractExpr;
import com.dat3m.dartagnan.expression.booleans.BoolBinaryExpr;
import com.dat3m.dartagnan.expression.booleans.BoolLiteral;
import com.dat3m.dartagnan.expression.booleans.BoolUnaryExpr;
import com.dat3m.dartagnan.expression.floats.*;
import com.dat3m.dartagnan.expression.integers.*;
import com.dat3m.dartagnan.expression.misc.ConstructExpr;
import com.dat3m.dartagnan.expression.misc.ExtractExpr;
import com.dat3m.dartagnan.expression.misc.GEPExpr;
import com.dat3m.dartagnan.expression.misc.ITEExpr;
import com.dat3m.dartagnan.program.Function;
Expand Down Expand Up @@ -46,6 +47,7 @@ public interface ExpressionVisitor<TRet> {
default TRet visitFloatLiteral(FloatLiteral lit) { return visitLeafExpression(lit); }

// =================================== Aggregates ===================================
default TRet visitAggregateCmpExpression(AggregateCmpExpr expr) { return visitBinaryExpression(expr); }
default TRet visitExtractExpression(ExtractExpr extract) { return visitUnaryExpression(extract); }
default TRet visitConstructExpression(ConstructExpr construct) { return visitExpression(construct); }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.dat3m.dartagnan.expression.aggregates;

import com.dat3m.dartagnan.expression.Expression;
import com.dat3m.dartagnan.expression.ExpressionVisitor;
import com.dat3m.dartagnan.expression.base.BinaryExpressionBase;
import com.dat3m.dartagnan.expression.type.AggregateType;
import com.dat3m.dartagnan.expression.type.BooleanType;
import com.dat3m.dartagnan.expression.utils.ExpressionHelper;

public final class AggregateCmpExpr extends BinaryExpressionBase<BooleanType, AggregateCmpOp> {

public AggregateCmpExpr(BooleanType type, Expression left, AggregateCmpOp kind, Expression right) {
super(type, kind, left, right);
ExpressionHelper.checkSameExpectedType(left, right, AggregateType.class);
}

@Override
public <T> T accept(ExpressionVisitor<T> visitor) {
return visitor.visitAggregateCmpExpression(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.dat3m.dartagnan.expression.aggregates;

import com.dat3m.dartagnan.expression.ExpressionKind;

public enum AggregateCmpOp implements ExpressionKind {
EQ, NEQ;

@Override
public String toString() {
return getSymbol();
}

@Override
public String getSymbol() {
return switch (this) {
case EQ -> "==";
case NEQ -> "!=";
};
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.dat3m.dartagnan.expression.misc;
package com.dat3m.dartagnan.expression.aggregates;

import com.dat3m.dartagnan.expression.Expression;
import com.dat3m.dartagnan.expression.ExpressionKind;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.dat3m.dartagnan.expression.misc;
package com.dat3m.dartagnan.expression.aggregates;

import com.dat3m.dartagnan.expression.Expression;
import com.dat3m.dartagnan.expression.ExpressionKind;
Expand Down
Loading

0 comments on commit c5468bf

Please sign in to comment.