Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

codegenDecl on functions overrides all attributes #10682

Open
mratsim opened this issue Feb 15, 2019 · 2 comments
Open

codegenDecl on functions overrides all attributes #10682

mratsim opened this issue Feb 15, 2019 · 2 comments

Comments

@mratsim
Copy link
Collaborator

mratsim commented Feb 15, 2019

codegenDecl pragma on functions will override all function attributes.

Example:

proc foo() =
  echo 1

{.pragma: hot, codegenDecl: "__attribute__((hot)) $# $#$#".}

proc bar() {.hot.} =
  echo 1

proc baz() {.inline.} =
  echo 1

proc oops() {.inline, hot.} =
  echo 1

foo()
bar()
baz()
oops()

This produces (in release emode)

N_LIB_PRIVATE N_NIMCALL(void, foo_wznx9adj3TlVt3o5axJ9aYOg)(void) {
	echoBinSafe(TM_YoGu5Gbh4YxJ9c0z7IstHKg_2, 1);
}

__attribute__((hot)) void bar_wznx9adj3TlVt3o5axJ9aYOg_2(void) {
	echoBinSafe(TM_YoGu5Gbh4YxJ9c0z7IstHKg_2, 1);
}

static N_INLINE(void, baz_Ij9bzunIMj7NU3a7ws3YxBQattr_func)(void) {
	echoBinSafe(TM_YoGu5Gbh4YxJ9c0z7IstHKg_2, 1);
}

__attribute__((hot)) void oops_Ij9bzunIMj7NU3a7ws3YxBQ_2attr_func(void) {
	echoBinSafe(TM_YoGu5Gbh4YxJ9c0z7IstHKg_2, 1);
}

In the first case N_LIB_PRIVATE N_NIMCALL has been replaced and in the second case static N_INLINE has been replaced.

For a bit more context, I'm writing a domain specific compiler in Nim for machine learning and image processing and I need to implement one function per SIMD supported (nothing, SSE, AVX, AVX512, ...). Unfortunately, ideally those should be in separate C files to avoid the compiler using incompatible features in older sets which seems complicated. Alternatively I can use GCC/Clang only attributes like __attribute__((__target__("avx2"))).

@mratsim
Copy link
Collaborator Author

mratsim commented Feb 15, 2019

I checked how this is implemented in ccgtypes genProcHeader:

Nim/compiler/ccgtypes.nim

Lines 888 to 912 in 2610b16

proc genProcHeader(m: BModule, prc: PSym): Rope =
var
rettype, params: Rope
genCLineDir(result, prc.info, m.config)
# using static is needed for inline procs
if lfExportLib in prc.loc.flags:
if isHeaderFile in m.flags:
result.add "N_LIB_IMPORT "
else:
result.add "N_LIB_EXPORT "
elif prc.typ.callConv == ccInline:
result.add "static "
elif {sfImportc, sfExportc} * prc.flags == {}:
result.add "N_LIB_PRIVATE "
var check = initIntSet()
fillLoc(prc.loc, locProc, prc.ast[namePos], mangleName(m, prc), OnUnknown)
genProcParams(m, prc.typ, rettype, params, check)
# careful here! don't access ``prc.ast`` as that could reload large parts of
# the object graph!
if prc.constraint.isNil:
addf(result, "$1($2, $3)$4",
[rope(CallingConvToStr[prc.typ.callConv]), rettype, prc.loc.r,
params])
else:
result = prc.cgDeclFrmt % [rettype, prc.loc.r, params]

I'm not sure there is a way to do what is needed in a backward compatible way.

I've found the current workaround:

proc foo() =
  echo 1

{.pragma: hot, codegenDecl: "__attribute__((hot)) N_LIB_PRIVATE N_NIMCALL($#, $#)$#".}
{.pragma: hot_inline, codegenDecl: "__attribute__((hot)) static N_INLINE($#, $#)$#".}

proc bar() {.hot.} =
  echo 1

proc baz() {.inline.} =
  echo 1

proc oops() {.hot_inline.} =
  echo 1

foo()
bar()
baz()
oops()
N_LIB_PRIVATE N_NIMCALL(void, foo_ZEVWdPzph9aEvWzKnk2jr4w)(void) {
	echoBinSafe(TM_rnFJuQ50wUpy8kftbt2QJA_2, 1);
}

__attribute__((hot)) N_LIB_PRIVATE N_NIMCALL(void, bar_ZEVWdPzph9aEvWzKnk2jr4w_2)(void) {
	echoBinSafe(TM_rnFJuQ50wUpy8kftbt2QJA_2, 1);
}

static N_INLINE(void, baz_txURmaVFiHb6ZhpniaNZhgattr_func3)(void) {
	echoBinSafe(TM_rnFJuQ50wUpy8kftbt2QJA_2, 1);
}

__attribute__((hot)) static N_INLINE(void, oops_ZEVWdPzph9aEvWzKnk2jr4w_3)(void) {
	echoBinSafe(TM_rnFJuQ50wUpy8kftbt2QJA_2, 1);
}

@mratsim
Copy link
Collaborator Author

mratsim commented Dec 13, 2019

Removing the low priority tag.

We are considering using LLVM Xray for instrumenting Nimbus.
Fine-grained instrumenting can be controlled with GCC attributes:

void alt_always_instrumented() __attribute__((xray_always_instrument));
void alt_never_instrumented() __attribute__((xray_never_instrument));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant