mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 23:15:16 +00:00
![YAMAMOTO Takashi](/assets/img/avatar_default.png)
Move the native stack overflow check from the caller to the callee because the former doesn't work for call_indirect and imported functions. Make the stack usage estimation more accurate. Instead of making a guess from the number of wasm locals in the function, use the LLVM's idea of the stack size of each MachineFunction. The former is inaccurate because a) it doesn't reflect optimization passes, and b) wasm locals are not the only reason to use stack. To use the post-compilation stack usage information without requiring 2-pass compilation or machine-code imm rewriting, introduce a global array to store stack consumption of each functions: For JIT, use a custom IRCompiler with an extra pass to fill the array. For AOT, use `clang -fstack-usage` equivalent because we support external llc. Re-implement function call stack usage estimation to reflect the real calling conventions better. (aot_estimate_stack_usage_for_function_call) Re-implement stack estimation logic (--enable-memory-profiling) based on the new machinery. Discussions: #2105.
133 lines
3.8 KiB
C++
133 lines
3.8 KiB
C++
/*
|
|
* Copyright (c)2023 YAMAMOTO Takashi. All rights reserved.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*/
|
|
|
|
#include <llvm-c/TargetMachine.h>
|
|
#include <llvm/ADT/None.h>
|
|
#include <llvm/ADT/Optional.h>
|
|
#include <llvm/IR/Instructions.h>
|
|
#if LLVM_VERSION_MAJOR >= 14
|
|
#include <llvm/MC/TargetRegistry.h>
|
|
#else
|
|
#include <llvm/Support/TargetRegistry.h>
|
|
#endif
|
|
#include <llvm/Target/TargetMachine.h>
|
|
|
|
#include "bh_assert.h"
|
|
|
|
#include "aot_llvm_extra2.h"
|
|
|
|
static llvm::Optional<llvm::Reloc::Model>
|
|
convert(LLVMRelocMode reloc_mode)
|
|
{
|
|
switch (reloc_mode) {
|
|
case LLVMRelocDefault:
|
|
return llvm::None;
|
|
case LLVMRelocStatic:
|
|
return llvm::Reloc::Static;
|
|
case LLVMRelocPIC:
|
|
return llvm::Reloc::PIC_;
|
|
case LLVMRelocDynamicNoPic:
|
|
return llvm::Reloc::DynamicNoPIC;
|
|
case LLVMRelocROPI:
|
|
return llvm::Reloc::ROPI;
|
|
case LLVMRelocRWPI:
|
|
return llvm::Reloc::RWPI;
|
|
case LLVMRelocROPI_RWPI:
|
|
return llvm::Reloc::ROPI_RWPI;
|
|
}
|
|
bh_assert(0);
|
|
return llvm::None;
|
|
}
|
|
|
|
static llvm::CodeGenOpt::Level
|
|
convert(LLVMCodeGenOptLevel opt_level)
|
|
{
|
|
switch (opt_level) {
|
|
case LLVMCodeGenLevelNone:
|
|
return llvm::CodeGenOpt::None;
|
|
case LLVMCodeGenLevelLess:
|
|
return llvm::CodeGenOpt::Less;
|
|
case LLVMCodeGenLevelDefault:
|
|
return llvm::CodeGenOpt::Default;
|
|
case LLVMCodeGenLevelAggressive:
|
|
return llvm::CodeGenOpt::Aggressive;
|
|
}
|
|
bh_assert(0);
|
|
return llvm::CodeGenOpt::None;
|
|
}
|
|
|
|
static llvm::Optional<llvm::CodeModel::Model>
|
|
convert(LLVMCodeModel code_model, bool *jit)
|
|
{
|
|
*jit = false;
|
|
switch (code_model) {
|
|
case LLVMCodeModelDefault:
|
|
return llvm::None;
|
|
case LLVMCodeModelJITDefault:
|
|
*jit = true;
|
|
return llvm::None;
|
|
case LLVMCodeModelTiny:
|
|
return llvm::CodeModel::Tiny;
|
|
case LLVMCodeModelSmall:
|
|
return llvm::CodeModel::Small;
|
|
case LLVMCodeModelKernel:
|
|
return llvm::CodeModel::Kernel;
|
|
case LLVMCodeModelMedium:
|
|
return llvm::CodeModel::Medium;
|
|
case LLVMCodeModelLarge:
|
|
return llvm::CodeModel::Large;
|
|
}
|
|
bh_assert(0);
|
|
return llvm::None;
|
|
}
|
|
|
|
LLVMTargetMachineRef
|
|
LLVMCreateTargetMachineWithOpts(LLVMTargetRef ctarget, const char *triple,
|
|
const char *cpu, const char *features,
|
|
LLVMCodeGenOptLevel opt_level,
|
|
LLVMRelocMode reloc_mode,
|
|
LLVMCodeModel code_model,
|
|
bool EmitStackSizeSection,
|
|
const char *StackUsageOutput)
|
|
{
|
|
llvm::TargetOptions opts;
|
|
|
|
// -fstack-size-section equiv
|
|
// emit it to ".stack_sizes" section in case of ELF
|
|
// you can read it with "llvm-readobj --stack-sizes"
|
|
opts.EmitStackSizeSection = EmitStackSizeSection;
|
|
|
|
// -fstack-usage equiv
|
|
if (StackUsageOutput != NULL) {
|
|
opts.StackUsageOutput = StackUsageOutput;
|
|
}
|
|
|
|
auto target = reinterpret_cast<llvm::Target *>(ctarget);
|
|
auto rm = convert(reloc_mode);
|
|
auto ol = convert(opt_level);
|
|
bool jit;
|
|
auto cm = convert(code_model, &jit);
|
|
auto targetmachine = target->createTargetMachine(triple, cpu, features,
|
|
opts, rm, cm, ol, jit);
|
|
return reinterpret_cast<LLVMTargetMachineRef>(targetmachine);
|
|
}
|
|
|
|
/* https://reviews.llvm.org/D153107 */
|
|
#if LLVM_VERSION_MAJOR < 17
|
|
using namespace llvm;
|
|
|
|
LLVMTailCallKind
|
|
LLVMGetTailCallKind(LLVMValueRef Call)
|
|
{
|
|
return (LLVMTailCallKind)unwrap<CallInst>(Call)->getTailCallKind();
|
|
}
|
|
|
|
void
|
|
LLVMSetTailCallKind(LLVMValueRef Call, LLVMTailCallKind kind)
|
|
{
|
|
unwrap<CallInst>(Call)->setTailCallKind((CallInst::TailCallKind)kind);
|
|
}
|
|
#endif
|