Update x-macro metaprogramming support in IRGenModule.

Teach IRGen how to handle runtime functions definitions in RuntimeFunctions.def
depending on their calling convention and on their need for global symbols referring
to their internal implementations.

IRGen would now generate wrappers for runtime functions invocations if at least one
of the following conditions is met:
- The runtime function is defined using FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL,
  which explicitly states that it has a global symbol referring to its implementation. In this case,
  the generated wrapper will perform an indirect call using the specified global symbol.
  This results in some performance improvements, because doing so removes one level of
  indirection during a call of the runtime function.
  The invocation sequence before looked like:
    Swift code -> dynamic linker stub -> runtime_function -> indirect call of runtime_function's implementation through a global function pointer
  And using a wrapper it becomes:
    Swift code -> wrapper -> indirect call of runtime_function's implementation through a global function pointer

- The runtime function is defined using the usual FUNCTION x-macro but it uses a calling convention
   that requires that wrappers should be used instead of dynamic linker stubs to avoid the situations
   where the dynamic linker would clobber some of the callee-saved registers when it performs a lazy
   binding of the runtime function, which may lead to an undefined behaviour during the program execution.

   In this case, the behaviour is similar to the first case, except that the name of the global symbol for
   the  runtime function f is assumed to be _f, i.e. it has an underscore as a prefix. This symbol
   will be auto-generated and properly initialized by an x-macro based metaprogramming machinery
   in the runtime library.
This commit is contained in:
Roman Levenstein
2016-02-17 21:49:08 -08:00
parent 1d0bfcf40e
commit 2956e5675f

View File

@@ -534,17 +534,48 @@ llvm::Constant *swift::getWrapperFn(llvm::Module &Module,
return fn;
}
#define QUOTE(...) __VA_ARGS__
#define STR(X) #X
#define FOR_CONV_RuntimeCC(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
#define FOR_CONV_C_CC(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
#define FOR_CONV_RuntimeCC1(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, \
RT_ENTRY_REF(NAME), CC, \
QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
#define FUNCTION(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
FOR_CONV_##CC(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
#define FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(ID, NAME, SYMBOL, IMPL, CC, \
RETURNS, ARGS, ATTRS) \
FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, SYMBOL, CC, QUOTE(RETURNS), \
QUOTE(ARGS), QUOTE(ATTRS))
#define RETURNS(...) { __VA_ARGS__ }
#define ARGS(...) { __VA_ARGS__ }
#define NO_ARGS {}
#define ATTRS(...) { __VA_ARGS__ }
#define NO_ATTRS {}
#define FUNCTION(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
llvm::Constant *IRGenModule::get##ID##Fn() { \
using namespace RuntimeConstants; \
return getRuntimeFn(*this, ID##Fn, #NAME, CC, \
RETURNS, ARGS, ATTRS); \
}
#define FUNCTION_IMPL(ID, NAME, CC, RETURNS, ARGS, ATTRS) \
llvm::Constant *IRGenModule::get##ID##Fn() { \
using namespace RuntimeConstants; \
return getRuntimeFn(Module, ID##Fn, #NAME, CC, RETURNS, ARGS, ATTRS); \
}
#define FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, SYMBOL_NAME, CC, RETURNS, \
ARGS, ATTRS) \
llvm::Constant *IRGenModule::get##ID##Fn() { \
using namespace RuntimeConstants; \
return getWrapperFn(Module, ID##Fn, #NAME, STR(SYMBOL_NAME), CC, RETURNS, \
ARGS, ATTRS); \
}
#include "swift/Runtime/RuntimeFunctions.def"
std::pair<llvm::GlobalVariable *, llvm::Constant *>