mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
[DLA] Add CreateInterProceduralTypes DLAStep
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
|
||||
revng_add_analyses_library(Decompiler revngc
|
||||
ASTBuildAnalysis.cpp
|
||||
DLACreateInterProceduralTypes.cpp
|
||||
DLAHelpers.cpp
|
||||
DLAPass.cpp
|
||||
DLAStep.cpp
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// Copyright (c) rev.ng Srls. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
#include "DLAStep.h"
|
||||
#include "DLATypeSystem.h"
|
||||
|
||||
using namespace dla;
|
||||
using namespace llvm;
|
||||
|
||||
using StepT = CreateInterproceduralTypes;
|
||||
|
||||
bool StepT::runOnTypeSystem(LayoutTypeSystem &TS) {
|
||||
const Module &M = TS.getModule();
|
||||
for (const Function &F : M.functions()) {
|
||||
if (F.isIntrinsic() or not F.getMetadata("revng.func.entry"))
|
||||
continue;
|
||||
revng_assert(not F.isVarArg());
|
||||
|
||||
// Create the Function's return types
|
||||
auto FRetTypes = TS.getOrCreateLayoutTypes(F);
|
||||
|
||||
// Create types for the Function's arguments
|
||||
for (const Argument &Arg : F.args()) {
|
||||
// Arguments can only be integers and pointers
|
||||
revng_assert(isa<IntegerType>(Arg.getType())
|
||||
or isa<PointerType>(Arg.getType()));
|
||||
auto N = TS.getOrCreateLayoutTypes(Arg).size();
|
||||
// Given that arguments can only be integers or pointers, we should only
|
||||
// create a single LayoutType for each argument
|
||||
revng_assert(N == 1ULL);
|
||||
}
|
||||
|
||||
for (const BasicBlock &B : F) {
|
||||
for (const Instruction &I : B) {
|
||||
if (auto *Call = dyn_cast<CallInst>(&I)) {
|
||||
const Function *Callee = getCallee(Call);
|
||||
if (Callee->isIntrinsic()
|
||||
or not Callee->getMetadata("revng.func.entry")) {
|
||||
continue;
|
||||
}
|
||||
unsigned ArgNo = 0U;
|
||||
for (const Argument &FormalArg : Callee->args()) {
|
||||
Value *ActualArg = Call->getOperand(ArgNo);
|
||||
revng_assert(isa<IntegerType>(ActualArg->getType())
|
||||
or isa<PointerType>(ActualArg->getType()));
|
||||
revng_assert(isa<IntegerType>(FormalArg.getType())
|
||||
or isa<PointerType>(FormalArg.getType()));
|
||||
auto ActualTypes = TS.getOrCreateLayoutTypes(*ActualArg);
|
||||
auto FormalTypes = TS.getOrCreateLayoutTypes(FormalArg);
|
||||
revng_assert(1ULL == ActualTypes.size() == FormalTypes.size());
|
||||
auto FieldNum = FormalTypes.size();
|
||||
for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) {
|
||||
// Actual type inherits from formal type
|
||||
TS.addInheritanceLink(ActualTypes[FieldId].first,
|
||||
FormalTypes[FieldId].first);
|
||||
}
|
||||
++ArgNo;
|
||||
}
|
||||
} else if (auto *PHI = dyn_cast<PHINode>(&I)) {
|
||||
revng_assert(isa<IntegerType>(PHI->getType())
|
||||
or isa<PointerType>(PHI->getType()));
|
||||
auto PHITypes = TS.getOrCreateLayoutTypes(*PHI);
|
||||
for (const Use &Incoming : PHI->incoming_values()) {
|
||||
revng_assert(isa<IntegerType>(Incoming->getType())
|
||||
or isa<PointerType>(Incoming->getType()));
|
||||
auto InTypes = TS.getOrCreateLayoutTypes(*Incoming.get());
|
||||
revng_assert(1ULL == PHITypes.size() == InTypes.size());
|
||||
auto FieldNum = PHITypes.size();
|
||||
for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) {
|
||||
// Incoming type inherits from PHI type
|
||||
TS.addInheritanceLink(InTypes[FieldId].first,
|
||||
PHITypes[FieldId].first);
|
||||
}
|
||||
}
|
||||
} else if (auto *RetI = dyn_cast<ReturnInst>(&I)) {
|
||||
if (Value *RetVal = RetI->getReturnValue()) {
|
||||
revng_assert(isa<StructType>(RetVal->getType())
|
||||
or isa<IntegerType>(RetVal->getType())
|
||||
or isa<PointerType>(RetVal->getType()));
|
||||
auto RetTypes = TS.getOrCreateLayoutTypes(*RetVal);
|
||||
revng_assert(RetTypes.size() == FRetTypes.size());
|
||||
auto FieldNum = RetTypes.size();
|
||||
for (auto FieldId = 0ULL; FieldId < FieldNum; ++FieldId) {
|
||||
// Return Operand type inherits from Function return type
|
||||
if (RetTypes[FieldId].first != nullptr)
|
||||
TS.addInheritanceLink(RetTypes[FieldId].first,
|
||||
FRetTypes[FieldId].first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
revng_assert(TS.verifyConsistency());
|
||||
return TS.getNumLayouts() != 0;
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include "revng-c/Decompiler/DLAPass.h"
|
||||
|
||||
// Local includes
|
||||
#include "DLAStep.h"
|
||||
#include "DLATypeSystem.h"
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
|
||||
virtual ~CreateInterproceduralTypes() override = default;
|
||||
|
||||
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override { return true; }
|
||||
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
|
||||
};
|
||||
|
||||
/// dla::Step that creates types for LLVM Values inside Functions and edges
|
||||
|
||||
Reference in New Issue
Block a user