-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory Datatype and Pointer type #550
Changes from all commits
70482e9
84452ae
c964d0b
1527ead
5e9451e
7526048
830ef6e
4b966ce
b8f37c0
9610249
a6c14fd
a704aa6
9d97bc9
7134ff0
5f58ca4
59ca125
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#include <assert.h> | ||
#include <stdlib.h> | ||
int __VERIFIER_nondet_int(void); | ||
typedef unsigned short u16; | ||
typedef unsigned int u32; | ||
|
||
u16 get_mistyped(u16* array) | ||
{ | ||
return array[0]; | ||
} | ||
|
||
u16 get_offset(u16* array) | ||
{ | ||
return array[1]; | ||
} | ||
|
||
u32 get_misaligned(u16* array) | ||
{ | ||
u32* interpreted = (u32*)((void*)(array + 1)); | ||
return *interpreted; | ||
} | ||
|
||
int main() | ||
{ | ||
u32* array = (u32*) malloc(2 * sizeof(u32)); | ||
u32 value = __VERIFIER_nondet_int(); | ||
array[1] = array[0] = value; | ||
u16 easy = get_mistyped((u16*)((void*)array)); | ||
assert(easy == (value & 0xffff)); | ||
u16 medium = get_offset((u16*)((void*)array)); | ||
assert(medium == (value >> 16)); | ||
u32 hard = get_misaligned((u16*)((void*)array)); | ||
assert(hard == ((value << 16) | (value >> 16))); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,10 @@ | |
import com.dat3m.dartagnan.expression.*; | ||
import com.dat3m.dartagnan.expression.op.IOpUn; | ||
import com.dat3m.dartagnan.expression.processing.ExpressionVisitor; | ||
import com.dat3m.dartagnan.expression.type.IntegerType; | ||
import com.dat3m.dartagnan.expression.type.PointerType; | ||
import com.dat3m.dartagnan.expression.type.Type; | ||
import com.dat3m.dartagnan.expression.type.TypeFactory; | ||
import com.dat3m.dartagnan.program.Register; | ||
import com.dat3m.dartagnan.program.event.core.Event; | ||
import com.dat3m.dartagnan.program.memory.Location; | ||
|
@@ -12,6 +15,9 @@ | |
import org.sosy_lab.java_smt.api.NumeralFormula.IntegerFormula; | ||
|
||
import java.math.BigInteger; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.IntStream; | ||
|
||
import static com.google.common.base.Preconditions.checkState; | ||
import static com.google.common.base.Verify.verify; | ||
|
@@ -124,6 +130,10 @@ public Formula visit(IExprBin iBin) { | |
case MOD: | ||
return integerFormulaManager.modulo(i1, i2); | ||
case AND: | ||
// optimized encoding for (x bitand 1), (x bitand 3), etc. | ||
if (iBin.getRHS() instanceof IValue rightValue && isAllOnes(rightValue.getValue())) { | ||
return integerFormulaManager.modulo(i1, integerFormulaManager.makeNumber(rightValue.getValue().add(BigInteger.ONE))); | ||
} | ||
bitvectorFormulaManager = bitvectorFormulaManager(); | ||
return bitvectorFormulaManager.toIntegerFormula( | ||
bitvectorFormulaManager.and( | ||
|
@@ -225,6 +235,11 @@ public Formula visit(IExprBin iBin) { | |
} | ||
} | ||
|
||
private static boolean isAllOnes(BigInteger value) { | ||
int length = value.bitLength(); | ||
return value.signum() != -1 && IntStream.range(0, length).allMatch(value::testBit); | ||
} | ||
|
||
@Override | ||
public Formula visit(IExprUn iUn) { | ||
Formula inner = encode(iUn.getInner()); | ||
|
@@ -249,19 +264,8 @@ public Formula visit(IExprUn iUn) { | |
} | ||
//TODO If narrowing, constrain the value. | ||
return inner; | ||
} else { | ||
final int bitWidth = iUn.getType().getBitWidth(); | ||
if (inner instanceof IntegerFormula number) { | ||
return bitvectorFormulaManager().makeBitvector(bitWidth, number); | ||
} | ||
if (inner instanceof BitvectorFormula number) { | ||
int innerBitWidth = bitvectorFormulaManager().getLength(number); | ||
if (innerBitWidth < bitWidth) { | ||
return bitvectorFormulaManager().extend(number, bitWidth - innerBitWidth, signed); | ||
} | ||
return bitvectorFormulaManager().extract(number, bitWidth - 1, 0); | ||
} | ||
} | ||
return applyBitWidth(inner, iUn.getType().getBitWidth(), signed); | ||
} | ||
case CTLZ -> { | ||
if (inner instanceof BitvectorFormula bv) { | ||
|
@@ -319,4 +323,80 @@ public Formula visit(Location location) { | |
checkState(event == null, "Cannot evaluate %s at event %s.", location, event); | ||
return context.lastValue(location.getMemoryObject(), location.getOffset()); | ||
} | ||
|
||
@Override | ||
public Formula visit(NullPointer constant) { | ||
return context.useIntegers ? integerFormulaManager().makeNumber(0) : | ||
bitvectorFormulaManager().makeBitvector(64, 0); | ||
} | ||
|
||
@Override | ||
public Formula visit(GEPExpression gep) { | ||
final TypeFactory types = TypeFactory.getInstance(); | ||
final List<Expression> expressions = gep.getOffsetExpressions(); | ||
final Formula base = gep.getBaseExpression().accept(this); | ||
final boolean integer = base instanceof IntegerFormula; | ||
verify(integer || base instanceof BitvectorFormula, "%s cannot represent pointers", base); | ||
final IntegerFormulaManager integerFormulaManager = integer ? integerFormulaManager() : null; | ||
final BitvectorFormulaManager bitvectorFormulaManager = integer ? null : bitvectorFormulaManager(); | ||
final List<IntegerFormula> integers = integer ? new ArrayList<>(List.of((IntegerFormula) base)) : null; | ||
final List<BitvectorFormula> bitvectors = new ArrayList<>(); | ||
final int length = integer ? 0 : bitvectorFormulaManager.getLength((BitvectorFormula) base); | ||
final List<Integer> constants = expressions.stream() | ||
.map(x -> x instanceof IValue v ? v.getValueAsInt() : 1) | ||
.toList(); | ||
final List<Integer> byteCounts = types.getByteCounts(gep.getIndexingType(), constants); | ||
for (int i = 0; i < expressions.size(); i++) { | ||
final Expression offset = expressions.get(i); | ||
final IValue constant = offset instanceof IValue v ? v : null; | ||
if (constant != null && constant.isZero()) { | ||
continue; | ||
} | ||
// only encode offset expressions if not constant. | ||
// byteCounts already contains constant offset values. | ||
final Formula count = constant != null ? null : offset.accept(this); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why this distinction is important. I think the method is a lot more complicated than it needs to be. Also, seeing all this distinction between integers and bitvectors, I think it might be a good idea to have a |
||
final int byteCount = byteCounts.get(i); | ||
if (integer) { | ||
final IntegerFormula coefficient = integerFormulaManager.makeNumber(byteCount); | ||
integers.add(count == null ? coefficient : integerFormulaManager.multiply(coefficient, | ||
count instanceof IntegerFormula f ? f : | ||
bitvectorFormulaManager().toIntegerFormula((BitvectorFormula) count, false))); | ||
} else { | ||
final BitvectorFormula coefficient = bitvectorFormulaManager.makeBitvector(byteCount, length); | ||
bitvectors.add(count == null ? coefficient : bitvectorFormulaManager.multiply(coefficient, | ||
count instanceof BitvectorFormula f ? f : | ||
bitvectorFormulaManager.makeBitvector(length, (IntegerFormula) count))); | ||
} | ||
} | ||
return integer ? integerFormulaManager.sum(integers) : | ||
bitvectors.stream().reduce((BitvectorFormula) base, bitvectorFormulaManager::add); | ||
} | ||
|
||
@Override | ||
public Formula visit(PointerCast cast) { | ||
final Type targetType = cast.getType(); | ||
final Formula inner = cast.getInnerExpression().accept(this); | ||
verify(targetType instanceof IntegerType || targetType instanceof PointerType, "Invalid type for %s", cast); | ||
if (context.useIntegers || targetType instanceof IntegerType t && t.isMathematical()) { | ||
return inner; | ||
} | ||
final int bitWith = targetType instanceof IntegerType t ? t.getBitWidth() : ((PointerType) targetType).getBitWidth(); | ||
return applyBitWidth(inner, bitWith, cast.isSigned()); | ||
} | ||
|
||
private Formula applyBitWidth(Formula inner, int bitWidth, boolean signed) { | ||
if (inner instanceof BooleanFormula) { | ||
return inner; | ||
} | ||
if (inner instanceof IntegerFormula number) { | ||
return bitvectorFormulaManager().makeBitvector(bitWidth, number); | ||
} | ||
verify(inner instanceof BitvectorFormula); | ||
final var number = (BitvectorFormula) inner; | ||
final int innerBitWidth = bitvectorFormulaManager().getLength(number); | ||
if (innerBitWidth < bitWidth) { | ||
return bitvectorFormulaManager().extend(number, bitWidth - innerBitWidth, signed); | ||
} | ||
return bitvectorFormulaManager().extract(number, bitWidth - 1, 0); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use size of the pointer type rather than the hardcoded value 64.