| # HLSL Entry Functions | |
| ## Usage | |
| In HLSL, entry functions denote the starting point for shader execution. They | |
| must be known at compile time. For all non-library shaders, the compiler assumes | |
| the default entry function name `main`, unless the DXC `/E` option is | |
| provided to specify an alternate entry point. For library shaders entry points | |
| are denoted using the `[shader(...)]` attribute. | |
| All scalar parameters to entry functions must have semantic annotations, and all | |
| struct parameters must have semantic annotations on every field in the struct | |
| declaration. Additionally if the entry function has a return type, a semantic | |
| annotation must be provided for the return type as well. | |
| HLSL entry functions can be called from other parts of the shader, which has | |
| implications on code generation. | |
| ## Implementation Details | |
| In Clang, the DXC `/E` option is translated to the cc1 flag `-hlsl-entry`, | |
| which in turn applies the `HLSLShader` attribute to the function with the | |
| specified name. This allows code generation for entry functions to always key | |
| off the presence of the `HLSLShader` attribute, regardless of what shader | |
| profile you are compiling. | |
| In code generation, two functions are generated. One is the user defined | |
| function, which is code generated as a mangled C++ function with internal | |
| linkage following normal function code generation. | |
| The actual exported entry function which can be called by the GPU driver is a | |
| `void(void)` function that isn't name mangled. In code generation we generate | |
| the unmangled entry function to serve as the actual shader entry. The shader | |
| entry function is annotated with the `hlsl.shader` function attribute | |
| identifying the entry's pipeline stage. | |
| The body of the unmangled entry function contains first a call to execute global | |
| constructors, then instantiations of the user-defined entry parameters with | |
| their semantic values populated, and a call to the user-defined function. | |
| After the call instruction the return value (if any) is saved using a | |
| target-appropriate intrinsic for storing outputs (for DirectX, the | |
| `llvm.dx.store.output`). Lastly, any present global destructors will be called | |
| immediately before the return. HLSL does not support C++ `atexit` | |
| registrations, instead calls to global destructors are compile-time generated. | |
| :::{note} | |
| HLSL support in Clang is currently focused on compute shaders, which do not | |
| support output semantics. Support for output semantics will not be | |
| implemented until other shader profiles are supported. | |
| ::: | |
| Below is example IR that represents the planned implementation, subject to | |
| change as the `llvm.dx.store.output` and `llvm.dx.load.input` intrinsics are | |
| not yet implemented. | |
| ```llvm | |
| ; Function Attrs: norecurse | |
| define void @main() #1 { | |
| entry: | |
| %0 = call i32 @llvm.dx.load.input.i32(...) | |
| %1 = call i32 @"?main@@YAXII@Z"(i32 %0) | |
| call @llvm.dx.store.output.i32(%1, ...) | |
| ret void | |
| } | |
| ``` |