mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 20:06:03 +03:00
Add @naked UDA
Adding the LLVM `naked` function attribute and disabling LDC's prologue/epilogue too.
This commit is contained in:
parent
f2c718d7a4
commit
c10cf86403
4 changed files with 69 additions and 13 deletions
|
@ -827,6 +827,18 @@ void emitDMDStyleFunctionTrace(IRState &irs, FuncDeclaration *fd,
|
|||
}
|
||||
}
|
||||
|
||||
// If the specified block is trivially unreachable, erases it and returns true.
|
||||
// This is a common case because it happens when 'return' is the last statement
|
||||
// in a function.
|
||||
bool eraseDummyAfterReturnBB(llvm::BasicBlock *bb) {
|
||||
if (pred_begin(bb) == pred_end(bb) &&
|
||||
bb != &bb->getParent()->getEntryBlock()) {
|
||||
bb->eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||
|
@ -1034,6 +1046,9 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
llvm::BasicBlock::Create(gIR->context(), "", func);
|
||||
|
||||
gIR->scopes.push_back(IRScope(beginbb));
|
||||
SCOPE_EXIT {
|
||||
gIR->scopes.pop_back();
|
||||
};
|
||||
|
||||
// Set the FastMath options for this function scope.
|
||||
#if LDC_LLVM_VER >= 308
|
||||
|
@ -1042,6 +1057,18 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
gIR->scopes.back().builder.SetFastMathFlags(irFunc->FMF);
|
||||
#endif
|
||||
|
||||
// @naked: emit body and return, no prologue/epilogue
|
||||
if (func->hasFnAttribute(llvm::Attribute::Naked)) {
|
||||
Statement_toIR(fd->fbody, gIR);
|
||||
const bool wasDummy = eraseDummyAfterReturnBB(gIR->scopebb());
|
||||
if (!wasDummy && !gIR->scopereturned()) {
|
||||
// this is what clang does to prevent LLVM complaining about
|
||||
// non-terminated function
|
||||
gIR->ir->CreateUnreachable();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// create alloca point
|
||||
// this gets erased when the function is complete, so alignment etc does not
|
||||
// matter at all
|
||||
|
@ -1163,14 +1190,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
funcGen.scopes.popCleanups(0);
|
||||
}
|
||||
|
||||
llvm::BasicBlock *bb = gIR->scopebb();
|
||||
if (pred_begin(bb) == pred_end(bb) &&
|
||||
bb != &bb->getParent()->getEntryBlock()) {
|
||||
// This block is trivially unreachable, so just delete it.
|
||||
// (This is a common case because it happens when 'return'
|
||||
// is the last statement in a function)
|
||||
bb->eraseFromParent();
|
||||
} else if (!gIR->scopereturned()) {
|
||||
const bool wasDummy = eraseDummyAfterReturnBB(gIR->scopebb());
|
||||
if (!wasDummy && !gIR->scopereturned()) {
|
||||
// llvm requires all basic blocks to end with a TerminatorInst but DMD does
|
||||
// not put a return statement in automatically, so we do it here.
|
||||
|
||||
|
@ -1201,8 +1222,6 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
allocaPoint = nullptr;
|
||||
}
|
||||
|
||||
gIR->scopes.pop_back();
|
||||
|
||||
if (gIR->dcomputetarget && hasKernelAttr(fd)) {
|
||||
auto fn = gIR->module.getFunction(fd->mangleString);
|
||||
gIR->dcomputetarget->addKernelMetadata(fd, fn);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue