@@ -110,6 +110,27 @@ StructLiteralExp *getMagicAttribute(Dsymbol *sym, const Identifier *id,
110
110
return nullptr ;
111
111
}
112
112
113
+ // / Returns the _last_ StructLiteralExp magic attribute with identifier `id`
114
+ // / from the ldc magic module with identifier `from` (attributes or dcompute) if
115
+ // / it is applied to `sym`, otherwise returns nullptr.
116
+ StructLiteralExp *getLastMagicAttribute (Dsymbol *sym, const Identifier *id,
117
+ const Identifier *from) {
118
+ if (!sym->userAttribDecl )
119
+ return nullptr ;
120
+
121
+ // Loop over all UDAs and find the last match
122
+ StructLiteralExp *lastMatch = nullptr ;
123
+ Expressions *attrs = sym->userAttribDecl ->getAttributes ();
124
+ expandTuples (attrs);
125
+ for (auto attr : *attrs) {
126
+ if (auto sle = attr->isStructLiteralExp ())
127
+ if (isFromMagicModule (sle, from) && id == sle->sd ->ident )
128
+ lastMatch = sle;
129
+ }
130
+
131
+ return lastMatch;
132
+ }
133
+
113
134
// / Calls `action` for each magic attribute with identifier `id` from
114
135
// / the ldc magic module with identifier `from` (attributes or dcompute)
115
136
// / applied to `sym`.
@@ -366,6 +387,105 @@ void applyAttrAssumeUsed(IRState &irs, StructLiteralExp *sle,
366
387
irs.usedArray .push_back (symbol);
367
388
}
368
389
390
+ // / Tries to recognize the calling convention,
391
+ // / TODO: Add support "cc <n>"
392
+ // / Returns true if succesful, with the calling convention in 'callconv'.
393
+ // / Returns false if unsuccesful.
394
+ bool parseCallingConvention (llvm::StringRef name,
395
+ llvm::CallingConv::ID *callconv) {
396
+
397
+ llvm::CallingConv::ID conv_id =
398
+ llvm::StringSwitch<llvm::CallingConv::ID>(name)
399
+ // Names recognized by Clang (see Clang's
400
+ // CodeGenTypes::ClangCallConvToLLVMCallConv):
401
+ .Case (" stdcall" , llvm::CallingConv::X86_StdCall)
402
+ .Case (" fastcall" , llvm::CallingConv::X86_FastCall)
403
+ .Case (" regcall" , llvm::CallingConv::X86_RegCall)
404
+ .Case (" thiscall" , llvm::CallingConv::X86_ThisCall)
405
+ .Case (" ms_abi" , llvm::CallingConv::Win64)
406
+ .Case (" sysv_abi" , llvm::CallingConv::X86_64_SysV)
407
+ .Case (" pcs(\" aapcs\" )" , llvm::CallingConv::ARM_AAPCS)
408
+ .Case (" pcs(\" aapcs-vfp\" )" , llvm::CallingConv::ARM_AAPCS_VFP)
409
+ .Case (" intel_ocl_bicc" , llvm::CallingConv::Intel_OCL_BI)
410
+ .Case (" pascal" ,
411
+ llvm::CallingConv::C) // Check Clang, this may change in future
412
+ .Case (" vectorcall" , llvm::CallingConv::X86_VectorCall)
413
+ .Case (" aarch64_vector_pcs" , llvm::CallingConv::AArch64_VectorCall)
414
+ .Case (" preserve_most" , llvm::CallingConv::PreserveMost)
415
+ .Case (" preserve_all" , llvm::CallingConv::PreserveAll)
416
+ .Case (" swiftcall" , llvm::CallingConv::Swift)
417
+ #if LDC_LLVM_VER >= 1300
418
+ .Case (" swiftasynccall" , llvm::CallingConv::SwiftTail)
419
+ #endif
420
+
421
+ // Names recognized in LLVM IR (see LLVM's
422
+ // LLParser::parseOptionalCallingConv):
423
+ .Case (" ccc" , llvm::CallingConv::C)
424
+ .Case (" fastcc" , llvm::CallingConv::Fast)
425
+ .Case (" coldcc" , llvm::CallingConv::Cold)
426
+ #if LDC_LLVM_VER >= 1000
427
+ .Case (" cfguard_checkcc" , llvm::CallingConv::CFGuard_Check)
428
+ #endif
429
+ .Case (" x86_stdcallcc" , llvm::CallingConv::X86_StdCall)
430
+ .Case (" x86_fastcallcc" , llvm::CallingConv::X86_FastCall)
431
+ .Case (" x86_regcallcc" , llvm::CallingConv::X86_RegCall)
432
+ .Case (" x86_thiscallcc" , llvm::CallingConv::X86_ThisCall)
433
+ .Case (" x86_vectorcallcc" , llvm::CallingConv::X86_VectorCall)
434
+ .Case (" arm_apcscc" , llvm::CallingConv::ARM_APCS)
435
+ .Case (" arm_aapcscc" , llvm::CallingConv::ARM_AAPCS)
436
+ .Case (" arm_aapcs_vfpcc" , llvm::CallingConv::ARM_AAPCS_VFP)
437
+ .Case (" aarch64_vector_pcs" , llvm::CallingConv::AArch64_VectorCall)
438
+ #if LDC_LLVM_VER >= 1000
439
+ .Case (" aarch64_sve_vector_pcs" ,
440
+ llvm::CallingConv::AArch64_SVE_VectorCall)
441
+ #endif
442
+ .Case (" msp430_intrcc" , llvm::CallingConv::MSP430_INTR)
443
+ .Case (" avr_intrcc" , llvm::CallingConv::AVR_INTR)
444
+ .Case (" avr_signalcc" , llvm::CallingConv::AVR_SIGNAL)
445
+ .Case (" ptx_kernel" , llvm::CallingConv::PTX_Kernel)
446
+ .Case (" ptx_device" , llvm::CallingConv::PTX_Device)
447
+ .Case (" spir_kernel" , llvm::CallingConv::SPIR_KERNEL)
448
+ .Case (" spir_func" , llvm::CallingConv::SPIR_FUNC)
449
+ .Case (" intel_ocl_bicc" , llvm::CallingConv::Intel_OCL_BI)
450
+ .Case (" x86_64_sysvcc" , llvm::CallingConv::X86_64_SysV)
451
+ .Case (" win64cc" , llvm::CallingConv::Win64)
452
+ .Case (" webkit_jscc" , llvm::CallingConv::WebKit_JS)
453
+ .Case (" anyregcc" , llvm::CallingConv::AnyReg)
454
+ .Case (" preserve_mostcc" , llvm::CallingConv::PreserveMost)
455
+ .Case (" preserve_allcc" , llvm::CallingConv::PreserveAll)
456
+ .Case (" ghccc" , llvm::CallingConv::GHC)
457
+ .Case (" swiftcc" , llvm::CallingConv::Swift)
458
+ #if LDC_LLVM_VER >= 1300
459
+ .Case (" swifttailcc" , llvm::CallingConv::SwiftTail)
460
+ #endif
461
+ .Case (" x86_intrcc" , llvm::CallingConv::X86_INTR)
462
+ .Case (" hhvmcc" , llvm::CallingConv::HHVM)
463
+ .Case (" hhvm_ccc" , llvm::CallingConv::HHVM_C)
464
+ .Case (" cxx_fast_tlscc" , llvm::CallingConv::CXX_FAST_TLS)
465
+ .Case (" amdgpu_vs" , llvm::CallingConv::AMDGPU_VS)
466
+ #if LDC_LLVM_VER >= 1200
467
+ .Case (" amdgpu_gfx" , llvm::CallingConv::AMDGPU_Gfx)
468
+ #endif
469
+ .Case (" amdgpu_ls" , llvm::CallingConv::AMDGPU_LS)
470
+ .Case (" amdgpu_hs" , llvm::CallingConv::AMDGPU_HS)
471
+ .Case (" amdgpu_es" , llvm::CallingConv::AMDGPU_ES)
472
+ .Case (" amdgpu_gs" , llvm::CallingConv::AMDGPU_GS)
473
+ .Case (" amdgpu_ps" , llvm::CallingConv::AMDGPU_PS)
474
+ .Case (" amdgpu_cs" , llvm::CallingConv::AMDGPU_CS)
475
+ .Case (" amdgpu_kernel" , llvm::CallingConv::AMDGPU_KERNEL)
476
+ #if LDC_LLVM_VER >= 1000
477
+ .Case (" tailcc" , llvm::CallingConv::Tail)
478
+ #endif
479
+
480
+ .Case (" default" , llvm::CallingConv::MaxID - 1 )
481
+ .Default (llvm::CallingConv::MaxID);
482
+
483
+ bool success = (conv_id != llvm::CallingConv::MaxID);
484
+ if (success && callconv)
485
+ *callconv = conv_id;
486
+ return success;
487
+ }
488
+
369
489
} // anonymous namespace
370
490
371
491
void applyVarDeclUDAs (VarDeclaration *decl, llvm::GlobalVariable *gvar) {
@@ -394,7 +514,8 @@ void applyVarDeclUDAs(VarDeclaration *decl, llvm::GlobalVariable *gvar) {
394
514
} else if (ident == Id::udaWeak) {
395
515
// @weak is applied elsewhere
396
516
} else if (ident == Id::udaDynamicCompile ||
397
- ident == Id::udaDynamicCompileEmit) {
517
+ ident == Id::udaDynamicCompileEmit ||
518
+ ident == Id::udaCallingConvention) {
398
519
sle->error (
399
520
" Special attribute `ldc.attributes.%s` is only valid for functions" ,
400
521
ident->toChars ());
@@ -450,7 +571,7 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
450
571
} else if (ident == Id::udaAssumeUsed) {
451
572
applyAttrAssumeUsed (*gIR , sle, func);
452
573
} else if (ident == Id::udaWeak || ident == Id::udaKernel ||
453
- ident == Id::udaNoSanitize) {
574
+ ident == Id::udaNoSanitize || ident==Id::udaCallingConvention ) {
454
575
// These UDAs are applied elsewhere, thus should silently be ignored here.
455
576
} else if (ident == Id::udaDynamicCompile) {
456
577
irFunc->dynamicCompile = true ;
@@ -498,6 +619,25 @@ void applyFuncDeclUDAs(FuncDeclaration *decl, IrFunction *irFunc) {
498
619
}
499
620
}
500
621
622
+ // / Checks whether 'fd' has the @ldc.attributes.callingConvention("...") UDA applied.
623
+ // / If so, it returns the calling convention in 'callconv'.
624
+ bool hasCallingConventionUDA (FuncDeclaration *fd,
625
+ llvm::CallingConv::ID *callconv) {
626
+ auto sle =
627
+ getLastMagicAttribute (fd, Id::udaCallingConvention, Id::attributes);
628
+ if (!sle)
629
+ return false ;
630
+
631
+ checkStructElems (sle, {Type::tstring});
632
+ auto name = getFirstElemString (sle);
633
+ bool success = parseCallingConvention (name, callconv);
634
+ if (!success)
635
+ sle->warning (" Ignoring unrecognized calling convention name '%s' for "
636
+ " `@ldc.attributes.callingConvention`" ,
637
+ name.str ().c_str ());
638
+ return success;
639
+ }
640
+
501
641
// / Checks whether 'sym' has the @ldc.attributes._weak() UDA applied.
502
642
bool hasWeakUDA (Dsymbol *sym) {
503
643
auto sle = getMagicAttribute (sym, Id::udaWeak, Id::attributes);
0 commit comments