Skip to content

Commit

Permalink
Code Simplification
Browse files Browse the repository at this point in the history
  • Loading branch information
shuangxiangkan committed Jul 28, 2023
1 parent 90f68f3 commit 74bc50f
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 163 deletions.
15 changes: 3 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,17 +89,8 @@ install(
PATTERN "**/*.h")

# Compile extapi.c to extapi.bc
string(REGEX REPLACE "/lib/cmake/llvm$" "" LLVM_DIR "${LLVM_DIR}")
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
COMMAND ${LLVM_DIR}/bin/clang -w -S -c -Xclang -disable-O0-optnone -fno-discard-value-names -emit-llvm ${PROJECT_SOURCE_DIR}/svf/lib/Util/extapi.c -o ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
find_path(LLVM_CLANG_DIR NAMES clang PATH_SUFFIXES bin)
add_custom_target(extapi_ir ALL
COMMAND ${LLVM_CLANG_DIR}/clang -w -S -c -Xclang -disable-O0-optnone -fno-discard-value-names -emit-llvm ${PROJECT_SOURCE_DIR}/svf/lib/Util/extapi.c -o ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
DEPENDS ${PROJECT_SOURCE_DIR}/svf/lib/Util/extapi.c
)

add_custom_target(extapi_ir ALL DEPENDS ${PROJECT_BINARY_DIR}/include/Util/extapi.bc)

install(
FILES ${PROJECT_BINARY_DIR}/include/Util/extapi.bc
COMPONENT devel
DESTINATION include/svf/Util
)
127 changes: 12 additions & 115 deletions svf-llvm/include/SVF-LLVM/LLVMUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,121 +98,6 @@ inline const Function* getProgFunction(const std::string& funName)
return nullptr;
}

inline std::vector<std::string> getFunAnnotations(const Function* fun)
{
std::vector<std::string> annotations;
// Get annotation variable
GlobalVariable *glob = fun->getParent()->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr)
return annotations;

ConstantArray *ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
if (ca == nullptr)
return annotations;

for (unsigned i = 0; i < ca->getNumOperands(); ++i)
{
ConstantStruct *structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr)
continue;

ConstantExpr *expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr)
continue;

if (expr->getOpcode() != Instruction::BitCast || expr->getOperand(0) != fun)
continue;

ConstantExpr *note = SVFUtil::cast<ConstantExpr>(structAn->getOperand(1));
if (note->getOpcode() != Instruction::GetElementPtr)
continue;

GlobalVariable *annotateStr = SVFUtil::dyn_cast<GlobalVariable>(note->getOperand(0));
if (annotateStr == nullptr)
continue;

ConstantDataSequential *data = SVFUtil::dyn_cast<ConstantDataSequential>(annotateStr->getInitializer());
if (data == nullptr)
continue;

if (data->isString()) {
std::string annotation = data->getAsString().str();
if (!annotation.empty()) {
annotations.push_back(annotation);
}
}
}
return annotations;
}

inline void removeFunAnnotations(const std::vector<Function*>& removedFuncList) {
if (removedFuncList.empty()) {
return; // No functions to remove annotations in extapi.bc module
}

Module* module = removedFuncList[0]->getParent();
GlobalVariable* glob = module->getGlobalVariable("llvm.global.annotations");

if (glob == nullptr) {
return; // No annotations to remove
}

ConstantArray* ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
if (ca == nullptr) {
return; // Invalid annotations format
}

std::vector<Constant*> newAnnotations;

for (unsigned i = 0; i < ca->getNumOperands(); ++i) {
ConstantStruct* structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr) {
continue;
}

ConstantExpr* expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr || expr->getOpcode() != Instruction::BitCast) {
// Keep the annotation if it's not created using BitCast
newAnnotations.push_back(structAn);
continue;
}

Function* annotatedFunc = SVFUtil::dyn_cast<Function>(expr->getOperand(0));
if (annotatedFunc == nullptr || std::find(removedFuncList.begin(), removedFuncList.end(), annotatedFunc) != removedFuncList.end()) {
// Skip this annotation as it belongs to one of the functions in removedFuncList
continue;
}

// Keep the annotation for all other functions
newAnnotations.push_back(structAn);
}

if (newAnnotations.size() == ca->getNumOperands()) {
return; // No annotations to remove
}

ArrayType* annotationsType = ArrayType::get(ca->getType()->getElementType(), newAnnotations.size());
Constant* newCA = ConstantArray::get(annotationsType, newAnnotations);

// Check if a global variable with the name llvm.global.annotations already exists
GlobalVariable* existingGlobal = module->getGlobalVariable("llvm.global.annotations");
if (existingGlobal) {
// Rename the existing llvm.global.annotations to llvm.global.annotations_old
existingGlobal->setName("llvm.global.annotations_old");
}

// Create a new global variable with the updated annotations
GlobalVariable* newGlobal = new GlobalVariable(*module, newCA->getType(), glob->isConstant(),
glob->getLinkage(), newCA, "llvm.global.annotations", glob, glob->getThreadLocalMode());

// Copy other properties from the old global variable to the new one
newGlobal->setSection(glob->getSection());
newGlobal->setAlignment(llvm::MaybeAlign(glob->getAlignment()));

// Remove the old global variable
glob->eraseFromParent();
}

/// Check whether a function is an entry function (i.e., main)
inline bool isProgEntryFunction(const Function* fun)
{
Expand Down Expand Up @@ -487,6 +372,18 @@ const std::string getSourceLocOfFunction(const Function* F);
bool isIntrinsicInst(const Instruction* inst);
bool isIntrinsicFun(const Function* func);

std::vector<std::string> getFunAnnotations(const Function* fun);
void removeFunAnnotations(std::vector<Function*>& removedFuncList);

inline void removeUnusedFuncsAndAnnotations(std::vector<Function*> removedFuncList)
{
/// Remove unused function annotations in extapi.bc
LLVMUtil::removeFunAnnotations(removedFuncList);
/// Remove unused function in extapi.bc
for (Function* func : removedFuncList)
func->eraseFromParent();
}

/// Get the corresponding Function based on its name
inline const SVFFunction* getFunction(const std::string& name)
{
Expand Down
2 changes: 1 addition & 1 deletion svf-llvm/include/SVF-LLVM/SVFIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ class SVFIRBuilder: public llvm::InstVisitor<SVFIRBuilder>
return nullPtr;
}

NodeID getGepValVar(const Value* val, const AccessPath& ls, const SVFType* elementType);
NodeID getGepValVar(const Value* val, const AccessPath& ap, const SVFType* elementType);

void setCurrentBBAndValueForPAGEdge(PAGEdge* edge);

Expand Down
47 changes: 12 additions & 35 deletions svf-llvm/lib/LLVMModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,51 +154,29 @@ void LLVMModuleSet::createSVFDataStructure()
{
getSVFType(IntegerType::getInt8Ty(getContext()));
// Functions need to be retrieved in the order of insertion
std::vector<const Function*> candidateDecls;
std::vector<const Function*> candidateDefs;

std::vector<const Function*> candidateFuncs;
for (Module& mod : modules)
{
std::vector<Function*> removedFuncList;
/// Function
for (Function& func : mod.functions())
{
if (func.isDeclaration() && (FunDefToDeclsMap.find(&func) != FunDefToDeclsMap.end() || mod.getName().str() != Options::ExtAPIInput()))
/// Remove unused function in extapi.bc module
/// if this function func defined in extapi.bc but never used in application code (without any corresponding declared functions).
if (mod.getName().str() == Options::ExtAPIInput() && FunDefToDeclsMap.find(&func) == FunDefToDeclsMap.end() && func.getName().str() != "svf__main")
{
/// if this function is declaration
candidateDecls.push_back(&func);
removedFuncList.push_back(&func);
continue;
}
else
{
/// if this function is definition
if (mod.getName().str() == Options::ExtAPIInput() && FunDefToDeclsMap.find(&func) == FunDefToDeclsMap.end() && func.getName().str() != "svf__main")
{
/// if this function func defined in ExtAPI but never used in application code (without any corresponding declared functions).
removedFuncList.push_back(&func);
continue;
}
else
{
/// if this function is in app bc, any def func should be added.
/// if this function is in ext bc, only functions which have declarations(should be used by app bc) can be inserted.
candidateDefs.push_back(&func);
}
candidateFuncs.push_back(&func);
}
}
// Remove unused function annotations in extapi.bc
LLVMUtil::removeFunAnnotations(removedFuncList);
// Remove unused function in extapi.bc
for (Function* func : removedFuncList)
{
func->eraseFromParent();
}
}
for (const Function* func: candidateDefs)
{
createSVFFunction(func);
/// Remove unused functions and annotations in extapi.bc
LLVMUtil::removeUnusedFuncsAndAnnotations(removedFuncList);
}

for (const Function* func: candidateDecls)
for (const Function* func: candidateFuncs)
{
createSVFFunction(func);
}
Expand Down Expand Up @@ -557,9 +535,8 @@ void LLVMModuleSet::loadExtAPIModules()
Err.print("SVFModuleLoader", llvm::errs());
abort();
}
// The module of ext.bc needs to be imported before other modules.
// Otherwise, when overwriting the app function with SVF extern function,
// the corresponding SVFFunction of the extern function will not be found.
// The module of extapi.bc needs to be inserted before applications modules, like std::vector<std::reference_wrapper<Module>> modules{extapi_module, app_module}.
// Otherwise, when overwriting the app function with SVF extern function, the corresponding SVFFunction of the extern function will not be found.
modules.insert(modules.begin(), *mod);
owned_modules.insert(owned_modules.begin(),std::move(mod));
}
Expand Down
95 changes: 95 additions & 0 deletions svf-llvm/lib/LLVMUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,101 @@ void LLVMUtil::processArguments(int argc, char **argv, int &arg_num, char **arg_
}
}

std::vector<std::string> LLVMUtil::getFunAnnotations(const Function* fun)
{
std::vector<std::string> annotations;
// Get annotation variable
GlobalVariable *glob = fun->getParent()->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr || !glob->hasInitializer())
return annotations;

ConstantArray *ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
for (unsigned i = 0; i < ca->getNumOperands(); ++i)
{
ConstantStruct *structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr)
continue;

Check warning on line 459 in svf-llvm/lib/LLVMUtil.cpp

View check run for this annotation

Codecov / codecov/patch

svf-llvm/lib/LLVMUtil.cpp#L459

Added line #L459 was not covered by tests

ConstantExpr *expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr || expr->getOpcode() != Instruction::BitCast || expr->getOperand(0) != fun)
continue;

ConstantExpr *note = SVFUtil::cast<ConstantExpr>(structAn->getOperand(1));
if (note->getOpcode() != Instruction::GetElementPtr)
continue;

Check warning on line 467 in svf-llvm/lib/LLVMUtil.cpp

View check run for this annotation

Codecov / codecov/patch

svf-llvm/lib/LLVMUtil.cpp#L467

Added line #L467 was not covered by tests

GlobalVariable *annotateStr = SVFUtil::dyn_cast<GlobalVariable>(note->getOperand(0));
if (annotateStr == nullptr || !annotateStr->hasInitializer())
continue;

Check warning on line 471 in svf-llvm/lib/LLVMUtil.cpp

View check run for this annotation

Codecov / codecov/patch

svf-llvm/lib/LLVMUtil.cpp#L471

Added line #L471 was not covered by tests

ConstantDataSequential *data = SVFUtil::dyn_cast<ConstantDataSequential>(annotateStr->getInitializer());
if (data->isString())
{
std::string annotation = data->getAsString().str();
if (!annotation.empty())
annotations.push_back(annotation);
}
}
return annotations;
}

void LLVMUtil::removeFunAnnotations(std::vector<Function*>& removedFuncList)
{
if (removedFuncList.empty())
return; // No functions to remove annotations in extapi.bc module

Module* module = removedFuncList[0]->getParent();
GlobalVariable* glob = module->getGlobalVariable("llvm.global.annotations");
if (glob == nullptr || !glob->hasInitializer())
return;

Check warning on line 492 in svf-llvm/lib/LLVMUtil.cpp

View check run for this annotation

Codecov / codecov/patch

svf-llvm/lib/LLVMUtil.cpp#L492

Added line #L492 was not covered by tests

ConstantArray* ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
std::vector<Constant*> newAnnotations;
for (unsigned i = 0; i < ca->getNumOperands(); ++i)
{
ConstantStruct* structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
if (structAn == nullptr)
continue;

ConstantExpr* expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0));
if (expr == nullptr || expr->getOpcode() != Instruction::BitCast)
{
// Keep the annotation if it's not created using BitCast
newAnnotations.push_back(structAn);
continue;

Check warning on line 507 in svf-llvm/lib/LLVMUtil.cpp

View check run for this annotation

Codecov / codecov/patch

svf-llvm/lib/LLVMUtil.cpp#L506-L507

Added lines #L506 - L507 were not covered by tests
}

Function* annotatedFunc = SVFUtil::dyn_cast<Function>(expr->getOperand(0));
if (annotatedFunc == nullptr || std::find(removedFuncList.begin(), removedFuncList.end(), annotatedFunc) != removedFuncList.end())
continue;

// Keep the annotation for all other functions
newAnnotations.push_back(structAn);
}

if (newAnnotations.size() == ca->getNumOperands())
return; // No annotations to remove

ArrayType* annotationsType = ArrayType::get(ca->getType()->getElementType(), newAnnotations.size());
Constant* newCA = ConstantArray::get(annotationsType, newAnnotations);

// Check if a global variable with the name llvm.global.annotations already exists
GlobalVariable* existingGlobal = module->getGlobalVariable("llvm.global.annotations");
if (existingGlobal)
// Rename the existing llvm.global.annotations to llvm.global.annotations_old
existingGlobal->setName("llvm.global.annotations_old");

// Create a new global variable with the updated annotations
GlobalVariable* newGlobal = new GlobalVariable(*module, newCA->getType(), glob->isConstant(),
glob->getLinkage(), newCA, "llvm.global.annotations", glob, glob->getThreadLocalMode());

// Copy other properties from the old global variable to the new one
newGlobal->setSection(glob->getSection());
newGlobal->setAlignment(llvm::MaybeAlign(glob->getAlignment()));

// Remove the old global variable
glob->eraseFromParent();
}

u32_t LLVMUtil::getTypeSizeInBytes(const Type* type)
{
Expand Down

0 comments on commit 74bc50f

Please sign in to comment.