mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Merge branch 'feature/segretate-aggregates-2'
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Model/ProgramCounterHandler.h"
|
||||
#include "revng/Support/BlockType.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
// Forward declarations
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/PipeboxCommon/Common.h"
|
||||
#include "revng/PipeboxCommon/LLVMContainer.h"
|
||||
#include "revng/PipeboxCommon/Model.h"
|
||||
|
||||
namespace revng::pypeline::pipes {
|
||||
|
||||
// For target binaries with 32-bit pointers, rewrite the LLVM module's
|
||||
// DataLayout so the default-address-space pointer is 32 bits wide before the
|
||||
// IR is handed off to `clifter`.
|
||||
//
|
||||
// Two preconditions must hold for the rewrite to be valid:
|
||||
//
|
||||
// 1. No scalar `alloca`'s allocated type transitively contains an
|
||||
// `llvm::PointerType`. Pointer-typed allocas would silently shrink
|
||||
// from 8 to 4 bytes when the DataLayout changes; pointer values must
|
||||
// instead live in integer-typed allocas and be bitcast (via
|
||||
// `ptrtoint`/`inttoptr`) at load/store boundaries.
|
||||
//
|
||||
// 2. No `getelementptr` has a source type that transitively contains an
|
||||
// `llvm::PointerType`. Otherwise the GEP's byte offsets would shift
|
||||
// under the new DataLayout.
|
||||
//
|
||||
// Both preconditions are checked with hard assertions; the pipe aborts if
|
||||
// either fails. The DataLayout rewrite is a no-op for targets whose pointer
|
||||
// is not 32 bits wide.
|
||||
class FixPointerSize {
|
||||
public:
|
||||
static constexpr llvm::StringRef Name = "fix-pointer-size";
|
||||
using Arguments = TypeList<PipeArgument<"Module",
|
||||
"LLVM Modules whose pointer size "
|
||||
"needs to match the "
|
||||
"target architecture">>;
|
||||
|
||||
const std::string StaticConfiguration;
|
||||
FixPointerSize(llvm::StringRef StaticConfiguration) :
|
||||
StaticConfiguration(StaticConfiguration) {}
|
||||
|
||||
PipeOutput run(const Model &TheModel,
|
||||
const revng::pypeline::Request &Incoming,
|
||||
const revng::pypeline::Request &Outgoing,
|
||||
llvm::StringRef Configuration,
|
||||
LLVMFunctionContainer &Container);
|
||||
};
|
||||
|
||||
} // namespace revng::pypeline::pipes
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "revng/EarlyFunctionAnalysis/Outliner.h"
|
||||
#include "revng/EarlyFunctionAnalysis/TemporaryOpaqueFunction.h"
|
||||
#include "revng/Model/Binary.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "revng/EarlyFunctionAnalysis/AnalyzeRegisterUsage.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
|
||||
namespace revng {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
namespace revng {
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
Builder.CreateStore(Undef, V);
|
||||
}
|
||||
|
||||
return createLoadVariable(Builder, V);
|
||||
return Builder.createLoadVariable(V);
|
||||
}
|
||||
|
||||
/// Get or create the LLVM value associated to a PTC temporary
|
||||
|
||||
@@ -9,12 +9,9 @@
|
||||
|
||||
#include "revng/Model/Architecture.h"
|
||||
#include "revng/Support/BlockType.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
namespace revng {
|
||||
class IRBuilder;
|
||||
} // namespace revng
|
||||
|
||||
inline llvm::IntegerType *getCSVType(llvm::GlobalVariable *CSV) {
|
||||
using namespace llvm;
|
||||
return cast<IntegerType>(CSV->getValueType());
|
||||
@@ -156,7 +153,7 @@ public:
|
||||
// Load and re-store each CSV affecting the PC and then feed them to
|
||||
// handleStore
|
||||
for (GlobalVariable *CSVAffectingPC : CSVsAffectingPC) {
|
||||
auto *FakeLoad = createLoad(Builder, CSVAffectingPC);
|
||||
auto *FakeLoad = Builder.createLoad(CSVAffectingPC);
|
||||
auto *FakeStore = Builder.CreateStore(FakeLoad, CSVAffectingPC);
|
||||
bool HasInjectedCode = handleStore(Builder, FakeStore);
|
||||
eraseFromParent(FakeStore);
|
||||
@@ -183,10 +180,10 @@ public:
|
||||
|
||||
llvm::Instruction *composeIntegerPC(revng::IRBuilder &B) const {
|
||||
return MetaAddress::composeIntegerPC(B,
|
||||
align(B, createLoad(B, AddressCSV)),
|
||||
createLoad(B, EpochCSV),
|
||||
createLoad(B, AddressSpaceCSV),
|
||||
createLoad(B, TypeCSV));
|
||||
align(B, B.createLoad(AddressCSV)),
|
||||
B.createLoad(EpochCSV),
|
||||
B.createLoad(AddressSpaceCSV),
|
||||
B.createLoad(TypeCSV));
|
||||
}
|
||||
|
||||
bool isPCSizedType(llvm::Type *T) const {
|
||||
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
|
||||
TarWriter Writer(OS, TarFormat::Plain);
|
||||
auto Objects = StorePair.first->objects();
|
||||
std::vector<const ObjectID> ToSave(Objects.begin(), Objects.end());
|
||||
std::vector<ObjectID> ToSave(Objects.begin(), Objects.end());
|
||||
auto Serialized = StorePair.first->serialize(ToSave);
|
||||
|
||||
for (auto &[ObjectID, Data] : Serialized) {
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
llvm::ArrayRef<char>> &Input) = 0;
|
||||
|
||||
virtual std::map<ObjectID, pypeline::Buffer>
|
||||
serialize(llvm::ArrayRef<const ObjectID> ToSave) const = 0;
|
||||
serialize(llvm::ArrayRef<ObjectID> ToSave) const = 0;
|
||||
|
||||
virtual void *get() = 0;
|
||||
};
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
}
|
||||
|
||||
virtual std::map<ObjectID, pypeline::Buffer>
|
||||
serialize(llvm::ArrayRef<const ObjectID> ToSave) const override {
|
||||
serialize(llvm::ArrayRef<ObjectID> ToSave) const override {
|
||||
std::vector<const ObjectID *> Input;
|
||||
for (const ObjectID &Element : ToSave)
|
||||
Input.push_back(&Element);
|
||||
|
||||
@@ -4,10 +4,20 @@
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
namespace revng {
|
||||
|
||||
@@ -44,6 +54,13 @@ using LLVMBuilderBase = llvm::IRBuilder<llvm::ConstantFolder,
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline bool
|
||||
sameSize(llvm::Type *LHS, llvm::Type *RHS, const llvm::DataLayout &DL) {
|
||||
auto LHSSize = DL.getTypeStoreSize(LHS).getFixedValue();
|
||||
auto RHSSize = DL.getTypeStoreSize(RHS).getFixedValue();
|
||||
return LHSSize == RHSSize;
|
||||
}
|
||||
|
||||
/// This is a wrapper over llvm's IR builder that force-sets a debug location
|
||||
/// even when its insertion point is a basic block.
|
||||
///
|
||||
@@ -120,6 +137,88 @@ public:
|
||||
getInserter().checkImpl();
|
||||
}
|
||||
|
||||
public:
|
||||
/// Create an `alloca` of integer type or byte array capable to hold \p T
|
||||
llvm::AllocaInst *createSimpleAlloca(llvm::Type *T) {
|
||||
using namespace llvm;
|
||||
const DataLayout &DL = GetInsertBlock()->getModule()->getDataLayout();
|
||||
|
||||
if (T->isPointerTy()) {
|
||||
auto Size = DL.getPointerSizeInBits(T->getPointerAddressSpace());
|
||||
return CreateAlloca(this->getIntNTy(Size));
|
||||
}
|
||||
|
||||
if (T->isIntegerTy())
|
||||
return CreateAlloca(T);
|
||||
|
||||
auto Size = DL.getTypeStoreSize(T).getFixedValue();
|
||||
return CreateAlloca(ArrayType::get(this->getInt8Ty(), Size));
|
||||
}
|
||||
|
||||
/// Load a value of type \p DesiredType from \p Variable (an `AllocaInst` or
|
||||
/// `GlobalVariable`). The variable's allocated type and \p DesiredType must
|
||||
/// have the same store size.
|
||||
llvm::LoadInst *createLoadFromVariable(llvm::Value *Variable,
|
||||
llvm::Type *DesiredType) {
|
||||
using namespace llvm;
|
||||
Type *AllocatedType = getVariableType(Variable);
|
||||
const DataLayout &DL = GetInsertBlock()->getModule()->getDataLayout();
|
||||
revng_assert(sameSize(DesiredType, AllocatedType, DL));
|
||||
return this->CreateLoad(DesiredType, Variable);
|
||||
}
|
||||
|
||||
/// Store \p V into \p Variable (an `AllocaInst` or `GlobalVariable`). The
|
||||
/// variable's allocated type and \p V's type must have the same store size.
|
||||
llvm::StoreInst *createStoreToVariable(llvm::Value *V,
|
||||
llvm::Value *Variable) {
|
||||
using namespace llvm;
|
||||
Type *AllocatedType = getVariableType(Variable);
|
||||
const DataLayout &DL = GetInsertBlock()->getModule()->getDataLayout();
|
||||
revng_assert(sameSize(V->getType(), AllocatedType, DL));
|
||||
return CreateStore(V, Variable);
|
||||
}
|
||||
|
||||
llvm::LoadInst *createLoad(llvm::GlobalVariable *GV) {
|
||||
return this->CreateLoad(GV->getValueType(), GV);
|
||||
}
|
||||
|
||||
llvm::LoadInst *createLoad(llvm::AllocaInst *Alloca) {
|
||||
return this->CreateLoad(Alloca->getAllocatedType(), Alloca);
|
||||
}
|
||||
|
||||
llvm::LoadInst *createLoadVariable(llvm::Value *Variable) {
|
||||
if (auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Variable))
|
||||
return createLoad(Alloca);
|
||||
if (auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(Variable))
|
||||
return createLoad(GV);
|
||||
revng_abort("Either GlobalVariable or AllocaInst expected");
|
||||
}
|
||||
|
||||
void setInsertPointToFirstNonAlloca(llvm::Function &F) {
|
||||
using namespace llvm;
|
||||
for (Instruction &I : F.getEntryBlock()) {
|
||||
if (not isa<AllocaInst>(&I)) {
|
||||
SetInsertPoint(&I);
|
||||
return;
|
||||
}
|
||||
}
|
||||
revng_abort();
|
||||
}
|
||||
|
||||
llvm::SmallVector<llvm::Value *, 4> unpack(llvm::Value *V) {
|
||||
using namespace llvm;
|
||||
Type *T = V->getType();
|
||||
if (isa<IntegerType>(T))
|
||||
return { V };
|
||||
if (auto *ST = dyn_cast<StructType>(T)) {
|
||||
SmallVector<Value *, 4> Result;
|
||||
for (unsigned I = 0; I < ST->getNumElements(); ++I)
|
||||
Result.push_back(this->CreateExtractValue(V, { I }));
|
||||
return Result;
|
||||
}
|
||||
revng_abort("Cannot unpack the given type");
|
||||
}
|
||||
|
||||
protected:
|
||||
// NOLINTNEXTLINE
|
||||
explicit IRBuilder(bool EnableDebugInformationChecks, llvm::LLVMContext &C) :
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "revng/Support/BasicBlockID.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/Generator.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
|
||||
class ProgramCounterHandler;
|
||||
@@ -1443,18 +1442,13 @@ inline void setPointersMetadata(Value *V,
|
||||
QMD.tuple(PointerOperandsMD) }));
|
||||
}
|
||||
|
||||
inline void setInsertPointToFirstNonAlloca(revng::IRBuilder &Builder,
|
||||
llvm::Function &F) {
|
||||
using namespace llvm;
|
||||
|
||||
BasicBlock &Entry = F.getEntryBlock();
|
||||
for (Instruction &I : Entry) {
|
||||
if (not isa<AllocaInst>(&I)) {
|
||||
Builder.SetInsertPoint(&I);
|
||||
return;
|
||||
}
|
||||
}
|
||||
revng_abort();
|
||||
inline llvm::Type *getVariableType(const llvm::Value *Variable) {
|
||||
if (auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Variable))
|
||||
return Alloca->getAllocatedType();
|
||||
else if (auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(Variable))
|
||||
return GV->getValueType();
|
||||
else
|
||||
revng_abort("Either GlobalVariable or AllocaInst expected");
|
||||
}
|
||||
|
||||
inline llvm::Value *getPointer(llvm::User *U) {
|
||||
@@ -1495,51 +1489,6 @@ llvm::Function *changeFunctionType(llvm::Function &OldFunction,
|
||||
llvm::Type *NewReturnType,
|
||||
llvm::ArrayRef<llvm::Type *> NewArguments);
|
||||
|
||||
inline llvm::SmallVector<llvm::Value *, 4> unpack(revng::IRBuilder &Builder,
|
||||
llvm::Value *V) {
|
||||
using namespace llvm;
|
||||
Type *Type = V->getType();
|
||||
if (isa<IntegerType>(Type)) {
|
||||
return { V };
|
||||
} else if (auto *StructType = dyn_cast<llvm::StructType>(Type)) {
|
||||
llvm::SmallVector<llvm::Value *, 4> Result;
|
||||
for (unsigned I = 0; I < StructType->getNumElements(); ++I)
|
||||
Result.push_back(Builder.CreateExtractValue(V, { I }));
|
||||
return Result;
|
||||
} else {
|
||||
revng_abort("Cannot unpack the given type");
|
||||
}
|
||||
}
|
||||
|
||||
inline llvm::Instruction *createLoad(revng::IRBuilder &Builder,
|
||||
llvm::GlobalVariable *GV) {
|
||||
return Builder.CreateLoad(GV->getValueType(), GV);
|
||||
}
|
||||
|
||||
inline llvm::Instruction *createLoad(revng::IRBuilder &Builder,
|
||||
llvm::AllocaInst *Alloca) {
|
||||
return Builder.CreateLoad(Alloca->getAllocatedType(), Alloca);
|
||||
}
|
||||
|
||||
inline llvm::Instruction *createLoadVariable(revng::IRBuilder &Builder,
|
||||
llvm::Value *Variable) {
|
||||
if (auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Variable))
|
||||
return createLoad(Builder, Alloca);
|
||||
else if (auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(Variable))
|
||||
return createLoad(Builder, GV);
|
||||
else
|
||||
revng_abort("Either GlobalVariable or AllocaInst expected");
|
||||
}
|
||||
|
||||
inline llvm::Type *getVariableType(const llvm::Value *Variable) {
|
||||
if (auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Variable))
|
||||
return Alloca->getAllocatedType();
|
||||
else if (auto *GV = llvm::dyn_cast<llvm::GlobalVariable>(Variable))
|
||||
return GV->getValueType();
|
||||
else
|
||||
revng_abort("Either GlobalVariable or AllocaInst expected");
|
||||
}
|
||||
|
||||
void pruneDICompileUnits(llvm::Module &M);
|
||||
|
||||
llvm::SmallSet<llvm::Value *, 2> findPhiTreeLeaves(llvm::Value *Root);
|
||||
|
||||
@@ -11,14 +11,11 @@
|
||||
|
||||
#include "revng/ADT/KeyedObjectContainer.h"
|
||||
#include "revng/Model/Architecture.h"
|
||||
#include "revng/Runtime/PlainMetaAddress.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IntegerSerialization.h"
|
||||
#include "revng/Support/OverflowSafeInt.h"
|
||||
|
||||
extern "C" {
|
||||
#include "revng/Runtime/PlainMetaAddress.h"
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
class TypeDefinition;
|
||||
class Constant;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/Register.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
namespace revng {
|
||||
|
||||
@@ -151,20 +151,32 @@ private:
|
||||
CUniquePtr<sqlite3_close_v2, SQLITE_OK> Connection;
|
||||
|
||||
public:
|
||||
Database(llvm::StringRef Path) {
|
||||
enum class OpenMode {
|
||||
ReadWrite,
|
||||
ReadOnly
|
||||
};
|
||||
|
||||
Database(llvm::StringRef Path, OpenMode Mode) {
|
||||
sqlite3 *Ptr = nullptr;
|
||||
int Result;
|
||||
|
||||
if (Path == ":memory:")
|
||||
if (Path == ":memory:") {
|
||||
Result = sqlite3_open_v2("",
|
||||
&Ptr,
|
||||
SQLITE_OPEN_MEMORY | SQLITE_OPEN_PRIVATECACHE,
|
||||
NULL);
|
||||
else
|
||||
} else if (Mode == OpenMode::ReadOnly) {
|
||||
std::string URI = ("file:" + Path.str() + "?immutable=1");
|
||||
Result = sqlite3_open_v2(URI.c_str(),
|
||||
&Ptr,
|
||||
SQLITE_OPEN_READONLY | SQLITE_OPEN_URI,
|
||||
NULL);
|
||||
} else {
|
||||
Result = sqlite3_open_v2(Path.str().c_str(),
|
||||
&Ptr,
|
||||
SQLITE_OPEN_READWRITE,
|
||||
NULL);
|
||||
}
|
||||
revng_assert(Result == SQLITE_OK);
|
||||
|
||||
Connection.reset(Ptr);
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
#include "revng/RestructureCFG/RestructureCFG.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/DecompilationHelpers.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/YAMLTraits.h"
|
||||
#include "revng/TypeNames/LLVMTypeNames.h"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
#include "revng/BasicAnalyses/RemoveHelperCalls.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
|
||||
@@ -49,7 +50,7 @@ RemoveHelperCallsPass::run(llvm::Function &F,
|
||||
|
||||
// Assumption: helpers do not leave the stack altered, thus we can save the
|
||||
// stack pointer and restore it back later.
|
||||
auto *SP = createLoad(Builder, GCBI->spReg());
|
||||
auto *SP = Builder.createLoad(GCBI->spReg());
|
||||
|
||||
auto *RetTy = cast<CallInst>(I)->getFunctionType()->getReturnType();
|
||||
auto *OriginalHelperMarker = OFPOriginalHelper.get(RetTy,
|
||||
|
||||
@@ -1138,7 +1138,7 @@ bool ArithmeticToGEPPass::runOnFunction(llvm::Function &F) {
|
||||
{
|
||||
GEPRewriter Rewriter(F);
|
||||
|
||||
std::set<const LocalValue<>> Replaced;
|
||||
std::set<LocalValue<>> Replaced;
|
||||
for (const LocalValue<> &PointerValue : Pointers) {
|
||||
|
||||
// This can happen because a likely pointer may also be an obvious
|
||||
|
||||
@@ -10,6 +10,7 @@ revng_add_analyses_library_internal(
|
||||
EmbedStatementComments.cpp
|
||||
ExitSSAPass.cpp
|
||||
ExtractValueToGEP.cpp
|
||||
FixPointerSize.cpp
|
||||
FoldModelGEP.cpp
|
||||
SplitStructPhis.cpp
|
||||
ImplicitModelCastPass.cpp
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "revng/ADT/SmallMap.h"
|
||||
#include "revng/ADT/ZipMapIterator.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
@@ -273,7 +274,7 @@ buildStore(BasicBlock *StoreBlock, Value *Incoming, AllocaInst *Alloca) {
|
||||
Builder.SetInsertPoint(StoreBlock->getTerminator(), Alloca->getDebugLoc());
|
||||
}
|
||||
|
||||
auto *S = Builder.CreateStore(Incoming, Alloca);
|
||||
auto *S = Builder.createStoreToVariable(Incoming, Alloca);
|
||||
revng_log(Log,
|
||||
"Created StoreInst " << dumpToString(S)
|
||||
<< " in Block: " << StoreBlock->getName());
|
||||
@@ -285,7 +286,9 @@ buildStore(BasicBlock *StoreBlock, Value *Incoming, AllocaInst *Alloca) {
|
||||
for (Use &Operand : NextInBlock.operands()) {
|
||||
if (Operand.get() == IncomingInst) {
|
||||
if (not LoadFromStore) {
|
||||
LoadFromStore = Builder.CreateLoad(IncomingInst->getType(), Alloca);
|
||||
LoadFromStore = Builder
|
||||
.createLoadFromVariable(Alloca,
|
||||
IncomingInst->getType());
|
||||
if (auto *IncomingInst = dyn_cast<Instruction>(Incoming))
|
||||
LoadFromStore->setDebugLoc(IncomingInst->getDebugLoc());
|
||||
}
|
||||
@@ -308,7 +311,7 @@ static void replacePHIEquivalenceClass(const SetVector<PHINode *> &PHIs,
|
||||
const DebugLoc &PHIDebugLoc = (*PHIs.begin())->getDebugLoc();
|
||||
Builder.SetInsertPointPastAllocas(&F, PHIDebugLoc);
|
||||
|
||||
AllocaInst *Alloca = Builder.CreateAlloca((*PHIs.begin())->getType());
|
||||
AllocaInst *Alloca = Builder.createSimpleAlloca((*PHIs.begin())->getType());
|
||||
revng_log(Log, "Created Alloca: " << dumpToString(Alloca));
|
||||
|
||||
{
|
||||
@@ -423,7 +426,7 @@ static void replacePHIEquivalenceClass(const SetVector<PHINode *> &PHIs,
|
||||
LoggerIndent IndentPHI{ Log };
|
||||
|
||||
Builder.SetInsertPoint(PHI->getParent()->getFirstNonPHI());
|
||||
auto *NewLoad = createLoad(Builder, Alloca);
|
||||
auto *NewLoad = Builder.createLoadFromVariable(Alloca, PHI->getType());
|
||||
NewLoad->setDebugLoc(PHIDebugLoc);
|
||||
revng_log(Log, "Create new load: " << dumpToString(NewLoad));
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
|
||||
#include "revng/ADT/Queue.h"
|
||||
#include "revng/Canonicalize/FixPointerSize.h"
|
||||
#include "revng/Model/Architecture.h"
|
||||
#include "revng/PipeboxCommon/ObjectID.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static bool containsPointer(Type *T) {
|
||||
OnceQueue<Type *> Queue;
|
||||
Queue.insert(T);
|
||||
while (not Queue.empty()) {
|
||||
Type *Current = Queue.pop();
|
||||
if (Current->isPointerTy())
|
||||
return true;
|
||||
auto ContainedTypesCount = Current->getNumContainedTypes();
|
||||
for (unsigned I = 0; I < ContainedTypesCount; ++I)
|
||||
Queue.insert(Current->getContainedType(I));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rewrite the default-address-space pointer specification in a DataLayout
|
||||
// string to the given pointer size in bits.
|
||||
static std::string rewriteDefaultPointerSize(StringRef Original,
|
||||
unsigned Bits) {
|
||||
std::string Width = std::to_string(Bits);
|
||||
std::string NewSpec = "p:" + Width + ":" + Width;
|
||||
|
||||
SmallVector<StringRef, 16> Parts;
|
||||
Original.split(Parts, '-');
|
||||
std::string Result;
|
||||
bool Replaced = false;
|
||||
for (StringRef Part : Parts) {
|
||||
if (not Result.empty())
|
||||
Result += '-';
|
||||
if (Part.starts_with("p:") or Part.starts_with("p0:")) {
|
||||
Result += NewSpec;
|
||||
Replaced = true;
|
||||
} else {
|
||||
Result += Part.str();
|
||||
}
|
||||
}
|
||||
if (not Replaced) {
|
||||
if (not Result.empty())
|
||||
Result += '-';
|
||||
Result += NewSpec;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static void checkAndFixModule(llvm::Module &M, unsigned TargetPointerBits) {
|
||||
for (llvm::GlobalVariable &GV : M.globals()) {
|
||||
// Ignore unused globals
|
||||
if (GV.use_empty())
|
||||
continue;
|
||||
|
||||
revng_assert(not containsPointer(GV.getValueType()),
|
||||
("used global variable's value type transitively contains a "
|
||||
"pointer: "
|
||||
+ dumpToString(&GV))
|
||||
.c_str());
|
||||
}
|
||||
|
||||
for (llvm::Function &F : M) {
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
|
||||
for (llvm::Instruction &I : llvm::instructions(F)) {
|
||||
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(&I)) {
|
||||
Type *AllocatedTy = Alloca->getAllocatedType();
|
||||
revng_assert(not containsPointer(AllocatedTy),
|
||||
("scalar alloca containing a pointer in @" + F.getName()
|
||||
+ ": " + dumpToString(Alloca))
|
||||
.str()
|
||||
.c_str());
|
||||
} else if (auto *GEP = dyn_cast<llvm::GetElementPtrInst>(&I)) {
|
||||
revng_assert(not containsPointer(GEP->getSourceElementType()),
|
||||
("GEP source type transitively contains a pointer in @"
|
||||
+ F.getName() + ": " + dumpToString(GEP))
|
||||
.str()
|
||||
.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto &DL = M.getDataLayout();
|
||||
if (DL.getPointerSizeInBits(0) == TargetPointerBits)
|
||||
return;
|
||||
|
||||
auto Original = DL.getStringRepresentation();
|
||||
M.setDataLayout(rewriteDefaultPointerSize(Original, TargetPointerBits));
|
||||
}
|
||||
|
||||
namespace revng::pypeline::pipes {
|
||||
|
||||
PipeOutput FixPointerSize::run(const Model &TheModel,
|
||||
const revng::pypeline::Request &Incoming,
|
||||
const revng::pypeline::Request &Outgoing,
|
||||
llvm::StringRef Configuration,
|
||||
LLVMFunctionContainer &Container) {
|
||||
using namespace model::ABI;
|
||||
auto TargetPointerBits = getPointerSize(TheModel.get()->targetABI()) * 8;
|
||||
|
||||
for (const ObjectID *Object : Outgoing.at(0)) {
|
||||
revng_assert(Object->kind() == Kinds::Function);
|
||||
checkAndFixModule(Container.getModule(*Object), TargetPointerBits);
|
||||
}
|
||||
|
||||
return { {}, {} };
|
||||
}
|
||||
|
||||
} // namespace revng::pypeline::pipes
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/DecompilationHelpers.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/YAMLTraits.h"
|
||||
|
||||
static Logger Log{ "fold-model-gep" };
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/IRHelpers.h"
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
struct MakeLocalVariables : public llvm::FunctionPass {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "revng/Model/IRHelpers.h"
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/YAMLTraits.h"
|
||||
#include "revng/TypeNames/LLVMTypeNames.h"
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "revng/Model/VerifyHelper.h"
|
||||
#include "revng/Support/BlockType.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/YAMLTraits.h"
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/IRHelpers.h"
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/DecompilationHelpers.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
struct RemoveLoadStore : public llvm::FunctionPass {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
struct RemovePointerCasts : public llvm::FunctionPass {
|
||||
public:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -67,12 +68,12 @@ bool SplitExponentialDataflow::runOnFunction(llvm::Function &F) {
|
||||
Changed = true;
|
||||
auto Location = I.getDebugLoc();
|
||||
B.SetInsertPointPastAllocas(&F, Location);
|
||||
auto *Alloca = B.CreateAlloca(I.getType());
|
||||
auto *Alloca = B.createSimpleAlloca(I.getType());
|
||||
B.SetInsertPoint(&*std::next(I.getIterator()), Location);
|
||||
auto *Load = B.CreateLoad(I.getType(), Alloca);
|
||||
auto *Load = B.createLoadFromVariable(Alloca, I.getType());
|
||||
I.replaceAllUsesWith(Load);
|
||||
B.SetInsertPoint(Load, Location);
|
||||
B.CreateStore(&I, Alloca);
|
||||
B.createStoreToVariable(&I, Alloca);
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -1528,7 +1528,7 @@ private:
|
||||
if constexpr (not IsLegacy) {
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F.getContext());
|
||||
B.SetInsertPointPastAllocas(&F, DL);
|
||||
return B.CreateAlloca(I->getType());
|
||||
return B.createSimpleAlloca(I->getType());
|
||||
} else {
|
||||
revng_assert(I->getType()->isIntOrPtrTy());
|
||||
const model::UpcastableType &VariableType = TheTypeMap.at(I);
|
||||
@@ -1547,6 +1547,8 @@ private:
|
||||
if (auto *I = dyn_cast<Instruction>(ToCopy))
|
||||
DL = I->getDebugLoc();
|
||||
revng::NonDebugInfoCheckingIRBuilder B(InsertBefore, DL);
|
||||
if (auto *Alloca = dyn_cast<AllocaInst>(ToCopy))
|
||||
return B.createLoadFromVariable(Alloca, U->getType());
|
||||
return B.CreateLoad(U->getType(), ToCopy);
|
||||
} else {
|
||||
// TODO: remove when we drop legacy mode.
|
||||
@@ -1580,7 +1582,7 @@ private:
|
||||
if constexpr (not IsLegacy) {
|
||||
revng::NonDebugInfoCheckingIRBuilder B(NextInstruction,
|
||||
ValueToAssign->getDebugLoc());
|
||||
return B.CreateStore(ValueToAssign, LocalVariable);
|
||||
return B.createStoreToVariable(ValueToAssign, LocalVariable);
|
||||
} else {
|
||||
// TODO: drop when we drop legacy mode.
|
||||
return VariableBuilder.createAssignmentBefore(LocalVariable,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
struct TernaryReductionPass : public llvm::FunctionPass {
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
struct TwosComplementArithmeticNormalizationPass : public llvm::FunctionPass {
|
||||
|
||||
+4
-20
@@ -1633,11 +1633,9 @@ private:
|
||||
// Alloca instructions get special handling and are emitted as local
|
||||
// variables in Clift:
|
||||
if (auto *A = llvm::dyn_cast<llvm::AllocaInst>(&I)) {
|
||||
const auto *NumElements = A->getArraySize();
|
||||
|
||||
// Non-constant alloca is not supported:
|
||||
revng_assert(not NumElements
|
||||
or llvm::isa<llvm::ConstantInt>(NumElements));
|
||||
// Dynamic-size allocas are not supported: callers must encode the
|
||||
// size in an `ArrayType` instead of using `alloca`'s ArraySize.
|
||||
revng_assert(not A->isArrayAllocation());
|
||||
|
||||
std::optional<std::string> Handle;
|
||||
|
||||
@@ -1652,21 +1650,7 @@ private:
|
||||
revng_assert(*A->getAllocationSizeInBits(*C.DataLayout) % 8 == 0);
|
||||
llvm::Type *Allocated = A->getAllocatedType();
|
||||
revng_assert(Allocated->isSized());
|
||||
|
||||
if (not Allocated->isArrayTy() and not A->isArrayAllocation()) {
|
||||
Type = C.importLLVMType(Allocated);
|
||||
|
||||
} else {
|
||||
uint64_t FieldBitSize = C.DataLayout->getTypeSizeInBits(Allocated);
|
||||
revng_assert(FieldBitSize % 8 == 0);
|
||||
uint64_t ElementSizeInBytes = FieldBitSize / 8;
|
||||
const auto
|
||||
*NumElements = cast<llvm::ConstantInt>(A->getArraySize());
|
||||
uint64_t NBytes = NumElements->getZExtValue() * ElementSizeInBytes;
|
||||
auto *ByteType = llvm::IntegerType::get(A->getContext(), 8);
|
||||
auto *ByteArrayType = llvm::ArrayType::get(ByteType, NBytes);
|
||||
Type = C.importLLVMType(ByteArrayType);
|
||||
}
|
||||
Type = C.importLLVMType(Allocated);
|
||||
}
|
||||
|
||||
mlir::Location Loc = C.getLocation(A);
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/BasicBlockID.h"
|
||||
#include "revng/Support/Generator.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/TemporaryLLVMOption.h"
|
||||
|
||||
@@ -382,12 +383,12 @@ CFGAnalyzer::State CFGAnalyzer::loadState(revng::IRBuilder &Builder) const {
|
||||
LLVMContext &Context = M.getContext();
|
||||
|
||||
// Load the stack pointer
|
||||
auto *SP0 = createLoad(Builder, GCBI.spReg());
|
||||
auto *SP0 = Builder.createLoad(GCBI.spReg());
|
||||
|
||||
// Load the return address
|
||||
Value *ReturnAddress = nullptr;
|
||||
if (GlobalVariable *Register = GCBI.raReg()) {
|
||||
ReturnAddress = createLoad(Builder, Register);
|
||||
ReturnAddress = Builder.createLoad(Register);
|
||||
} else {
|
||||
auto *OpaquePointer = PointerType::get(Context, 0);
|
||||
auto *StackPointerPointer = Builder.CreateIntToPtr(SP0, OpaquePointer);
|
||||
@@ -409,7 +410,7 @@ CFGAnalyzer::State CFGAnalyzer::loadState(revng::IRBuilder &Builder) const {
|
||||
SmallVector<Value *, 16> CSVs;
|
||||
Type *IsRetTy = Type::getInt128Ty(Context);
|
||||
for (auto *CSR : ABICSVs) {
|
||||
auto *V = createLoad(Builder, CSR);
|
||||
auto *V = Builder.createLoad(CSR);
|
||||
CSVs.emplace_back(V);
|
||||
}
|
||||
|
||||
@@ -1150,7 +1151,7 @@ void CallSummarizer::handleCall(MetaAddress CallerBlock,
|
||||
// Adjust back the stack pointer
|
||||
if (not IsTailCall) {
|
||||
if (MaybeFSO.has_value()) {
|
||||
auto *StackPointer = createLoad(Builder, SPCSV);
|
||||
auto *StackPointer = Builder.createLoad(SPCSV);
|
||||
Value *Offset = ConstantInt::get(StackPointer->getType(), *MaybeFSO);
|
||||
auto *AdjustedStackPointer = Builder.CreateAdd(StackPointer, Offset);
|
||||
Builder.CreateStore(AdjustedStackPointer, SPCSV);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "revng/Pipes/ModelGlobal.h"
|
||||
#include "revng/Support/BasicBlockID.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "revng/EarlyFunctionAnalysis/CallHandler.h"
|
||||
#include "revng/EarlyFunctionAnalysis/Outliner.h"
|
||||
#include "revng/Model/IRHelpers.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
@@ -212,7 +213,7 @@ void Outliner::integrateFunctionCallee(CallHandler *TheCallHandler,
|
||||
PointeeType = CSV->getValueType();
|
||||
} else {
|
||||
PointeeType = GCBI.spReg()->getValueType();
|
||||
Pointer = Builder.CreateIntToPtr(createLoad(Builder, GCBI.spReg()),
|
||||
Pointer = Builder.CreateIntToPtr(Builder.createLoad(GCBI.spReg()),
|
||||
PointeeType->getPointerTo());
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "revng/EarlyFunctionAnalysis/PromoteGlobalToLocalVars.h"
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
|
||||
@@ -48,7 +49,7 @@ PromoteGlobalToLocalPass::run(llvm::Function &F,
|
||||
|
||||
// Load all the CSVs and store their value onto the local variables.
|
||||
for (const auto &[CSV, Alloca] : CSVMap)
|
||||
Builder.CreateStore(createLoad(Builder, CSV), Alloca);
|
||||
Builder.CreateStore(Builder.createLoad(CSV), Alloca);
|
||||
|
||||
return PreservedAnalyses::none();
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "revng/Pipes/RootKind.h"
|
||||
#include "revng/Pipes/TaggedFunctionKind.h"
|
||||
#include "revng/Support/BlockType.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
@@ -292,7 +293,7 @@ static Value *loadCSVOrUndef(revng::IRBuilder &Builder,
|
||||
auto *Type = IntegerType::get(M->getContext(), Size * 8);
|
||||
return UndefValue::get(Type);
|
||||
} else {
|
||||
return createLoad(Builder, CSV);
|
||||
return Builder.createLoad(CSV);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/Pipes/RootKind.h"
|
||||
#include "revng/Pipes/TaggedFunctionKind.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
using std::tuple;
|
||||
@@ -167,7 +168,7 @@ public:
|
||||
auto Name = model::Register::getCSVName(Register);
|
||||
GlobalVariable *CSV = RootModule.getGlobalVariable(Name, true);
|
||||
revng_assert(CSV != nullptr);
|
||||
Arguments.push_back(createLoad(Builder, CSV));
|
||||
Arguments.push_back(Builder.createLoad(CSV));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "revng/Pipes/StringMap.h"
|
||||
#include "revng/Pipes/TaggedFunctionKind.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/SimplePassManager.h"
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/Pipes/RootKind.h"
|
||||
#include "revng/Pipes/TaggedFunctionKind.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
@@ -227,7 +228,7 @@ Function *PromoteCSVs::createWrapper(const WrapperKey &Key) {
|
||||
// Update values of the out arguments
|
||||
unsigned OutArgument = FirstOutArgument;
|
||||
for (GlobalVariable *CSV : Written) {
|
||||
Builder.CreateStore(createLoad(Builder, CSV),
|
||||
Builder.CreateStore(Builder.createLoad(CSV),
|
||||
HelperWrapper->getArg(OutArgument));
|
||||
++OutArgument;
|
||||
}
|
||||
@@ -283,7 +284,7 @@ void PromoteCSVs::wrap(CallInst *Call,
|
||||
|
||||
// Add arguments read
|
||||
for (GlobalVariable *CSV : Read)
|
||||
NewArguments.push_back(createLoad(Builder, CSV));
|
||||
NewArguments.push_back(Builder.createLoad(CSV));
|
||||
|
||||
SmallVector<AllocaInst *, 16> WrittenCSVAllocas;
|
||||
for (GlobalVariable *CSV : Written) {
|
||||
@@ -300,7 +301,7 @@ void PromoteCSVs::wrap(CallInst *Call,
|
||||
|
||||
// Restore into CSV the written registers
|
||||
for (const auto &[CSV, Alloca] : zip(Written, WrittenCSVAllocas))
|
||||
Builder.CreateStore(createLoad(Builder, Alloca), CSV);
|
||||
Builder.CreateStore(Builder.createLoad(Alloca), CSV);
|
||||
|
||||
// Erase the old call
|
||||
eraseFromParent(Call);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "revng/FunctionIsolation/StructInitializers.h"
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
@@ -333,7 +333,8 @@ AccessFixer::decomposeMemcpy(llvm::Instruction &I) {
|
||||
BasicBlock &Entry = I.getFunction()->getEntryBlock();
|
||||
Builder.SetInsertPoint(&Entry, Entry.begin());
|
||||
auto *UInt8Type = IntegerType::getInt8Ty(Abort.getContext());
|
||||
auto *Storage = Builder.CreateAlloca(UInt8Type, 0, Size);
|
||||
auto *StorageType = ArrayType::get(UInt8Type, Size->getZExtValue());
|
||||
auto *Storage = Builder.CreateAlloca(StorageType);
|
||||
uint64_t Alignment = Storage->getAlign().value();
|
||||
auto &Read = Call;
|
||||
auto &Write = *cast<CallInst>(Call.clone());
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "revng/Model/RawBinaryView.h"
|
||||
#include "revng/Support/CommandLine.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/SimplePassManager.h"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "llvm/IR/PassManager.h"
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using CSVToAllocaMap = llvm::DenseMap<llvm::GlobalVariable *,
|
||||
@@ -42,7 +43,7 @@ public:
|
||||
std::back_inserter(Arguments));
|
||||
|
||||
for (GlobalVariable *CSV : ReadCSVs)
|
||||
Arguments.push_back(createLoadVariable(Builder, csvToAlloca(CSV)));
|
||||
Arguments.push_back(Builder.createLoadVariable(csvToAlloca(CSV)));
|
||||
|
||||
CallInst *Result = Builder.CreateCall(getRandom(M, ReturnType), Arguments);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "revng/BasicAnalyses/GeneratedCodeBasicInfo.h"
|
||||
#include "revng/Model/ProgramCounterHandler.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
#include "ExternalJumpsHandler.h"
|
||||
|
||||
@@ -47,7 +48,7 @@ BasicBlock *ExternalJumpsHandler::createReturnFromExternal() {
|
||||
// Identify the global variables to be serialized
|
||||
GlobalVariable *SavedRegistersPtr = TheModule.getGlobalVariable("saved_"
|
||||
"registers");
|
||||
Instruction *SavedRegisters = createLoad(Builder, SavedRegistersPtr);
|
||||
Instruction *SavedRegisters = Builder.createLoad(SavedRegistersPtr);
|
||||
|
||||
// TODO: if we do not support this architecture, here things will be
|
||||
// completely broken
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "revng/Lift/VariableManager.h"
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/RandomAccessIterator.h"
|
||||
#include "revng/Support/Range.h"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "revng/Lift/LibTcg.h"
|
||||
#include "revng/Model/ProgramCounterHandler.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
#include "JumpTargetManager.h"
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "revng/Lift/Lift.h"
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/SimplePassManager.h"
|
||||
#include "revng/Support/Statistics.h"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "revng/ABI/FunctionType/Layout.h"
|
||||
#include "revng/BasicAnalyses/ShrinkInstructionOperandsPass.h"
|
||||
#include "revng/FunctionCallIdentification/FunctionCallIdentification.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueRegisterUser.h"
|
||||
#include "revng/Support/Statistics.h"
|
||||
@@ -546,7 +547,7 @@ RootAnalyzer::promoteCSVsToAlloca(Function *OptimizedFunction) {
|
||||
replaceAllUsesInFunctionWith(OptimizedFunction, CSV, Alloca);
|
||||
|
||||
// Initialize the alloca
|
||||
InitBuilder.CreateStore(createLoad(InitBuilder, CSV), Alloca);
|
||||
InitBuilder.CreateStore(InitBuilder.createLoad(CSV), Alloca);
|
||||
}
|
||||
|
||||
return CSVMap;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||
|
||||
#include "revng/Model/Binary.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
|
||||
#include "DropHelperCallsPass.h"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/CommandLine.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
// This name corresponds to a function in `early-linked`.
|
||||
@@ -243,7 +244,7 @@ VariableManager::storeToCPUStateOffset(revng::IRBuilder &Builder,
|
||||
|
||||
if (BitMask != 0 and StoreSize != FieldSize) {
|
||||
// Load the value
|
||||
auto *LoadEnvField = createLoad(Builder, Target);
|
||||
auto *LoadEnvField = Builder.createLoad(Target);
|
||||
|
||||
auto *Blanked = Builder.CreateAnd(LoadEnvField, BitMask);
|
||||
|
||||
@@ -268,7 +269,7 @@ Value *VariableManager::loadFromCPUStateOffset(revng::IRBuilder &Builder,
|
||||
return nullptr;
|
||||
|
||||
// Load the whole field
|
||||
auto *LoadEnvField = createLoad(Builder, Target);
|
||||
auto *LoadEnvField = Builder.createLoad(Target);
|
||||
|
||||
// Extract the desired part
|
||||
// Shift right of the desired amount
|
||||
@@ -351,7 +352,7 @@ void VariableManager::memOpAtEnvOffset(revng::IRBuilder &Builder,
|
||||
StoreInst *New = nullptr;
|
||||
if (EnvIsSrc) {
|
||||
revng_assert(not IsMemset);
|
||||
New = Builder.CreateStore(createLoad(Builder, EnvVar), OtherPtr);
|
||||
New = Builder.CreateStore(Builder.createLoad(EnvVar), OtherPtr);
|
||||
} else {
|
||||
Type *CSVType = EnvVar->getValueType();
|
||||
Value *ToStore = nullptr;
|
||||
|
||||
@@ -150,7 +150,7 @@ LegacyVB::createLocalVariable(const model::Type &VariableType) {
|
||||
// Here we should definitely use the builder that checks the debug info,
|
||||
// but since this going to go away soon, let it stay as is.
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *F);
|
||||
B.setInsertPointToFirstNonAlloca(*F);
|
||||
Constant *ReferenceString = toLLVMString(VariableType, *F->getParent());
|
||||
return B.CreateCall(LocalVarFunction, { ReferenceString });
|
||||
}
|
||||
@@ -189,7 +189,7 @@ LegacyVB::createCallStackArgumentVariable(const model::Type &VariableType) {
|
||||
llvm::Constant *VarTypeString = toLLVMString(VariableType, *F->getParent());
|
||||
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *F);
|
||||
B.setInsertPointToFirstNonAlloca(*F);
|
||||
|
||||
Value *Size = ConstantInt::get(Types.InputPointerSizedInteger, VariableSize);
|
||||
Instruction *Reference = B.CreateCall(getCallStackArgumentsAllocator(),
|
||||
@@ -214,7 +214,7 @@ LegacyVB::createStackFrameVariable(model::UpcastableType FrameType) {
|
||||
revng_assert(StackSize);
|
||||
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *F);
|
||||
B.setInsertPointToFirstNonAlloca(*F);
|
||||
|
||||
Instruction
|
||||
*Reference = B.CreateCall(getStackFrameAllocator(),
|
||||
@@ -301,7 +301,7 @@ VB::LocalVarType *VB::createLocalVariable(const model::Type &VariableType) {
|
||||
revng_assert(VariableSize);
|
||||
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *F);
|
||||
B.setInsertPointToFirstNonAlloca(*F);
|
||||
|
||||
return B.CreateAlloca(llvm::ArrayType::get(Types.Int8Ty, VariableSize));
|
||||
}
|
||||
@@ -310,7 +310,7 @@ template<>
|
||||
std::pair<VB::LocalVarType *, llvm::Instruction *>
|
||||
VB::createLocalVariableAndTakeIntAddress(const model::Type &VariableType) {
|
||||
revng::NonDebugInfoCheckingIRBuilder B(F->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *F);
|
||||
B.setInsertPointToFirstNonAlloca(*F);
|
||||
auto *Variable = createLocalVariable(VariableType);
|
||||
return {
|
||||
Variable,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/ProgramCounterHandler.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
namespace FunctionTags {
|
||||
|
||||
@@ -84,7 +84,8 @@ private:
|
||||
sqlite::Database Database;
|
||||
|
||||
public:
|
||||
PrototypeDatabase(llvm::StringRef Path) : Database(Path) {}
|
||||
PrototypeDatabase(llvm::StringRef Path) :
|
||||
Database(Path, sqlite::Database::OpenMode::ReadOnly) {}
|
||||
|
||||
/// Find a platform by its exact name.
|
||||
/// Returns -1 if no platform with that name exists.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/ProgramCounterHandler.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
// This name corresponds to a function in `early-linked`.
|
||||
RegisterIRHelper SetMetaAddressHelper("set_PlainMetaAddress");
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
}
|
||||
|
||||
Value *loadJumpablePC(revng::IRBuilder &Builder) const final {
|
||||
return createLoad(Builder, AddressCSV);
|
||||
return Builder.createLoad(AddressCSV);
|
||||
}
|
||||
|
||||
std::array<Value *, 4>
|
||||
@@ -156,10 +157,10 @@ private:
|
||||
}
|
||||
|
||||
Value *loadJumpablePC(revng::IRBuilder &Builder) const final {
|
||||
auto *Address = createLoad(Builder, AddressCSV);
|
||||
auto *Address = Builder.createLoad(AddressCSV);
|
||||
auto *AddressType = Address->getType();
|
||||
return Builder.CreateOr(Address,
|
||||
Builder.CreateZExt(createLoad(Builder, IsThumb),
|
||||
Builder.CreateZExt(Builder.createLoad(IsThumb),
|
||||
AddressType));
|
||||
}
|
||||
|
||||
@@ -411,10 +412,10 @@ static void setPlainMetaAddressImpl(revng::IRBuilder &Builder,
|
||||
void PCH::setCurrentPCPlainMetaAddress(revng::IRBuilder &Builder) const {
|
||||
setPlainMetaAddressImpl(Builder,
|
||||
"current_pc",
|
||||
createLoad(Builder, EpochCSV),
|
||||
createLoad(Builder, AddressSpaceCSV),
|
||||
createLoad(Builder, TypeCSV),
|
||||
createLoad(Builder, AddressCSV));
|
||||
Builder.createLoad(EpochCSV),
|
||||
Builder.createLoad(AddressSpaceCSV),
|
||||
Builder.createLoad(TypeCSV),
|
||||
Builder.createLoad(AddressCSV));
|
||||
}
|
||||
|
||||
void PCH::setLastPCPlainMetaAddress(revng::IRBuilder &Builder,
|
||||
@@ -618,10 +619,10 @@ public:
|
||||
bool Empty = Root->case_begin() == Root->case_end();
|
||||
if (Empty) {
|
||||
revng::NonDebugInfoCheckingIRBuilder Builder(Root);
|
||||
CurrentEpoch = createLoad(Builder, EpochCSV);
|
||||
CurrentAddressSpace = createLoad(Builder, AddressSpaceCSV);
|
||||
CurrentType = createLoad(Builder, TypeCSV);
|
||||
CurrentAddress = createLoad(Builder, AddressCSV);
|
||||
CurrentEpoch = Builder.createLoad(EpochCSV);
|
||||
CurrentAddressSpace = Builder.createLoad(AddressSpaceCSV);
|
||||
CurrentType = Builder.createLoad(TypeCSV);
|
||||
CurrentAddress = Builder.createLoad(AddressCSV);
|
||||
} else {
|
||||
// Get the switches of the the first MA. This is just in order to get a
|
||||
// reference to their conditions
|
||||
@@ -819,10 +820,10 @@ PCH::buildDispatcher(DispatcherTargets &Targets,
|
||||
});
|
||||
|
||||
// First of all, create code to load the components of the MetaAddress
|
||||
Value *CurrentEpoch = createLoad(Builder, EpochCSV);
|
||||
Value *CurrentAddressSpace = createLoad(Builder, AddressSpaceCSV);
|
||||
Value *CurrentType = createLoad(Builder, TypeCSV);
|
||||
Value *CurrentAddress = createLoad(Builder, AddressCSV);
|
||||
Value *CurrentEpoch = Builder.createLoad(EpochCSV);
|
||||
Value *CurrentAddressSpace = Builder.createLoad(AddressSpaceCSV);
|
||||
Value *CurrentType = Builder.createLoad(TypeCSV);
|
||||
Value *CurrentAddress = Builder.createLoad(AddressCSV);
|
||||
|
||||
SwitchManager SM(Default,
|
||||
CurrentEpoch,
|
||||
@@ -952,7 +953,7 @@ void PCH::buildHotPath(revng::IRBuilder &B,
|
||||
auto &[Address, BB] = CandidateTarget;
|
||||
|
||||
auto CreateCmp = [&B](GlobalVariable *CSV, uint64_t Value) {
|
||||
Instruction *Load = createLoad(B, CSV);
|
||||
Instruction *Load = B.createLoad(CSV);
|
||||
Type *LoadType = Load->getType();
|
||||
return B.CreateICmpEQ(Load, ConstantInt::get(LoadType, Value));
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@ model::TypeDefinition::trySize(VerifyHelper &VH) const {
|
||||
Result = rc_recur E->UnderlyingType()->trySize(VH);
|
||||
|
||||
} else if (auto *T = llvm::dyn_cast<model::TypedefDefinition>(this)) {
|
||||
// TODO: in case of a recursive type (not via a pointer), we'll get an
|
||||
// assertion, instead of a clean failure
|
||||
Result = rc_recur T->UnderlyingType()->trySize(VH);
|
||||
|
||||
} else if (auto *S = llvm::dyn_cast<model::StructDefinition>(this)) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "revng/ABI/Analyses/ConvertFunctionsToCABI.h"
|
||||
#include "revng/ABI/Analyses/ConvertFunctionsToRaw.h"
|
||||
#include "revng/Canonicalize/FixPointerSize.h"
|
||||
#include "revng/Canonicalize/SimplifySwitch.h"
|
||||
#include "revng/Canonicalize/SwitchToStatements.h"
|
||||
#include "revng/CliftPipes/Clifter.h"
|
||||
@@ -93,6 +94,7 @@ REGISTER(Container, TranslatedContainer);
|
||||
|
||||
using namespace revng::pypeline::pipes;
|
||||
|
||||
REGISTER(Pipe, FixPointerSize);
|
||||
REGISTER(Pipe, PureLLVMPassesPipe);
|
||||
REGISTER(Pipe, PureLLVMPassesRootPipe);
|
||||
REGISTER(Pipe, PureMLIRPassesPipe);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/PromoteStackPointer/InjectStackSizeProbesAtCallSites.h"
|
||||
#include "revng/PromoteStackPointer/InjectStackSizeProbesAtCallSitesPass.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
// This name is not present after `CleanupStackSizeMarkers`.
|
||||
RegisterIRHelper StackSizeAtCallSite("stack_size_at_call_site");
|
||||
@@ -33,9 +34,9 @@ static bool injectStackSizeProbesAtCallSites(llvm::Module &M,
|
||||
for (Function &F : FunctionTags::Isolated.functions(&M)) {
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
setInsertPointToFirstNonAlloca(B, F);
|
||||
B.setInsertPointToFirstNonAlloca(F);
|
||||
|
||||
auto *SP0 = createLoad(B, SP);
|
||||
auto *SP0 = B.createLoad(SP);
|
||||
|
||||
for (BasicBlock &BB : F) {
|
||||
for (Instruction &I : BB) {
|
||||
@@ -45,7 +46,7 @@ static bool injectStackSizeProbesAtCallSites(llvm::Module &M,
|
||||
B.SetInsertPoint(&I);
|
||||
|
||||
// Inject a call to the marker. First argument is sp - sp0
|
||||
auto *Call = B.CreateCall(SSACS, B.CreateSub(SP0, createLoad(B, SP)));
|
||||
auto *Call = B.CreateCall(SSACS, B.CreateSub(SP0, B.createLoad(SP)));
|
||||
Call->copyMetadata(I);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/IRHelpers.h"
|
||||
#include "revng/PromoteStackPointer/InstrumentStackAccessesPass.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "revng/PromoteStackPointer/PromoteStackPointerPass.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
// This name is not present after `promote-stack-pointer`.
|
||||
RegisterIRHelper UndefinedLocalSPMarker("revng_undefined_local_sp");
|
||||
@@ -77,7 +78,7 @@ static bool adjustStackAfterCalls(const model::Binary &Binary,
|
||||
Changed = true;
|
||||
|
||||
B.SetInsertPoint(I.getNextNode());
|
||||
B.CreateStore(B.CreateAdd(createLoad(B, GlobalSP), FSO), GlobalSP);
|
||||
B.CreateStore(B.CreateAdd(B.createLoad(GlobalSP), FSO), GlobalSP);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +170,7 @@ static bool promoteStackPointer(const model::Binary &Binary,
|
||||
AllocaInst *LocalSP = Builder.CreateAlloca(SPType, nullptr, "local_sp");
|
||||
|
||||
// Call InitLocalSP, to initialize the value of the local stack pointer.
|
||||
setInsertPointToFirstNonAlloca(Builder, F);
|
||||
Builder.setInsertPointToFirstNonAlloca(F);
|
||||
auto *SPVal = Builder.CreateCall(InitLocalSP);
|
||||
|
||||
// Store the initial SP value in the new alloca.
|
||||
|
||||
@@ -1230,7 +1230,7 @@ void SegregateFunctionStack<Legacy>::upgrade() {
|
||||
|
||||
// TODO: the checks should be enabled conditionally based on the user.
|
||||
revng::NonDebugInfoCheckingIRBuilder B(NewFunction->getContext());
|
||||
setInsertPointToFirstNonAlloca(B, *NewFunction);
|
||||
B.setInsertPointToFirstNonAlloca(*NewFunction);
|
||||
|
||||
lowerArguments(B);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/RemoveExtractValues/RemoveExtractValuesPass.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/Model/LoadModelPass.h"
|
||||
#include "revng/RemoveLiftingArtifacts/CleanupIR.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -83,20 +85,19 @@ bool CleanupIRPass::Impl::replaceInstructions(Function &F) {
|
||||
FunctionTags::AllocatesLocalVariable)) {
|
||||
revng::IRBuilder Builder(Context);
|
||||
Builder.SetInsertPointPastAllocas(Call->getFunction());
|
||||
Value *AllocatedSize = nullptr;
|
||||
uint64_t AllocatedBytes = 0;
|
||||
if (auto *Callee = getCalledFunction(Call);
|
||||
Callee and Callee->getName().startswith("revng_stack_frame")) {
|
||||
AllocatedSize = Call->getArgOperand(0);
|
||||
auto *Size = cast<ConstantInt>(Call->getArgOperand(0));
|
||||
AllocatedBytes = Size->getZExtValue();
|
||||
} else {
|
||||
model::UpcastableType
|
||||
AllocatedType = fromLLVMString(Call->getArgOperand(0), Model);
|
||||
AllocatedSize = ConstantInt::get(Context,
|
||||
APInt(/*NumBits*/ 64,
|
||||
AllocatedType->size().value()));
|
||||
AllocatedBytes = AllocatedType->size().value();
|
||||
}
|
||||
auto *Int8Type = IntegerType::getInt8Ty(Context);
|
||||
auto *Alloca = Builder.CreateAlloca(Int8Type,
|
||||
/* ArraySize */ AllocatedSize);
|
||||
auto *Alloca = Builder.CreateAlloca(ArrayType::get(Int8Type,
|
||||
AllocatedBytes));
|
||||
|
||||
// Some uses of the Call can be replaced directly with GEPs in the Alloca.
|
||||
for (Use &U : Call->uses()) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "revng/Pipes/Kinds.h"
|
||||
#include "revng/RemoveLiftingArtifacts/MakeSegmentRef.h"
|
||||
#include "revng/Support/Debug.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
#include "revng/Support/MetaAddress.h"
|
||||
#include "revng/Support/OpaqueFunctionsPool.h"
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "revng/RestructureCFG/ScopeGraphGraphTraits.h"
|
||||
#include "revng/RestructureCFG/ScopeGraphUtils.h"
|
||||
#include "revng/Support/GraphAlgorithms.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "revng/Model/FunctionTags.h"
|
||||
#include "revng/RestructureCFG/ScopeGraphUtils.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
#include "revng/Support/IRHelpers.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "revng/RestructureCFG/ASTTree.h"
|
||||
#include "revng/RestructureCFG/ExprNode.h"
|
||||
#include "revng/Support/Assert.h"
|
||||
#include "revng/Support/IRBuilder.h"
|
||||
|
||||
#include "SimplifyHybridNot.h"
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ revng_add_library_internal(
|
||||
CommonOptions.cpp
|
||||
CustomizedLLVMPasses.cpp
|
||||
Debug.cpp
|
||||
DropRedundantPtrIntCasts.cpp
|
||||
ExplicitSpecializations.cpp
|
||||
FileSystem.cpp
|
||||
InitRevng.cpp
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
//
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
/// `inttoptr` already does an implicit zero-extension when its operand is
|
||||
/// narrower than the target pointer, and `ptrtoint` already truncates when the
|
||||
/// target integer is narrower than the pointer.
|
||||
/// This pass exploits this fact turning:
|
||||
///
|
||||
/// %w = zext iN %x to iM
|
||||
/// %p = inttoptr iM %w to ptr
|
||||
/// %w = ptrtoint ptr %p to iM
|
||||
/// %t = trunc iM %w to iN
|
||||
///
|
||||
/// into:
|
||||
///
|
||||
/// %p = inttoptr iN %x to ptr
|
||||
/// %t = ptrtoint ptr %p to iN
|
||||
///
|
||||
/// \note instcombine reverts these changes, so you might want to run this
|
||||
// close to the leaves of your pipeline.
|
||||
struct DropRedundantPtrIntCasts : public FunctionPass {
|
||||
static char ID;
|
||||
|
||||
DropRedundantPtrIntCasts() : FunctionPass(ID) {}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
bool Changed = false;
|
||||
SmallVector<Instruction *, 16> ToErase;
|
||||
|
||||
for (auto &I : llvm::instructions(F)) {
|
||||
if (auto *IntToPtr = dyn_cast<IntToPtrInst>(&I)) {
|
||||
if (auto *ZeroExtend = dyn_cast<ZExtInst>(IntToPtr->getOperand(0))) {
|
||||
IRBuilder<> B(IntToPtr);
|
||||
auto *New = B.CreateIntToPtr(ZeroExtend->getOperand(0),
|
||||
IntToPtr->getType());
|
||||
if (auto *NewI = dyn_cast<Instruction>(New))
|
||||
NewI->copyMetadata(*IntToPtr);
|
||||
IntToPtr->replaceAllUsesWith(New);
|
||||
ToErase.push_back(IntToPtr);
|
||||
Changed = true;
|
||||
}
|
||||
} else if (auto *TR = dyn_cast<TruncInst>(&I)) {
|
||||
if (auto *PtrToInt = dyn_cast<PtrToIntInst>(TR->getOperand(0))) {
|
||||
IRBuilder<> B(TR);
|
||||
auto *New = B.CreatePtrToInt(PtrToInt->getPointerOperand(),
|
||||
TR->getType());
|
||||
if (auto *NewI = dyn_cast<Instruction>(New))
|
||||
NewI->copyMetadata(*TR);
|
||||
TR->replaceAllUsesWith(New);
|
||||
ToErase.push_back(TR);
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto *I : ToErase)
|
||||
I->eraseFromParent();
|
||||
|
||||
return Changed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
char DropRedundantPtrIntCasts::ID = 0;
|
||||
|
||||
using Register = RegisterPass<DropRedundantPtrIntCasts>;
|
||||
static Register X("drop-redundant-ptrint-casts", "", false, false);
|
||||
@@ -396,6 +396,8 @@ branches:
|
||||
container: llvm-functions
|
||||
category: debug
|
||||
filename: clifter_input.bc
|
||||
- pipe: fix-pointer-size
|
||||
arguments: [llvm-functions]
|
||||
- pipe: clifter
|
||||
arguments: [llvm-functions, clift-functions]
|
||||
artifacts:
|
||||
|
||||
@@ -17,5 +17,5 @@ commands:
|
||||
- type: source
|
||||
filter: db-invariants
|
||||
command: |-
|
||||
sqlite3 "$SOURCES_ROOT/share/revng/prototypes.sqlite" < "$INPUT"
|
||||
sqlite3 -cmd ".open \"file:$SOURCES_ROOT/share/revng/prototypes.sqlite?immutable=1\"" < "$INPUT"
|
||||
| FileCheck "$INPUT"
|
||||
|
||||
@@ -16,7 +16,7 @@ commands:
|
||||
|
||||
revng model override-by-name
|
||||
"$OUTPUT/context/model.yml"
|
||||
${SOURCE}.override.yml
|
||||
${SOURCE}.override.$QEMU_NAME.yml
|
||||
> "$OUTPUT/context/model-tmp.yml";
|
||||
mv "$OUTPUT/context/model-tmp.yml" "$OUTPUT/context/model.yml";
|
||||
|
||||
@@ -25,6 +25,7 @@ commands:
|
||||
revng analyze --resume "$OUTPUT" detect-stack-size "$INPUT" -o /dev/null;
|
||||
|
||||
revng artifact --resume "$OUTPUT" segregate-stack-accesses "$INPUT" |
|
||||
revng opt -S | FileCheck ${SOURCE}.filecheck.ll;
|
||||
revng opt -remove-llvmassume-calls -instcombine-noarrays -sroa-noarrays -drop-redundant-ptrint-casts -dce -type-shrinking -dce -drop-redundant-ptrint-casts -early-cse -instsimplify -dce -S |
|
||||
FileCheck --check-prefix=CHECK-$QEMU_NAME ${SOURCE}.filecheck.ll;
|
||||
|
||||
revng artifact --resume "$OUTPUT" emit-c "$INPUT" -o /dev/null;
|
||||
|
||||
+308
-139
@@ -2,163 +2,332 @@
|
||||
; This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
;
|
||||
|
||||
CHECK: define i64 @local_raw_primitives_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: add i64 [[IGN:.*]]%[[ARG1]]
|
||||
CHECK-DAG: add i64 [[IGN:.*]]%[[ARG2]]
|
||||
CHECK: }
|
||||
; This file mixes checks for what we expect to happen on a x86-64 binarya and an
|
||||
; i386 binary. In this case, the i386 binary is interesting due to SystemV ABI
|
||||
; making heavy use of stack arguments.
|
||||
|
||||
CHECK: define i64 @local_call_raw_primitives_on_registers() [[IGN:.*]] {
|
||||
CHECK-DAG: = call i64 @local_raw_primitives_on_registers(i64 2, i64 1)
|
||||
CHECK: }
|
||||
; raw_primitives_on_registers
|
||||
|
||||
CHECK: define i64 @local_raw_pointers_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[ARG1_PTR:.*]] = inttoptr i64 %[[ARG1]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[ARG1_PTR:.*]]
|
||||
CHECK-DAG: %[[ARG2_PTR:.*]] = inttoptr i64 %[[ARG2]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[ARG2_PTR]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_raw_primitives_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: add i64 [[IGN:.*]]%[[ARG1]]
|
||||
CHECK-x86_64-DAG: add i64 [[IGN:.*]]%[[ARG2]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_call_raw_pointers_on_registers() [[IGN:.*]] {
|
||||
CHECK-DAG: = call i64 @local_raw_pointers_on_registers(i64 [[ARG:.*]], i64 [[ARG]])
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_call_raw_primitives_on_registers() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: = call i64 @local_raw_primitives_on_registers(i64 2, i64 1)
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_raw_primitives_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[STACK_ARG8:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-DAG: %[[STACK_ARG8_PTR:.*]] = inttoptr i64 %[[STACK_ARG8]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[STACK_ARG8_PTR:.*]]
|
||||
CHECK-DAG: %[[STACK_ARG_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[STACK_ARG_PTR]]
|
||||
CHECK: }
|
||||
; raw_pointers_on_registers
|
||||
|
||||
CHECK: define i64 @local_call_raw_primitives_on_stack() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-DAG: store i64 8, ptr %[[STACK_8]]
|
||||
CHECK-DAG: store i64 7, ptr %[[STACK]]
|
||||
CHECK-DAG: = call i64 @local_raw_primitives_on_stack(i64 4, i64 3, i64 2, i64 1, i64 5, i64 6, i64 %[[STACK_INT]])
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_raw_pointers_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[ARG1_PTR:.*]] = inttoptr i64 %[[ARG1]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[ARG1_PTR]]
|
||||
CHECK-x86_64-DAG: %[[ARG2_PTR:.*]] = inttoptr i64 %[[ARG2]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[ARG2_PTR]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_cabi_primitives_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: add i64 [[IGN:.*]]%[[ARG1]]
|
||||
CHECK-DAG: add i64 [[IGN:.*]]%[[ARG2]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_call_raw_pointers_on_registers() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: = call i64 @local_raw_pointers_on_registers(i64 [[ARG:.*]], i64 [[ARG]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_call_cabi_primitives_on_registers() [[IGN:.*]] {
|
||||
CHECK-DAG: = call i64 @local_cabi_primitives_on_registers(i64 1, i64 2)
|
||||
CHECK: }
|
||||
; raw_primitives_on_stack
|
||||
|
||||
CHECK: define i64 @local_cabi_primitives_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG1:.*]], i64 %[[STACK_ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[IGN:.*]] = add i64 %[[IGN:.*]]%[[STACK_ARG1]]
|
||||
CHECK-DAG: %[[IGN:.*]] = add i64 %[[IGN:.*]]%[[STACK_ARG2]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_raw_primitives_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[STACK_ARG8:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-x86_64-DAG: %[[STACK_ARG8_PTR:.*]] = inttoptr i64 %[[STACK_ARG8]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[STACK_ARG8_PTR]]
|
||||
CHECK-x86_64-DAG: %[[STACK_ARG_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[STACK_ARG_PTR]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_call_cabi_primitives_on_stack() [[IGN:.*]] {
|
||||
CHECK-DAG: = call i64 @local_cabi_primitives_on_stack(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 [[SCALAR1:.*]], i64 [[SCALAR2:.*]])
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_call_raw_primitives_on_stack() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-x86_64-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 8, ptr %[[STACK_8]]
|
||||
CHECK-x86_64-DAG: store i64 7, ptr %[[STACK]]
|
||||
CHECK-x86_64-DAG: = call i64 @local_raw_primitives_on_stack(i64 4, i64 3, i64 2, i64 1, i64 5, i64 6, i64 %[[STACK_INT]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_cabi_aggregate_on_registers(i64 %[[ARG1:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[ARG1]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[ARG1]], 8
|
||||
CHECK-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD2_PTR]], align 8
|
||||
CHECK: }
|
||||
; cabi_primitives_on_registers
|
||||
|
||||
CHECK: define i64 @local_call_cabi_aggregate_on_registers() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-DAG: = call i64 @local_cabi_aggregate_on_registers(i64 %[[STACK_INT]])
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_cabi_primitives_on_registers(i64 %[[ARG1:.*]], i64 %[[ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: add i64 [[IGN:.*]]%[[ARG1]]
|
||||
CHECK-x86_64-DAG: add i64 [[IGN:.*]]%[[ARG2]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_cabi_aggregate_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD2_PTR]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_call_cabi_primitives_on_registers() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: = call i64 @local_cabi_primitives_on_registers(i64 1, i64 2)
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_call_cabi_aggregate_on_stack() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-DAG: = call i64 @local_cabi_aggregate_on_stack(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 %[[STACK_INT]])
|
||||
CHECK: }
|
||||
CHECK-i386: define i32 @local_cabi_primitives_on_registers(i32 %[[A:.*]], i32 %[[B:.*]]) [[IGN:.*]] {
|
||||
CHECK-i386-DAG: %[[T1:.*]] = add i32 {{.*}}, %[[A]]
|
||||
CHECK-i386-DAG: %[[T2:.*]] = add i32 %[[T1]], %[[B]]
|
||||
CHECK-i386: ret i32 %[[T2]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK: define i64 @local_cabi_aggregate_on_stack_and_registers(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-DAG: load i64, ptr %[[FIELD2_PTR]]
|
||||
CHECK: }
|
||||
CHECK-i386: define i32 @local_call_cabi_primitives_on_registers() [[IGN:.*]] {
|
||||
CHECK-i386: %[[CALL:.*]] = call i32 @local_cabi_primitives_on_registers(i32 1, i32 2)
|
||||
CHECK-i386: %[[RET:.*]] = add i32 %[[CALL]], {{.*}}
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK: define i64 @local_call_cabi_aggregate_on_stack_and_registers() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-DAG: = call i64 @local_cabi_aggregate_on_stack_and_registers(i64 1, i64 2, i64 3, i64 4, i64 5, i64 %[[STACK_INT]])
|
||||
CHECK: }
|
||||
; cabi_primitives_on_stack
|
||||
|
||||
CHECK: define <{ i64, i64 }> @local_raw_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[RESULT:.*]] = call <{ i64, i64 }> @struct_initializer(i64 124, i64 123)
|
||||
CHECK-DAG: ret <{ i64, i64 }> %[[RESULT]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_cabi_primitives_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG1:.*]], i64 %[[STACK_ARG2:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[IGN:.*]] = add i64 %[[IGN:.*]]%[[STACK_ARG1]]
|
||||
CHECK-x86_64-DAG: %[[IGN:.*]] = add i64 %[[IGN:.*]]%[[STACK_ARG2]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define i64 @local_call_raw_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK: %[[RESULT:.*]] = call <{ i64, i64 }> @local_raw_return_small_aggregate()
|
||||
CHECK-DAG: call i64 @OpaqueExtractvalue(<{ i64, i64 }> %[[RESULT]], i64 1)
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_call_cabi_primitives_on_stack() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: = call i64 @local_cabi_primitives_on_stack(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 [[SCALAR1:.*]], i64 [[SCALAR2:.*]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK: define [16 x i8] @local_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[RETURN_ALLOCA:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT_8:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 8
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_8:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_8]] to ptr
|
||||
CHECK-DAG: store i64 124, ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-DAG: store i64 123, ptr %[[RETURN_ALLOCA_8]]
|
||||
CHECK-DAG: %[[TO_RETURN:.*]] = load [16 x i8], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-DAG: ret [16 x i8] %[[TO_RETURN]]
|
||||
CHECK: }
|
||||
CHECK-i386: define i32 @local_cabi_primitives_on_stack(i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[G:.*]], i32 %[[H:.*]]) [[IGN:.*]] {
|
||||
CHECK-i386: %[[T1:.*]] = add i32 {{.*}}, %[[G]]
|
||||
CHECK-i386: %[[T2:.*]] = add i32 %[[T1]], %[[H]]
|
||||
CHECK-i386: ret i32 %[[T2]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK: define i64 @local_call_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[RETURN_ALLOCA:.*]] = alloca [16 x i8]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-DAG: %[[RETURN_VALUE:.*]] = call [16 x i8] @local_cabi_return_small_aggregate()
|
||||
CHECK-DAG: store [16 x i8] %[[RETURN_VALUE]], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT_8:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 8
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_8:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_8]] to ptr
|
||||
CHECK-DAG: %[[TO_RETURN:.*]] = load i64, ptr %[[RETURN_ALLOCA_8]]
|
||||
CHECK: }
|
||||
CHECK-i386: define i32 @local_call_cabi_primitives_on_stack() [[IGN:.*]] {
|
||||
CHECK-i386: %[[CALL:.*]] = call i32 @local_cabi_primitives_on_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8)
|
||||
CHECK-i386: %[[RET:.*]] = add i32 %[[CALL]], {{.*}}
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK: define [64 x i8] @local_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[RETURN_ALLOCA:.*]] = alloca [64 x i8]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT_16:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 16
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_16:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_16]] to ptr
|
||||
CHECK-DAG: store i64 123, ptr %[[RETURN_ALLOCA_16]]
|
||||
CHECK-DAG: %[[TO_RETURN:.*]] = load [64 x i8], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-DAG: ret [64 x i8] %[[TO_RETURN]]
|
||||
CHECK: }
|
||||
; cabi_aggregate_on_registers
|
||||
|
||||
CHECK: define i64 @local_call_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-DAG: %[[RETURN_ALLOCA:.*]] = alloca [64 x i8]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-DAG: %[[RETURN_VALUE:.*]] = call [64 x i8] @local_cabi_return_big_aggregate()
|
||||
CHECK-DAG: store [64 x i8] %[[RETURN_VALUE]], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_INT_16:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 16
|
||||
CHECK-DAG: %[[RETURN_ALLOCA_16:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_16]] to ptr
|
||||
CHECK-DAG: %[[TO_RETURN:.*]] = load i64, ptr %[[RETURN_ALLOCA_16]]
|
||||
CHECK: }
|
||||
CHECK-x86_64: define i64 @local_cabi_aggregate_on_registers(i64 %[[ARG1:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[ARG1]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-x86_64-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[ARG1]], 8
|
||||
CHECK-x86_64-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD2_PTR]], align 8
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_cabi_aggregate_on_registers() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-x86_64-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-x86_64-DAG: = call i64 @local_cabi_aggregate_on_registers(i64 %[[STACK_INT]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-i386: define i32 @local_cabi_aggregate_on_registers(i32 %[[PTR:.*]]) [[IGN:.*]] {
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[PTR]] to ptr
|
||||
CHECK-i386: %[[A:.*]] = load i32, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[T1:.*]] = add i32 {{.*}}, %[[A]]
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[PTR]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: %[[B:.*]] = load i32, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[T2:.*]] = add i32 %[[T1]], %[[B]]
|
||||
CHECK-i386: ret i32 %[[T2]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK-i386: define i32 @local_call_cabi_aggregate_on_registers() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [8 x i8]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[SLOT_INT]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: store i32 2, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: store i32 1, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[CALL:.*]] = call i32 @local_cabi_aggregate_on_registers(i32 %[[SLOT_INT]])
|
||||
CHECK-i386: %[[RET:.*]] = add i32 %[[CALL]], {{.*}}
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
; cabi_aggregate_on_stack
|
||||
|
||||
CHECK-x86_64: define i64 @local_cabi_aggregate_on_stack(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-x86_64-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-x86_64-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD2_PTR]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_cabi_aggregate_on_stack() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-x86_64-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-x86_64-DAG: = call i64 @local_cabi_aggregate_on_stack(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 %[[STACK_INT]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-i386: define i32 @local_cabi_aggregate_on_stack(i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[PTR:.*]]) [[IGN:.*]] {
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[PTR]] to ptr
|
||||
CHECK-i386: %[[A:.*]] = load i32, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[T1:.*]] = add i32 {{.*}}, %[[A]]
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[PTR]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: %[[B:.*]] = load i32, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[T2:.*]] = add i32 %[[T1]], %[[B]]
|
||||
CHECK-i386: ret i32 %[[T2]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK-i386: define i32 @local_call_cabi_aggregate_on_stack() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [8 x i8]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[SLOT_INT]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: store i32 2, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: store i32 1, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[CALL:.*]] = call i32 @local_cabi_aggregate_on_stack(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 %[[SLOT_INT]])
|
||||
CHECK-i386: %[[RET:.*]] = add i32 %[[CALL]], {{.*}}
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
; cabi_aggregate_on_stack_and_registers
|
||||
|
||||
CHECK-x86_64: define i64 @local_cabi_aggregate_on_stack_and_registers(i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[IGN:.*]], i64 %[[STACK_ARG:.*]]) [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[FIELD1_PTR:.*]] = inttoptr i64 %[[STACK_ARG]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD1_PTR]]
|
||||
CHECK-x86_64-DAG: %[[FIELD2_ADDR:.*]] = add i64 %[[STACK_ARG]], 8
|
||||
CHECK-x86_64-DAG: %[[FIELD2_PTR:.*]] = inttoptr i64 %[[FIELD2_ADDR]] to ptr
|
||||
CHECK-x86_64-DAG: load i64, ptr %[[FIELD2_PTR]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_cabi_aggregate_on_stack_and_registers() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[STACK:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT:.*]] = ptrtoint ptr %[[STACK]] to i64
|
||||
CHECK-x86_64-DAG: store i64 1, ptr %[[STACK]]
|
||||
CHECK-x86_64-DAG: %[[STACK_INT_8:.*]] = add i64 %[[STACK_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[STACK_8:.*]] = inttoptr i64 %[[STACK_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 2, ptr %[[STACK_8]]
|
||||
CHECK-x86_64-DAG: = call i64 @local_cabi_aggregate_on_stack_and_registers(i64 1, i64 2, i64 3, i64 4, i64 5, i64 %[[STACK_INT]])
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-i386: define i32 @local_cabi_aggregate_on_stack_and_registers(i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[IGN:.*]], i32 %[[PTR:.*]]) [[IGN:.*]] {
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[PTR]] to ptr
|
||||
CHECK-i386: %[[A:.*]] = load i32, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[T1:.*]] = add i32 {{.*}}, %[[A]]
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[PTR]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: %[[B:.*]] = load i32, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[T2:.*]] = add i32 %[[T1]], %[[B]]
|
||||
CHECK-i386: ret i32 %[[T2]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK-i386: define i32 @local_call_cabi_aggregate_on_stack_and_registers() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [8 x i8]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[B_OFF:.*]] = add i32 %[[SLOT_INT]], 4
|
||||
CHECK-i386: %[[B_PTR:.*]] = inttoptr i32 %[[B_OFF]] to ptr
|
||||
CHECK-i386: store i32 2, ptr %[[B_PTR]]
|
||||
CHECK-i386: %[[A_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: store i32 1, ptr %[[A_PTR]]
|
||||
CHECK-i386: %[[CALL:.*]] = call i32 @local_cabi_aggregate_on_stack_and_registers(i32 1, i32 2, i32 3, i32 4, i32 5, i32 %[[SLOT_INT]])
|
||||
CHECK-i386: %[[RET:.*]] = add i32 %[[CALL]], {{.*}}
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
; raw_return_small_aggregate
|
||||
|
||||
CHECK-x86_64: define <{ i64, i64 }> @local_raw_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[RESULT:.*]] = call <{ i64, i64 }> @struct_initializer(i64 124, i64 123)
|
||||
CHECK-x86_64-DAG: ret <{ i64, i64 }> %[[RESULT]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_raw_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64: %[[RESULT:.*]] = call <{ i64, i64 }> @local_raw_return_small_aggregate()
|
||||
CHECK-x86_64-DAG: call i64 @OpaqueExtractvalue(<{ i64, i64 }> %[[RESULT]], i64 1)
|
||||
CHECK-x86_64: }
|
||||
|
||||
; cabi_return_small_aggregate
|
||||
|
||||
CHECK-x86_64: define [16 x i8] @local_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT_8:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_8:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 124, ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-x86_64-DAG: store i64 123, ptr %[[RETURN_ALLOCA_8]]
|
||||
CHECK-x86_64-DAG: %[[TO_RETURN:.*]] = load [16 x i8], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-x86_64-DAG: ret [16 x i8] %[[TO_RETURN]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA:.*]] = alloca [16 x i8]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-x86_64-DAG: %[[RETURN_VALUE:.*]] = call [16 x i8] @local_cabi_return_small_aggregate()
|
||||
CHECK-x86_64-DAG: store [16 x i8] %[[RETURN_VALUE]], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT_8:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 8
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_8:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_8]] to ptr
|
||||
CHECK-x86_64-DAG: %[[TO_RETURN:.*]] = load i64, ptr %[[RETURN_ALLOCA_8]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-i386: define [8 x i8] @local_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [8 x i8]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[SLOT_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: %[[BASE:.*]] = load i32, ptr %[[SLOT_PTR]]
|
||||
CHECK-i386-DAG: store i32 124, ptr {{.*}}
|
||||
CHECK-i386-DAG: %[[OFF:.*]] = add i32 %[[BASE]], 4
|
||||
CHECK-i386-DAG: store i32 123, ptr {{.*}}
|
||||
CHECK-i386: %[[RV:.*]] = load [8 x i8], ptr %[[SLOT]]
|
||||
CHECK-i386: ret [8 x i8] %[[RV]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK-i386: define i32 @local_call_cabi_return_small_aggregate() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [8 x i8]
|
||||
CHECK-i386: %[[RV:.*]] = call [8 x i8] @local_cabi_return_small_aggregate()
|
||||
CHECK-i386: store [8 x i8] %[[RV]], ptr %[[SLOT]]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[SLOT_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: %[[B:.*]] = load i32, ptr %[[SLOT_PTR]]
|
||||
CHECK-i386: %[[RET:.*]] = add i32 {{.*}}%[[B]]
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
|
||||
; cabi_return_big_aggregate
|
||||
|
||||
CHECK-x86_64: define [64 x i8] @local_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA:.*]] = alloca [64 x i8]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT_16:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 16
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_16:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_16]] to ptr
|
||||
CHECK-x86_64-DAG: store i64 123, ptr %[[RETURN_ALLOCA_16]]
|
||||
CHECK-x86_64-DAG: %[[TO_RETURN:.*]] = load [64 x i8], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-x86_64-DAG: ret [64 x i8] %[[TO_RETURN]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-x86_64: define i64 @local_call_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA:.*]] = alloca [64 x i8]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT:.*]] = ptrtoint ptr %[[RETURN_ALLOCA]] to i64
|
||||
CHECK-x86_64-DAG: %[[RETURN_VALUE:.*]] = call [64 x i8] @local_cabi_return_big_aggregate()
|
||||
CHECK-x86_64-DAG: store [64 x i8] %[[RETURN_VALUE]], ptr %[[RETURN_ALLOCA]]
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_INT_16:.*]] = add i64 %[[RETURN_ALLOCA_INT]], 16
|
||||
CHECK-x86_64-DAG: %[[RETURN_ALLOCA_16:.*]] = inttoptr i64 %[[RETURN_ALLOCA_INT_16]] to ptr
|
||||
CHECK-x86_64-DAG: %[[TO_RETURN:.*]] = load i64, ptr %[[RETURN_ALLOCA_16]]
|
||||
CHECK-x86_64: }
|
||||
|
||||
CHECK-i386: define [28 x i8] @local_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [28 x i8]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[SLOT_PTR:.*]] = inttoptr i32 %[[SLOT_INT]] to ptr
|
||||
CHECK-i386: %[[BASE:.*]] = load i32, ptr %[[SLOT_PTR]]
|
||||
CHECK-i386: %[[OFF:.*]] = add i32 %[[BASE]], 8
|
||||
CHECK-i386: store i32 123, ptr {{.*}}
|
||||
CHECK-i386: %[[RV:.*]] = load [28 x i8], ptr %[[SLOT]]
|
||||
CHECK-i386: ret [28 x i8] %[[RV]]
|
||||
CHECK-i386: }
|
||||
|
||||
CHECK-i386: define i32 @local_call_cabi_return_big_aggregate() [[IGN:.*]] {
|
||||
CHECK-i386: %[[SLOT:.*]] = alloca [28 x i8]
|
||||
CHECK-i386: %[[RV:.*]] = call [28 x i8] @local_cabi_return_big_aggregate()
|
||||
CHECK-i386: store [28 x i8] %[[RV]], ptr %[[SLOT]]
|
||||
CHECK-i386: %[[SLOT_INT:.*]] = ptrtoint ptr %[[SLOT]] to i32
|
||||
CHECK-i386: %[[OFF:.*]] = add i32 %[[SLOT_INT]], 4
|
||||
CHECK-i386: %[[SLOT_PTR:.*]] = inttoptr i32 %[[OFF]] to ptr
|
||||
CHECK-i386: %[[D:.*]] = load i32, ptr %[[SLOT_PTR]]
|
||||
CHECK-i386: %[[RET:.*]] = add i32 {{.*}}%[[D]]
|
||||
CHECK-i386: ret i32 %[[RET]]
|
||||
CHECK-i386: }
|
||||
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
#
|
||||
# This file is distributed under the MIT License. See LICENSE.md for details.
|
||||
#
|
||||
---
|
||||
Architecture: x86
|
||||
|
||||
Functions:
|
||||
- Name: cabi_primitives_on_registers
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100004-CABIFunctionDefinition"
|
||||
- Name: cabi_primitives_on_stack
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100005-CABIFunctionDefinition"
|
||||
- Name: cabi_aggregate_on_registers
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100006-CABIFunctionDefinition"
|
||||
- Name: cabi_aggregate_on_stack
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100007-CABIFunctionDefinition"
|
||||
- Name: cabi_aggregate_on_stack_and_registers
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100008-CABIFunctionDefinition"
|
||||
- Name: cabi_return_small_aggregate
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100010-CABIFunctionDefinition"
|
||||
- Name: cabi_return_big_aggregate
|
||||
Prototype:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100012-CABIFunctionDefinition"
|
||||
TypeDefinitions:
|
||||
- Kind: StructDefinition
|
||||
ID: 100003
|
||||
Size: 8
|
||||
Fields:
|
||||
- Offset: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100004
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
Arguments:
|
||||
- Index: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 1
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100005
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
Arguments:
|
||||
- Index: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 1
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 2
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 3
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 5
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 6
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 7
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100006
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
Arguments:
|
||||
- Index: 0
|
||||
Type:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100003-StructDefinition"
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100007
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
Arguments:
|
||||
- Index: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 1
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 2
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 3
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 5
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 6
|
||||
Type:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100003-StructDefinition"
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100008
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
Arguments:
|
||||
- Index: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 1
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 2
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 3
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Index: 5
|
||||
Type:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100003-StructDefinition"
|
||||
- Kind: StructDefinition
|
||||
ID: 100009
|
||||
Size: 8
|
||||
Fields:
|
||||
- Offset: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100010
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100009-StructDefinition"
|
||||
Arguments: []
|
||||
- Kind: StructDefinition
|
||||
ID: 100011
|
||||
Size: 28
|
||||
Fields:
|
||||
- Offset: 0
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 4
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 8
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 12
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 16
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 20
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Offset: 24
|
||||
Type:
|
||||
Kind: PrimitiveType
|
||||
PrimitiveKind: Generic
|
||||
Size: 4
|
||||
- Kind: CABIFunctionDefinition
|
||||
ID: 100012
|
||||
ABI: SystemV_x86
|
||||
ReturnType:
|
||||
Kind: DefinedType
|
||||
Definition: "/TypeDefinitions/100011-StructDefinition"
|
||||
Arguments: []
|
||||
@@ -175,7 +175,7 @@ define i32 @d_argument(ptr %arg) {
|
||||
; The the ret instruction should load from there again.
|
||||
;
|
||||
; CHECK-LABEL: define %s @s
|
||||
; CHECK: [[ALLOCA:%[a-zA-Z0-9_]+]] = alloca %s
|
||||
; CHECK: [[ALLOCA:%[a-zA-Z0-9_]+]] = alloca [8 x i8]
|
||||
; CHECK-NEXT: [[LOADED_VALUE:%[a-zA-Z0-9_]+]] = load %s, ptr %arg
|
||||
; CHECK-NEXT: store %s [[LOADED_VALUE]], ptr [[ALLOCA]]
|
||||
; CHECK-NEXT: store i64 7, ptr @segment
|
||||
@@ -196,7 +196,7 @@ define %s @s(ptr %arg) {
|
||||
; This is the same as the previous test, but with segment and argument swapped.
|
||||
;
|
||||
; CHECK-LABEL: define %s @s_swapped
|
||||
; CHECK: [[ALLOCA:%[a-zA-Z0-9_]+]] = alloca %s
|
||||
; CHECK: [[ALLOCA:%[a-zA-Z0-9_]+]] = alloca [8 x i8]
|
||||
; CHECK-NEXT: [[LOADED_VALUE:%[a-zA-Z0-9_]+]] = load %s, ptr @segment
|
||||
; CHECK-NEXT: store %s [[LOADED_VALUE]], ptr [[ALLOCA]]
|
||||
; CHECK-NEXT: store i64 7, ptr %arg
|
||||
|
||||
Reference in New Issue
Block a user