mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
Ban dynamic-size allocas, use ArrayType instead
This commit is contained in:
+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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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"
|
||||
@@ -84,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()) {
|
||||
|
||||
Reference in New Issue
Block a user