Skip to content
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

opaque pointer support (type inference) for c #1323

Merged
merged 77 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
f3761ea
find type assert
jumormt Jan 6, 2024
18970cb
add assertion checking num field
jumormt Jan 6, 2024
40b8def
fix indirect call does not have called func
jumormt Jan 6, 2024
19fc337
add type check option
jumormt Jan 8, 2024
f57fc37
add type check option && first version of collect types
jumormt Jan 8, 2024
f38e36a
add "store (value operand) <- gep" rule
jumormt Jan 8, 2024
9c8d789
add inter-procedural rule
jumormt Jan 8, 2024
8e13066
add some comments
jumormt Jan 8, 2024
5144f86
fix call base bug
jumormt Jan 8, 2024
fae7e57
add callsite to callee inference
jumormt Jan 8, 2024
8934f21
do not propagate to declare func
jumormt Jan 8, 2024
4fcfafe
fix vararg
jumormt Jan 8, 2024
14efeb5
refactor
jumormt Jan 9, 2024
27fb0ea
use hash map to cache results
jumormt Jan 9, 2024
2e6d12d
refine
jumormt Jan 9, 2024
6f62afb
iterative memorizing dfs
jumormt Jan 9, 2024
7279bee
iterative memorizing dfs
jumormt Jan 9, 2024
5edb5f2
fix bug
jumormt Jan 9, 2024
3138be2
add comments and fix bug for c++20
jumormt Jan 9, 2024
7cad38a
fix deadloop
jumormt Jan 9, 2024
cc5f2aa
fix deadloop
jumormt Jan 9, 2024
28b941e
refine coding
jumormt Jan 9, 2024
f1cab1a
refactor inferTypeOfHeapObjOrStaticObj
jumormt Jan 9, 2024
8c838bf
refactor inferTypeOfHeapObjOrStaticObj
jumormt Jan 9, 2024
87b671c
add a new typeinference class
jumormt Jan 10, 2024
d38f373
refactor
jumormt Jan 10, 2024
076ca38
fix bug
jumormt Jan 10, 2024
8d15f3f
add debug support
jumormt Jan 10, 2024
cf89135
add default type
jumormt Jan 10, 2024
4712b6b
move getptrelementtype to test
jumormt Jan 10, 2024
550ebb1
move getClassNameOfThisPtr to chg builder and add diff test
jumormt Jan 10, 2024
3063af8
remove getelementptr in SVFExt and llvmmodule
jumormt Jan 10, 2024
376d729
return max field for ptr type
jumormt Jan 11, 2024
fd0e4d4
default for heap is i8
jumormt Jan 11, 2024
9a89761
for param of ext api, first find source and then derive type
jumormt Jan 11, 2024
868e023
refactor getOrInferLLVMObjType
jumormt Jan 11, 2024
9f45f32
skip global function value -> callsite when forward infer type
jumormt Jan 11, 2024
578a379
update comment
jumormt Jan 11, 2024
ef078d7
fix passing a function as a param
jumormt Jan 11, 2024
8889fd0
rename typesizedifftest, remove unnecessary getfirstcast
jumormt Jan 12, 2024
ef8ccd1
remove getptrelement and getpointerto in svf/*
jumormt Jan 12, 2024
058f626
ptr in svf main
jumormt Jan 12, 2024
b13b37f
thisptr class name prepare
jumormt Jan 12, 2024
8639716
infer type based on c++ constructor
jumormt Jan 13, 2024
ec19b79
add comments
jumormt Jan 13, 2024
1d33ec4
getOrInferThisPtrClassName update
jumormt Jan 13, 2024
d17948b
refine type diff test
jumormt Jan 14, 2024
5f35694
refine type diff test
jumormt Jan 14, 2024
1d52b55
fix indirect call passing
jumormt Jan 14, 2024
f854a53
separate cpp source and allocation
jumormt Jan 15, 2024
1857464
refactor iscpp constructor
jumormt Jan 15, 2024
a243d10
update
jumormt Jan 15, 2024
8efc471
for c++ fw type inference, consider constructor for now
jumormt Jan 15, 2024
04d89a8
update
jumormt Jan 15, 2024
f3a4f8e
delete c++
jumormt Jan 15, 2024
6cf0f73
delete c++
jumormt Jan 15, 2024
146fbd8
update based on comments
jumormt Jan 16, 2024
ab8963d
rename
jumormt Jan 16, 2024
ab04330
refactor
jumormt Jan 17, 2024
0aeeacb
reformat
jumormt Jan 17, 2024
76cdfc3
refactor
jumormt Jan 17, 2024
22dd059
move typeinference to LLVMModuleSet
jumormt Jan 21, 2024
12b3431
release llvm modouleset immediately after svfir is built
jumormt Jan 21, 2024
7352b98
remove static method
jumormt Jan 21, 2024
c363ad3
fix ander diff test
jumormt Jan 21, 2024
6ffb132
fix saber
jumormt Jan 21, 2024
3cdc19e
bytesize default 1
jumormt Jan 24, 2024
37f43f2
fix wpa release llvm module
jumormt Jan 24, 2024
8118f53
fix mac CI
jumormt Jan 24, 2024
eb34d0a
delete cpp
jumormt Jan 24, 2024
a176ca5
move release llvmmoduleset to the end of main
jumormt Jan 24, 2024
63aa46e
merge SVF master into opaque c
jumormt Jan 24, 2024
4d2f565
rename typeinference to objtypeinference
jumormt Jan 25, 2024
82f2e31
enable type check by default
jumormt Jan 25, 2024
9e61dd0
refactor
jumormt Jan 25, 2024
b0980a0
rename cpp and add ctest type infer CI
jumormt Jan 25, 2024
d620c42
add some assertions for npd
jumormt Jan 25, 2024
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
Prev Previous commit
Next Next commit
refactor
  • Loading branch information
jumormt committed Jan 24, 2024
commit 14efeb59bc38ddc4090dc456aa280255fc2e110f
9 changes: 0 additions & 9 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,21 +129,12 @@ static inline Type* getPtrElementType(const PointerType* pty)
/// Return size of this object based on LLVM value
u32_t getNumOfElements(const Type* ety);

/// Validate type inference
void validateTypeCheck(const CallBase* cs);

/// Select the largest (conservative) type from all types
const Type* selectLargestType(Set<const Type*>& objTys);

u32_t getArgNoInCallInst(const CallInst* callInst, const Value* arg);

/// Collect all possible types of a heap allocation site
void collectAllHeapObjTypes(Set<const Type*>& types, const CallBase* heapAlloc);

/// Get the reference type of heap/static object from an allocation site.
//@{
const Type *inferTypeOfHeapObjOrStaticObj(const Instruction* inst);
//@}


/// Return true if this value refers to a object
Expand Down
14 changes: 14 additions & 0 deletions svf-llvm/include/SVF-LLVM/SymbolTableBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class SymbolTableBuilder
friend class SVFIRBuilder;
private:
SymbolTableInfo* symInfo;
Map<const Value*, Set<const Type*>> valueTypes; // value types cache

public:
/// Constructor
Expand Down Expand Up @@ -82,6 +83,19 @@ class SymbolTableBuilder
void handleCE(const Value* val);
// @}


/// Collect all possible types of a heap allocation site
void forwardCollectAllHeapObjTypes(Set<const Type*>& types, const CallBase* heapAlloc);

/// Get the reference type of heap/static object from an allocation site.
//@{
const Type *inferTypeOfHeapObjOrStaticObj(const Instruction* inst);
//@}


/// Validate type inference
void validateTypeCheck(const CallBase* cs);

/// Create an objectInfo based on LLVM value
ObjTypeInfo* createObjTypeInfo(const Value* val);

Expand Down
207 changes: 0 additions & 207 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,7 @@ const std::string vfunPreLabel = "_Z";
const std::string clsName = "class.";
const std::string structName = "struct.";
const std::string vtableType = "(...)**";
const std::string TYPEMALLOC = "TYPE_MALLOC";

#define ABORT_MSG(reason) \
do \
{ \
SVFUtil::errs() << __FILE__ << ':' << __LINE__ << ": " << reason \
<< '\n'; \
abort(); \
} while (0)
#define ABORT_IFNOT(condition, reason) \
do \
{ \
if (!(condition)) \
ABORT_MSG(reason); \
} while (0)

#define TYPE_DEBUG 0 /* Turn this on if you're debugging type inference */


/*!
Expand Down Expand Up @@ -387,121 +371,6 @@ u32_t LLVMUtil::getArgNoInCallInst(const CallInst *callInst, const Value *arg) {
return std::distance(callInst->arg_begin(), it);
}

/*!
* Collect all possible types of a heap allocation site
* @param types the derived result
* @param heapAlloc the heap allocation site
*/
void LLVMUtil::collectAllHeapObjTypes(Set<const Type*>& types, const CallBase* heapAlloc) {
assert(heapAlloc && "not an instruction?");
FIFOWorkList<const Value*> valueWorkList;
Set<const Value*> visited;
valueWorkList.push(heapAlloc);
visited.insert(heapAlloc);
auto pushIntoWorklist = [&visited, &valueWorkList](const auto& pUser) {
if (!visited.count(pUser)) {
visited.insert(pUser);
valueWorkList.push(pUser);
}
};
while (!valueWorkList.empty()) {
const Value *curValue = valueWorkList.pop();
for (const auto &it : curValue->uses())
{
if (LoadInst *loadInst = SVFUtil::dyn_cast<LoadInst>(it.getUser())) {
/*
* infer based on load, e.g.,
%call = call i8* malloc()
%1 = bitcast i8* %call to %struct.MyStruct*
%q = load %struct.MyStruct, %struct.MyStruct* %1
*/
types.insert(loadInst->getType());
} else if (StoreInst *storeInst = SVFUtil::dyn_cast<StoreInst>(it.getUser())) {
if (storeInst->getPointerOperand() == curValue) {
/*
* infer based on store (pointer operand), e.g.,
%call = call i8* malloc()
%1 = bitcast i8* %call to %struct.MyStruct*
store %struct.MyStruct .., %struct.MyStruct* %1
*/
types.insert(storeInst->getValueOperand()->getType());
} else {
/*
* propagate across store (value operand) and load
%call = call i8* malloc()
store i8* %call, i8** %p
%q = load i8*, i8** %p
..infer based on %q..
*/
for (const auto &nit : storeInst->getPointerOperand()->uses()) {
if (SVFUtil::isa<LoadInst>(nit.getUser())) {
pushIntoWorklist(nit.getUser());
}
}
/*
* infer based on store (value operand) <- gep (result element)
%call1 = call i8* @TYPE_MALLOC(i32 noundef 16, i32 noundef 2), !dbg !39
%2 = bitcast i8* %call1 to %struct.MyStruct*, !dbg !41
%3 = load %struct.MyStruct*, %struct.MyStruct** %p, align 8, !dbg !42
%next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %3, i32 0, i32 1, !dbg !43
store %struct.MyStruct* %2, %struct.MyStruct** %next, align 8, !dbg !44
*/
if (GetElementPtrInst *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(
storeInst->getPointerOperand())) {
types.insert(gepInst->getSourceElementType());
}
}
} else if (GetElementPtrInst *gepInst = SVFUtil::dyn_cast<GetElementPtrInst>(it.getUser())) {
if (gepInst->getPointerOperand() == curValue) {
/*
* infer based on gep (pointer operand)
%call = call i8* malloc()
%1 = bitcast i8* %call to %struct.MyStruct*
%next = getelementptr inbounds %struct.MyStruct, %struct.MyStruct* %1, i32 0..
*/
types.insert(gepInst->getSourceElementType());
}
} else if (BitCastInst *bitcast = SVFUtil::dyn_cast<BitCastInst>(it.getUser())) {
// continue on bitcast
pushIntoWorklist(bitcast);
} else if (ReturnInst *retInst = SVFUtil::dyn_cast<ReturnInst>(it.getUser())) {
/*;
* propagate from return to caller
Function Attrs: noinline nounwind optnone uwtable
define dso_local i8* @malloc_wrapper() #0 !dbg !22 {
entry:
%call = call i8* @malloc(i32 noundef 16), !dbg !25
ret i8* %call, !dbg !26
}
%call = call i8* @malloc_wrapper()
..infer based on %call..
*/
for(const auto& callsite: retInst->getFunction()->uses()) {
if (CallInst* callInst = SVFUtil::dyn_cast<CallInst>(callsite.getUser())) {
pushIntoWorklist(callInst);
}
}
} else if (CallInst* callInst = SVFUtil::dyn_cast<CallInst>(it.getUser())) {
/*;
* propagate from callsite to callee
%call = call i8* @malloc(i32 noundef 16)
%0 = bitcast i8* %call to %struct.Node*, !dbg !43
call void @foo(%struct.Node* noundef %0), !dbg !45

define dso_local void @foo(%struct.Node* noundef %param) #0 !dbg !22 {...}
..infer based on the formal param %param..
*/
u32_t pos = getArgNoInCallInst(callInst, curValue);
if (Function *calleeFunc = callInst->getCalledFunction()) {
// for variable argument, conservatively collect all params
if(calleeFunc->isVarArg()) pos = 0;
if(!calleeFunc->isDeclaration())
pushIntoWorklist(calleeFunc->getArg(pos));
}
}
}
}
}

/*!
* Return size of this Object
Expand All @@ -520,35 +389,6 @@ u32_t LLVMUtil::getNumOfElements(const Type* ety)
return numOfFields;
}

/*!
* Validate type inference
* @param cs : stub malloc function with element number label
*/
void LLVMUtil::validateTypeCheck(const CallBase *cs) {
if (const Function* func = cs->getCalledFunction())
{
if (func->getName().find(TYPEMALLOC) != std::string::npos)
{
Set<const Type*> types;
collectAllHeapObjTypes(types, cs);
const Type *pType = selectLargestType(types);
ABORT_IFNOT(pType, "fail to infer any types:" +
dumpValue(cs) + getSourceLoc(cs) + "\n");
ConstantInt* pInt =
SVFUtil::dyn_cast<llvm::ConstantInt>(cs->getOperand(1));
assert(pInt && "the second argument is a integer");
if (getNumOfElements(pType) >= pInt->getZExtValue())
SVFUtil::outs() << SVFUtil::sucMsg("\t SUCCESS :") <<
dumpValue(cs) << getSourceLoc(cs) << SVFUtil::pasMsg(" TYPE: ") << dumpType(pType) << "\n";
else
{
SVFUtil::errs() << SVFUtil::errMsg("\t FAILURE :") <<
dumpValue(cs) << getSourceLoc(cs) << " TYPE: " << dumpType(pType) << "\n";
ABORT_IFNOT(false, "test case failed!");
}
}
}
}

const Type* LLVMUtil::selectLargestType(Set<const Type*>& objTys) {
if(objTys.empty()) return nullptr;
Expand All @@ -563,53 +403,6 @@ const Type* LLVMUtil::selectLargestType(Set<const Type*>& objTys) {
return *largestElement.second.begin();
}

/*!
* Return the type of the object from a heap allocation
*/
const Type* LLVMUtil::inferTypeOfHeapObjOrStaticObj(const Instruction *inst)
{
const PointerType* type = SVFUtil::dyn_cast<PointerType>(inst->getType());
Set<const Type*> types;
const SVFInstruction* svfinst = LLVMModuleSet::getLLVMModuleSet()->getSVFInstruction(inst);
if(SVFUtil::isHeapAllocExtCallViaRet(svfinst))
{
if(const Value* v = getFirstUseViaCastInst(inst))
{
if (const PointerType *newTy = SVFUtil::dyn_cast<PointerType>(v->getType())) {
type = newTy;
}
}
const CallBase *heapAlloc = SVFUtil::dyn_cast<CallBase>(inst);
collectAllHeapObjTypes(types, heapAlloc);
const Type *pType = selectLargestType(types);

#if TYPE_DEBUG
ABORT_IFNOT(pType, "fail to infer any types:" + dumpValue(inst) + getSourceLoc(inst) + "\n");
ABORT_IFNOT(getNumOfElements(getPtrElementType(type)) <= getNumOfElements(pType),
"inferred type is not sound:" + dumpValue(inst) + getSourceLoc(inst) + "\n");
return pType;
#else
if(pType) return pType;
#endif

}
else if(SVFUtil::isHeapAllocExtCallViaArg(svfinst))
{
const CallBase* cs = LLVMUtil::getLLVMCallSite(inst);
int arg_pos = SVFUtil::getHeapAllocHoldingArgPosition(SVFUtil::getSVFCallSite(svfinst));
const Value* arg = cs->getArgOperand(arg_pos);
type = SVFUtil::dyn_cast<PointerType>(arg->getType());
}
else
{
assert( false && "not a heap allocation instruction?");
}

assert(type && "not a pointer type?");
// TODO: getPtrElementType need type inference
return getPtrElementType(type);
}

/*!
* Get the num of BB's predecessors
*/
Expand Down
Loading