wasm-micro-runtime/core/iwasm/compilation/aot_llvm_extra2.cpp
YAMAMOTO Takashi cd7941cc39
AOT/JIT native stack bound check improvement (#2244)
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.
2023-06-22 07:27:07 +08:00

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