Skip to content

Commit 6581ce1

Browse files
Merge pull request #5 from AnnotationsForAll/development
Version 0.2.0
2 parents f527285 + 4491377 commit 6581ce1

19 files changed

+503
-17
lines changed

WhyR Tests (Windows).launch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
1616
<listEntry value="4"/>
1717
</listAttribute>
18-
<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapping name=&amp;quot;New Mapping&amp;quot;&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapEntry memento=&amp;quot;&amp;amp;lt;?xml version=&amp;amp;quot;1.0&amp;amp;quot; encoding=&amp;amp;quot;UTF-8&amp;amp;quot; standalone=&amp;amp;quot;no&amp;amp;quot;?&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;amp;lt;mapEntry backendPath=&amp;amp;quot;\cygdrive\c\&amp;amp;quot; localPath=&amp;amp;quot;C:\&amp;amp;quot;/&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&amp;lt;/mapping&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.cdt.debug.core.containerType.mapping&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/>
18+
<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;sourceLookupDirector&gt;&#13;&#10;&lt;sourceContainers duplicates=&quot;false&quot;&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapping name=&amp;quot;/&amp;quot;&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapEntry memento=&amp;quot;&amp;amp;lt;?xml version=&amp;amp;quot;1.0&amp;amp;quot; encoding=&amp;amp;quot;UTF-8&amp;amp;quot; standalone=&amp;amp;quot;no&amp;amp;quot;?&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;amp;lt;mapEntry backendPath=&amp;amp;quot;\&amp;amp;quot; localPath=&amp;amp;quot;C:\cygwin&amp;amp;quot;/&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&amp;lt;/mapping&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.cdt.debug.core.containerType.mapping&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapping name=&amp;quot;New Mapping&amp;quot;&amp;gt;&amp;#13;&amp;#10;&amp;lt;mapEntry memento=&amp;quot;&amp;amp;lt;?xml version=&amp;amp;quot;1.0&amp;amp;quot; encoding=&amp;amp;quot;UTF-8&amp;amp;quot; standalone=&amp;amp;quot;no&amp;amp;quot;?&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;amp;lt;mapEntry backendPath=&amp;amp;quot;\cygdrive\c\&amp;amp;quot; localPath=&amp;amp;quot;C:\&amp;amp;quot;/&amp;amp;gt;&amp;amp;#13;&amp;amp;#10;&amp;quot;/&amp;gt;&amp;#13;&amp;#10;&amp;lt;/mapping&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.cdt.debug.core.containerType.mapping&quot;/&gt;&#13;&#10;&lt;container memento=&quot;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot; standalone=&amp;quot;no&amp;quot;?&amp;gt;&amp;#13;&amp;#10;&amp;lt;default/&amp;gt;&amp;#13;&amp;#10;&quot; typeId=&quot;org.eclipse.debug.core.containerType.default&quot;/&gt;&#13;&#10;&lt;/sourceContainers&gt;&#13;&#10;&lt;/sourceLookupDirector&gt;&#13;&#10;"/>
1919
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
2020
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
2121
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>

include/whyr/esc_why3.hpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* model.hpp
2+
* esc_why3.hpp
33
*
44
* Created on: Sep 15, 2016
55
* Author: jrobbins
@@ -44,6 +44,8 @@ namespace whyr {
4444
unordered_set<Type*> floatTypes;
4545
/// All the array types used.
4646
unordered_set<ArrayType*> arrayTypes;
47+
/// All the struct types used.
48+
unordered_set<StructType*> structTypes;
4749
/// All the functions called by other functions.
4850
unordered_set<Function*> funcsCalled;
4951
/// All the globals used by other functions.
@@ -152,6 +154,12 @@ namespace whyr {
152154
* Returns the constant name of a global variable.
153155
*/
154156
string getWhy3GlobalName(GlobalValue* global);
157+
/**
158+
* Returns the name of a field in a struct.
159+
* Be sure to add the preceding '.' before adding this to the output stream!
160+
* This function requires the module, because it might rely on debug info to make names.
161+
*/
162+
string getWhy3StructFieldName(AnnotatedModule* module, StructType* type, unsigned index);
155163

156164
/*
157165
*
@@ -244,6 +252,14 @@ namespace whyr {
244252
* Adds a theory for an array type.
245253
*/
246254
void addArrayType(ostream &out, AnnotatedModule* module, ArrayType* type);
255+
/**
256+
* Adds the base theory for all struct types.
257+
*/
258+
void addCommonStructType(ostream &out, AnnotatedModule* module);
259+
/**
260+
* Adds a theory for a struct type.
261+
*/
262+
void addStructType(ostream &out, AnnotatedModule* module, StructType* type);
247263
/**
248264
* Adds a theory for a derived type.
249265
* This function calls addArrayType, addPtrType, etc.

include/whyr/expressions.hpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ namespace whyr {
6969
LOGIC_EXPR_OPERAND,
7070
LOGIC_EXPR_SPECIAL_LLVM_CONST,
7171
LOGIC_EXPR_BADDR,
72+
LOGIC_EXPR_LLVM_STRUCT_CONST,
7273
};
7374

7475
/**
@@ -1072,6 +1073,26 @@ namespace whyr {
10721073

10731074
static bool classof(const LogicExpression* expr);
10741075
};
1076+
1077+
/**
1078+
* This constructs an LLVM struct out of potentially logical intermediate values.
1079+
*/
1080+
class LogicExpressionLLVMStructConstant : public LogicExpression {
1081+
protected:
1082+
list<LogicExpression*>* elements;
1083+
LogicType* retType;
1084+
public:
1085+
LogicExpressionLLVMStructConstant(LogicType* type, list<LogicExpression*>* elements, NodeSource* source = NULL);
1086+
list<LogicExpression*>* getElems();
1087+
1088+
virtual ~LogicExpressionLLVMStructConstant();
1089+
virtual string toString();
1090+
virtual LogicType* returnType();
1091+
virtual void checkTypes();
1092+
virtual void toWhy3(ostream &out, Why3Data &data);
1093+
1094+
static bool classof(const LogicExpression* expr);
1095+
};
10751096
}
10761097

10771098
#endif /* INCLUDE_WHYR_EXPRESSIONS_HPP_ */

include/whyr/whyr.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace whyr {
3939
class whyr_exception; class whyr_warning;
4040

4141
/// This is the WhyR version string. Update it for new releases.
42-
#define WHYR_VERSION "0.1.0"
42+
#define WHYR_VERSION "0.2.0"
4343

4444
/**
4545
* This structure keeps track of all the WhyR configuration settings.

src/esc_why3.cpp

Lines changed: 138 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ namespace whyr {
3131
} else if (type->isArrayTy()) {
3232
info.arrayTypes.insert(cast<ArrayType>(type));
3333
getTypeInfo(info, type->getArrayElementType());
34+
} else if (type->isStructTy()) {
35+
info.structTypes.insert(cast<StructType>(type));
36+
for (unsigned i = 0; i < type->getStructNumElements(); i++) {
37+
getTypeInfo(info, type->getStructElementType(i));
38+
}
3439
} else if (type->isVoidTy() || type->isLabelTy()) {
3540
// do nothing
3641
} else {
@@ -265,6 +270,17 @@ namespace whyr {
265270
return "Double";
266271
} else if (type->isArrayTy()) {
267272
return "Array" + getWhy3TheoryName(type->getArrayElementType()) + "_" + to_string(type->getArrayNumElements());
273+
} else if (type->isStructTy()) {
274+
if (type->getStructName().empty()) {
275+
ostringstream name;
276+
name << "Struct";
277+
for (unsigned i = 0; i < type->getStructNumElements(); i++) {
278+
name << "_" << getWhy3TheoryName(type->getStructElementType(i));
279+
}
280+
return name.str();
281+
} else {
282+
return "Type_" + getWhy3SafeName(string(type->getStructName().data()));
283+
}
268284
} else {
269285
throw llvm_exception("Unknown type in LLVM input");
270286
}
@@ -281,6 +297,17 @@ namespace whyr {
281297
return "double";
282298
} else if (type->isArrayTy()) {
283299
return "a" + getWhy3TypeName(type->getArrayElementType()) + "_" + to_string(type->getArrayNumElements());
300+
} else if (type->isStructTy()) {
301+
if (type->getStructName().empty()) {
302+
ostringstream name;
303+
name << "struct";
304+
for (unsigned i = 0; i < type->getStructNumElements(); i++) {
305+
name << "_" << getWhy3TypeName(type->getStructElementType(i));
306+
}
307+
return name.str();
308+
} else {
309+
return "type_" + getWhy3SafeName(string(type->getStructName().data()));
310+
}
284311
} else {
285312
throw llvm_exception("Unknown type in LLVM input");
286313
}
@@ -370,6 +397,10 @@ namespace whyr {
370397
return string("global_") + getWhy3SafeName(global->getName().data());
371398
}
372399

400+
string getWhy3StructFieldName(AnnotatedModule* module, StructType* type, unsigned index) {
401+
return getWhy3TypeName(type) + "_field_" + to_string(index);
402+
}
403+
373404
// ABOUT CustomTruncate BELOW:
374405
// There is a bug in Alt-Ergo that causes all proofs to run forever when Why3's real.Truncate theory is imported.
375406
// We add a custom truncation theory that is more limited than Why3's. This reduces the impact of the bug, but does not eliminate it.
@@ -424,6 +455,9 @@ end
424455
for (unordered_set<ArrayType*>::iterator ii = data.info->arrayTypes.begin(); ii != data.info->arrayTypes.end(); ii++) {
425456
out << " use import " << getWhy3TheoryName(*ii) << endl;
426457
}
458+
for (unordered_set<StructType*>::iterator ii = data.info->structTypes.begin(); ii != data.info->structTypes.end(); ii++) {
459+
out << " use import " << getWhy3TheoryName(*ii) << endl;
460+
}
427461
if (data.info->usesAlloc) {
428462
out << " use import Alloc" << endl;
429463
}
@@ -507,6 +541,15 @@ end
507541
addOperand(out, module, cc->getElementAsConstant(i), func);
508542
out << "]";
509543
}
544+
} else if (isa<ConstantStruct>(operand)) {
545+
ConstantStruct* cc = cast<ConstantStruct>(operand);
546+
out << "{ ";
547+
for (unsigned i = 0; i < operand->getType()->getStructNumElements(); i++) {
548+
out << getWhy3TheoryName(operand->getType()) << "." << getWhy3StructFieldName(module, cc->getType(), i) << " = ";
549+
addOperand(out, module, cc->getAggregateElement(i));
550+
out << "; ";
551+
}
552+
out << "}";
510553
} else if (isa<ConstantAggregateZero>(operand)) {
511554
if (operand->getType()->isArrayTy()) {
512555
Constant* value = cast<ConstantAggregateZero>(operand)->getSequentialElement();
@@ -517,6 +560,15 @@ end
517560
addOperand(out, module, value, func);
518561
out << "]";
519562
}
563+
} else if (operand->getType()->isStructTy()) {
564+
ConstantAggregateZero* cc = cast<ConstantAggregateZero>(operand);
565+
out << "{ ";
566+
for (unsigned i = 0; i < operand->getType()->getStructNumElements(); i++) {
567+
out << getWhy3TheoryName(operand->getType()) << "." << getWhy3StructFieldName(module, cast<StructType>(operand->getType()), i) << " = ";
568+
addOperand(out, module, cc->getStructElement(i));
569+
out << "; ";
570+
}
571+
out << "}";
520572
} else {
521573
throw type_exception("Instantiation of aggregate zero of type '" + LogicTypeLLVM(operand->getType()).toString() + "' currently unsupported");
522574
}
@@ -945,6 +997,11 @@ end
945997
addOperand(out, func->getModule(), ii->get(), func);
946998
out << "))";
947999
currentType = currentType->getArrayElementType();
1000+
} else if (currentType->isStructTy()) {
1001+
unsigned index = cast<ConstantInt>(ii->get())->getLimitedValue();
1002+
unsigned offset = func->getModule()->rawIR()->getDataLayout().getStructLayout(cast<StructType>(currentType))->getElementOffsetInBits(index);
1003+
out << offset;
1004+
currentType = currentType->getStructElementType(index);
9481005
}
9491006
}
9501007
out << ")))";
@@ -956,8 +1013,15 @@ end
9561013
addOperand(out, func->getModule(), inst, func);
9571014
out << " = ";
9581015
addOperand(out, func->getModule(), exInst->getAggregateOperand(), func);
1016+
Type* operandType = exInst->getAggregateOperand()->getType();
9591017
for (ExtractValueInst::idx_iterator ii = exInst->idx_begin(); ii != exInst->idx_end(); ii++) {
960-
out << "[" << *ii << "]";
1018+
if (operandType->isArrayTy()) {
1019+
out << "[" << *ii << "]";
1020+
operandType = operandType->getArrayElementType();
1021+
} else if (operandType->isStructTy()) {
1022+
out << "." << getWhy3StructFieldName(func->getModule(), cast<StructType>(operandType), *ii);
1023+
operandType = operandType->getStructElementType(*ii);
1024+
}
9611025
}
9621026
break;
9631027
}
@@ -967,19 +1031,48 @@ end
9671031
addOperand(out, func->getModule(), inst, func);
9681032
out << " = ";
9691033

970-
int i = 0;
1034+
int i = 0; Type* operandType = insInst->getAggregateOperand()->getType();
9711035
for (InsertValueInst::idx_iterator ii = insInst->idx_begin(); ii != insInst->idx_end(); ii++) {
972-
addOperand(out, func->getModule(), insInst->getAggregateOperand(), func);
973-
for (int j = 0; j < i; j++) {
1036+
if (operandType->isStructTy()) {
1037+
out << "{";
1038+
}
1039+
addOperand(out, func->getModule(), insInst->getAggregateOperand(), func);
1040+
1041+
Type* operandType2 = insInst->getAggregateOperand()->getType();
1042+
for (int j = 0; j < i; j++) {
1043+
if (operandType2->isArrayTy()) {
9741044
out << "[" << *(insInst->idx_begin()+j) << "]";
1045+
operandType2 = operandType2->getArrayElementType();
1046+
} else if (operandType2->isStructTy()) {
1047+
out << "." << getWhy3StructFieldName(func->getModule(), cast<StructType>(operandType2), *(insInst->idx_begin()+j));
1048+
operandType2 = operandType2->getStructElementType(*(insInst->idx_begin()+j));
9751049
}
1050+
}
1051+
1052+
if (operandType->isArrayTy()) {
9761053
out << "[" << *ii << " <- ";
1054+
operandType = operandType->getArrayElementType();
1055+
} else if (operandType->isStructTy()) {
1056+
out << " with " << getWhy3TheoryName(operandType) << "." << getWhy3StructFieldName(func->getModule(), cast<StructType>(operandType), *ii) << " = ";
1057+
operandType = operandType->getStructElementType(*ii);
1058+
}
1059+
9771060
i++;
9781061
}
1062+
1063+
Type* operandType3 = insInst->getAggregateOperand()->getType();
9791064
addOperand(out, func->getModule(), insInst->getInsertedValueOperand(), func);
1065+
string ending;
9801066
for (int j = 0; j < i; j++) {
981-
out << "]";
1067+
if (operandType3->isArrayTy()) {
1068+
ending = "]" + ending;
1069+
operandType3 = operandType3->getArrayElementType();
1070+
} else if (operandType3->isStructTy()) {
1071+
ending = ";}" + ending;
1072+
operandType3 = operandType3->getStructElementType(*(insInst->idx_begin()+j));
1073+
}
9821074
}
1075+
out << ending;
9831076
break;
9841077
}
9851078
case Instruction::OtherOps::ICmp: {
@@ -1786,11 +1879,39 @@ end
17861879
out << "end" << endl << endl;
17871880
}
17881881

1882+
void addCommonStructType(ostream &out, AnnotatedModule* module) {
1883+
// do nothing. Currently, no memory models require we have any common code.
1884+
}
1885+
1886+
void addStructType(ostream &out, AnnotatedModule* module, StructType* type) {
1887+
// find the imports we need
1888+
unordered_set<Type*> imports;
1889+
for (unsigned i = 0; i < type->getStructNumElements(); i++) {
1890+
imports.insert(type->getStructElementType(i));
1891+
}
1892+
1893+
// add the theory
1894+
out << "theory " << getWhy3TheoryName(type) << endl;
1895+
for (unordered_set<Type*>::iterator ii = imports.begin(); ii != imports.end(); ii++) {
1896+
out << " use import " << getWhy3TheoryName(*ii) << endl;
1897+
}
1898+
out << " constant size : int = " << module->rawIR()->getDataLayout().getStructLayout(type)->getSizeInBits() << endl;
1899+
out << " type " << getWhy3TypeName(type) << " = {" << endl;
1900+
for (unsigned i = 0; i < type->getStructNumElements(); i++) {
1901+
Type* elem = type->getStructElementType(i);
1902+
out << " " << getWhy3StructFieldName(module, type, i) << " : " << getWhy3FullName(elem) << ";" << endl;
1903+
}
1904+
out << " }" << endl;
1905+
out << "end" << endl << endl;
1906+
}
1907+
17891908
void addDerivedType(ostream &out, AnnotatedModule* module, Type* type) {
17901909
if (type->isPointerTy()) {
17911910
addPtrType(out, module, cast<PointerType>(type));
17921911
} else if (type->isArrayTy()) {
17931912
addArrayType(out, module, cast<ArrayType>(type));
1913+
} else if (type->isStructTy()) {
1914+
addStructType(out, module, cast<StructType>(type));
17941915
}
17951916
}
17961917

@@ -1987,6 +2108,7 @@ end
19872108
unordered_set<Type*> notSeen;
19882109
notSeen.insert(info.ptrTypes.begin(), info.ptrTypes.end());
19892110
notSeen.insert(info.arrayTypes.begin(), info.arrayTypes.end());
2111+
notSeen.insert(info.structTypes.begin(), info.structTypes.end());
19902112

19912113
// while there's still more nodes in need of calculation; that is, if the state changed since last iteration...
19922114
bool changed;
@@ -2006,6 +2128,13 @@ end
20062128
if (notSeen.find((*ii)->getArrayElementType()) != notSeen.end()) {
20072129
allSeen = false;
20082130
}
2131+
} else if ((*ii)->isStructTy()) {
2132+
for (unsigned i = 0; i < (*ii)->getStructNumElements(); i++) {
2133+
if (notSeen.find((*ii)->getStructElementType(i)) != notSeen.end()) {
2134+
allSeen = false;
2135+
break;
2136+
}
2137+
}
20092138
}
20102139

20112140
if (allSeen) {
@@ -2135,6 +2264,10 @@ end
21352264
addCommonArrayType(out, module);
21362265
}
21372266

2267+
if (!info.structTypes.empty()) {
2268+
addCommonStructType(out, module);
2269+
}
2270+
21382271
list<Type*> types;
21392272
getCorrectDerivedTypeOrder(types, info, module);
21402273

0 commit comments

Comments
 (0)