llvm::Function* LocalStack::getStackPrepareFunc() { static const auto c_funcName = "stack.prepare"; if (auto func = getModule()->getFunction(c_funcName)) return func; llvm::Type* argsTys[] = {Type::WordPtr, Type::Size->getPointerTo(), Type::Size, Type::Size, Type::Size, Type::BytePtr}; auto func = llvm::Function::Create(llvm::FunctionType::get(Type::WordPtr, argsTys, false), llvm::Function::PrivateLinkage, c_funcName, getModule()); func->setDoesNotThrow(); func->setDoesNotAccessMemory(1); func->setDoesNotAlias(2); func->setDoesNotCapture(2); auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func); auto updateBB = llvm::BasicBlock::Create(func->getContext(), "Update", func); auto outOfStackBB = llvm::BasicBlock::Create(func->getContext(), "OutOfStack", func); auto iter = func->arg_begin(); llvm::Argument* base = &(*iter++); base->setName("base"); llvm::Argument* sizePtr = &(*iter++); sizePtr->setName("size.ptr"); llvm::Argument* min = &(*iter++); min->setName("min"); llvm::Argument* max = &(*iter++); max->setName("max"); llvm::Argument* diff = &(*iter++); diff->setName("diff"); llvm::Argument* jmpBuf = &(*iter); jmpBuf->setName("jmpBuf"); InsertPointGuard guard{m_builder}; m_builder.SetInsertPoint(checkBB); auto sizeAlignment = getModule()->getDataLayout().getABITypeAlignment(Type::Size); auto size = m_builder.CreateAlignedLoad(sizePtr, sizeAlignment, "size"); auto minSize = m_builder.CreateAdd(size, min, "size.min", false, true); auto maxSize = m_builder.CreateAdd(size, max, "size.max", true, true); auto minOk = m_builder.CreateICmpSGE(minSize, m_builder.getInt64(0), "ok.min"); auto maxOk = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(RuntimeManager::stackSizeLimit), "ok.max"); auto ok = m_builder.CreateAnd(minOk, maxOk, "ok"); m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue); m_builder.SetInsertPoint(updateBB); auto newSize = m_builder.CreateNSWAdd(size, diff, "size.next"); m_builder.CreateAlignedStore(newSize, sizePtr, sizeAlignment); auto sp = m_builder.CreateGEP(base, size, "sp"); m_builder.CreateRet(sp); m_builder.SetInsertPoint(outOfStackBB); auto longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp); m_builder.CreateCall(longjmp, {jmpBuf}); m_builder.CreateUnreachable(); return func; }
llvm::Function* Array::getReallocFunc() { if (auto func = getModule()->getFunction("ext_realloc")) return func; llvm::Type* reallocArgTypes[] = {Type::BytePtr, Type::Size}; auto reallocFunc = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, reallocArgTypes, false), llvm::Function::ExternalLinkage, "ext_realloc", getModule()); reallocFunc->setDoesNotThrow(); reallocFunc->setDoesNotAlias(0); reallocFunc->setDoesNotCapture(1); return reallocFunc; }