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

Add @naked UDA #2773

Merged
merged 2 commits into from
Jul 28, 2018
Merged

Add @naked UDA #2773

merged 2 commits into from
Jul 28, 2018

Conversation

kinke
Copy link
Member

@kinke kinke commented Jul 11, 2018

No description provided.

@kinke
Copy link
Member Author

kinke commented Jul 11, 2018

Motivation: being able to replace the DMD-style naked asm functions with LLVM asm + @naked UDA, in order to get LTO working with druntime/Phobos on Windows.

gen/uda.cpp Outdated

namespace llvm {
// Auto-generate:
// Attribute::AttrKind getAttrKindFromName(StringRef AttrName) { ... }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice find.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, took me a bit of time. ;) - Let's see which LLVM versions support this.

@JohanEngelen
Copy link
Member

LGTM. Would be nice to add a link to the LLVM langref naked to the documentation.

@kinke
Copy link
Member Author

kinke commented Jul 11, 2018

There's no direct URL to the naked spec, it's just one of the many function attributes. I copied the 2 sentences there as druntime comment.

@kinke kinke force-pushed the uda branch 3 times, most recently from 6a8e8a1 to d729184 Compare July 11, 2018 23:27
As preparation for a trivial addition to ldc.attributes, probably more
to follow over time:

enum naked = llvmAttr("naked");
@kinke
Copy link
Member Author

kinke commented Jul 11, 2018

I didn't find a similar function in LLVM 3.7 and 3.8, so this kind of llvmAttr("EnumAttributeName") may be LLVM 3.9+ only (and so cannot be used in druntime/Phobos until we lift the min LLVM version :/).

@@ -13,6 +13,20 @@
#include "id.h"

#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This include looks unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't. ;)

@JohanEngelen
Copy link
Member

There's no direct URL to the naked spec, it's just one of the many function attributes. I copied the 2 sentences there as druntime comment.

I more meant that'd it be nice to say explicitly that the UDA is applying the LLVM naked attribute.

gen/uda.cpp Outdated
#else
// no getAttrKindFromName(); just detect `naked` for now
if (key == "naked") {
func->addFnAttr(llvm::Attribute::Naked)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot return here. Better to use an if-else chain to prevent such errors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, even managed to forget the semicolon. ;)

@kinke
Copy link
Member Author

kinke commented Jul 15, 2018

It may need to do more than just applying the LLVM attribute. We shouldn't allocate storage for implicit and explicit parameters (our 'prologue'); I had to resort to defining a parameter-less impl-function and overriding its mangle in order to fake a naked function taking 2 params.

@kinke
Copy link
Member Author

kinke commented Jul 26, 2018

LDC prologue/epilogue now disabled too, which seems to work fine for Win64. On Linux x64 however, the 2 params of the testcase are still dumped to memory; the generated IR is exactly the same as the Win64 one, incl. function attributes:

; Function Attrs: naked uwtable
define i32 @nakedFunction(i32 %param1_arg, i8* %param2_arg) #0 comdat {
  %1 = call i32 asm sideeffect "xor %eax, %eax", "={eax}"() ; [#uses = 1]
  ret i32 %1
}

The faulty Linux .s, params dumped inbetween inline asm and return instruction:

nakedFunction:
	.cfi_startproc
	#APP
	xorl	%eax, %eax
	#NO_APP
	movl	%edi, -4(%rbp)
	movq	%rsi, -16(%rbp)
	retq

Adding the LLVM `naked` function attribute and disabling LDC's
prologue/epilogue too.
@kinke
Copy link
Member Author

kinke commented Jul 27, 2018

Alright, same thing for Linux happening with clang. -O can be used as ugly workaround.

The updated version doesn't require a return statement anymore (and so allows for naked functions without return instruction or with manual ones only), see the extended test. The appended unreachable vanishes for Linux (not in unoptimized -output-s output) but makes it to the final assembly on Win64 (again, with clang too)...

@kinke kinke merged commit 7461269 into ldc-developers:master Jul 28, 2018
@kinke kinke deleted the uda branch July 28, 2018 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants