Ban dynamic-size allocas, use ArrayType instead

This commit is contained in:
Alessandro Di Federico
2026-06-18 15:11:19 +02:00
parent 8d67f33ce5
commit 325da01cad
3 changed files with 13 additions and 28 deletions
+4 -20
View File
@@ -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);
+2 -1
View File
@@ -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());
+7 -7
View File
@@ -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()) {