Files
Alessandro Di Federico 1429b526ab Introduce libtcg
This commit drops libptc in favor of its new form libtcg.

It brings several improvements, among which:

* The QEMU version we work on has been upgraded.
* CPUStateAccessAnalysis has been reimplemented in a way that makes it
  easier to debug and solves some limitations (e.g., tracking leaking
  pointers).
* Identification of pieces of the CPU state that are read by each helper
  and fixing access to the CPU state is now performed at build-time.
* We no longer mmap the code we need to translate, dropping all the
  issues related to code that needed to be mapped where something is
  already present.
* We now have two distinct flavors of helper modules: the full one and
  the "slim" one. The latter contains the definition only of functions
  we intend to inline. It is used in most of the pipeline, a good thing
  since we spend less time optimizing code we don't really care about.
  The full module is only used on the re-compilation branch of the
  pipeline.
* We no longer split the `cpu_loop` function.
* We change MetaAddress to rely on architectures from `model::` as
  opposed to the LLVM ones.
* We no longer attach debug info to LLVM IR containing the original
  assembly.
* We now verify that the lifted code only contains code we expect.
2025-10-31 17:25:03 +01:00

117 lines
3.6 KiB
C++

#pragma once
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include <map>
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Module.h"
#include "revng/Support/Debug.h"
#include "Function.h"
namespace aua {
class ArgumentUsageAnalysis {
private:
struct CallSite {
llvm::Function *Callee = nullptr;
bool IsIndirect = false;
bool IsDeclared = false;
bool IsVarArg = false;
bool HasBeenAnalyzed = false;
bool IsNoReturn = false;
bool IsPure = false;
template<typename O>
void dump(O &Stream) const {
Stream << "IsIndirect: " << IsIndirect << "\n";
Stream << "IsDeclared: " << IsDeclared << "\n";
Stream << "IsVarArg: " << IsVarArg << "\n";
Stream << "HasBeenAnalyzed: " << HasBeenAnalyzed << "\n";
Stream << "IsNoReturn: " << IsNoReturn << "\n";
Stream << "IsPure: " << IsPure << "\n";
}
};
private:
Context &TheContext;
std::map<const llvm::Function *, Function> Results;
llvm::Module &M;
const llvm::DataLayout &DL;
public:
ArgumentUsageAnalysis(Context &TheContext, llvm::Module &M) :
TheContext(TheContext), M(M), DL(M.getDataLayout()) {}
public:
auto begin() { return Results.begin(); }
auto end() { return Results.end(); }
const Function &at(const llvm::Function *F) const { return Results.at(F); }
auto find(const llvm::Function *F) const { return Results.find(F); }
auto begin() const { return Results.begin(); }
auto end() const { return Results.end(); }
public:
void run();
private:
void analyzeFunction(llvm::Function &F);
CallSite analyzeCallSite(const llvm::CallInst &Call);
void taintAnalysis(Function &FunctionResults, const llvm::Function &F);
const Value *analyzeInstruction(Function &FunctionResults,
const llvm::Instruction &I);
void registerFunctionResults(Function &FunctionResults, llvm::Instruction &I);
void registerLoad(Function &FunctionResults, const llvm::LoadInst &Load) {
auto Size = DL.getTypeAllocSize(Load.getType());
registerRead(FunctionResults,
Load.getOperandUse(Load.getPointerOperandIndex()));
}
void registerRead(Function &FunctionResults, const llvm::Use &Location) {
const Value &PointerValue = FunctionResults.get(*Location.get());
FunctionResults.registerAccess(Location, PointerValue);
}
void registerStore(Function &FunctionResults, llvm::StoreInst &Store) {
auto Size = DL.getTypeAllocSize(Store.getValueOperand()->getType());
registerWrite(FunctionResults,
Store.getOperandUse(Store.getPointerOperandIndex()));
// Register escaped value from value operand
const Value &Value = FunctionResults.get(*Store.getValueOperand());
FunctionResults.logEscapedValue("store " + getName(&Store), Value);
FunctionResults.registerEscapedValue(Store, Value);
}
void registerWrite(Function &FunctionResults, const llvm::Use &Location) {
const Value &PointerValue = FunctionResults.get(*Location.get());
FunctionResults.registerAccess(Location, PointerValue);
}
void registerMemcpy(Function &FunctionResults, llvm::CallInst &Call) {
registerWrite(FunctionResults, Call.getArgOperandUse(0));
registerRead(FunctionResults, Call.getArgOperandUse(1));
}
void registerCall(Function &FunctionResults, llvm::CallInst &Call);
const Value *getCallResult(const llvm::CallInst &Call);
const Value *handleCall(Function &FunctionResults,
const llvm::CallInst &Call);
};
} // namespace aua