mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
107 lines
4.3 KiB
C++
107 lines
4.3 KiB
C++
//
|
|
// 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/Debug.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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (VerifyLog.isEnabled())
|
|
revng_assert(TS.verifyConsistency());
|
|
return TS.getNumLayouts() != 0;
|
|
}
|