|
12 | 12 |
|
13 | 13 | #include "CGBuiltin.h" |
14 | 14 | #include "CGHLSLRuntime.h" |
| 15 | +#include "CodeGenFunction.h" |
15 | 16 |
|
16 | 17 | using namespace clang; |
17 | 18 | using namespace CodeGen; |
@@ -214,6 +215,44 @@ static Intrinsic::ID getWaveActiveMaxIntrinsic(llvm::Triple::ArchType Arch, |
214 | 215 | } |
215 | 216 | } |
216 | 217 |
|
| 218 | +// Returns the mangled name for a builtin function that the SPIR-V backend |
| 219 | +// will expand into a spec Constant. |
| 220 | +static std::string getSpecConstantFunctionName(clang::QualType SpecConstantType, |
| 221 | + ASTContext &Context) { |
| 222 | + // The parameter types for our conceptual intrinsic function. |
| 223 | + QualType ClangParamTypes[] = {Context.IntTy, SpecConstantType}; |
| 224 | + |
| 225 | + // Create a temporary FunctionDecl for the builtin fuction. It won't be |
| 226 | + // added to the AST. |
| 227 | + FunctionProtoType::ExtProtoInfo EPI; |
| 228 | + QualType FnType = |
| 229 | + Context.getFunctionType(SpecConstantType, ClangParamTypes, EPI); |
| 230 | + DeclarationName FuncName = &Context.Idents.get("__spirv_SpecConstant"); |
| 231 | + FunctionDecl *FnDeclForMangling = FunctionDecl::Create( |
| 232 | + Context, Context.getTranslationUnitDecl(), SourceLocation(), |
| 233 | + SourceLocation(), FuncName, FnType, /*TSI=*/nullptr, SC_Extern); |
| 234 | + |
| 235 | + // Attach the created parameter declarations to the function declaration. |
| 236 | + SmallVector<ParmVarDecl *, 2> ParamDecls; |
| 237 | + for (QualType ParamType : ClangParamTypes) { |
| 238 | + ParmVarDecl *PD = ParmVarDecl::Create( |
| 239 | + Context, FnDeclForMangling, SourceLocation(), SourceLocation(), |
| 240 | + /*IdentifierInfo*/ nullptr, ParamType, /*TSI*/ nullptr, SC_None, |
| 241 | + /*DefaultArg*/ nullptr); |
| 242 | + ParamDecls.push_back(PD); |
| 243 | + } |
| 244 | + FnDeclForMangling->setParams(ParamDecls); |
| 245 | + |
| 246 | + // Get the mangled name. |
| 247 | + std::string Name; |
| 248 | + llvm::raw_string_ostream MangledNameStream(Name); |
| 249 | + std::unique_ptr<MangleContext> Mangler(Context.createMangleContext()); |
| 250 | + Mangler->mangleName(FnDeclForMangling, MangledNameStream); |
| 251 | + MangledNameStream.flush(); |
| 252 | + |
| 253 | + return Name; |
| 254 | +} |
| 255 | + |
217 | 256 | Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, |
218 | 257 | const CallExpr *E, |
219 | 258 | ReturnValueSlot ReturnValue) { |
@@ -773,6 +812,42 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, |
773 | 812 | return EmitRuntimeCall( |
774 | 813 | Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID)); |
775 | 814 | } |
| 815 | + case Builtin::BI__builtin_get_spirv_spec_constant_bool: |
| 816 | + case Builtin::BI__builtin_get_spirv_spec_constant_short: |
| 817 | + case Builtin::BI__builtin_get_spirv_spec_constant_ushort: |
| 818 | + case Builtin::BI__builtin_get_spirv_spec_constant_int: |
| 819 | + case Builtin::BI__builtin_get_spirv_spec_constant_uint: |
| 820 | + case Builtin::BI__builtin_get_spirv_spec_constant_longlong: |
| 821 | + case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong: |
| 822 | + case Builtin::BI__builtin_get_spirv_spec_constant_half: |
| 823 | + case Builtin::BI__builtin_get_spirv_spec_constant_float: |
| 824 | + case Builtin::BI__builtin_get_spirv_spec_constant_double: { |
| 825 | + llvm::Function *SpecConstantFn = getSpecConstantFunction(E->getType()); |
| 826 | + llvm::Value *SpecId = EmitScalarExpr(E->getArg(0)); |
| 827 | + llvm::Value *DefaultVal = EmitScalarExpr(E->getArg(1)); |
| 828 | + llvm::Value *Args[] = {SpecId, DefaultVal}; |
| 829 | + return Builder.CreateCall(SpecConstantFn, Args); |
| 830 | + } |
776 | 831 | } |
777 | 832 | return nullptr; |
778 | 833 | } |
| 834 | + |
| 835 | +llvm::Function *clang::CodeGen::CodeGenFunction::getSpecConstantFunction( |
| 836 | + const clang::QualType &SpecConstantType) { |
| 837 | + |
| 838 | + // Find or create the declaration for the function. |
| 839 | + llvm::Module *M = &CGM.getModule(); |
| 840 | + std::string MangledName = |
| 841 | + getSpecConstantFunctionName(SpecConstantType, getContext()); |
| 842 | + llvm::Function *SpecConstantFn = M->getFunction(MangledName); |
| 843 | + |
| 844 | + if (!SpecConstantFn) { |
| 845 | + llvm::Type *IntType = ConvertType(getContext().IntTy); |
| 846 | + llvm::Type *RetTy = ConvertType(SpecConstantType); |
| 847 | + llvm::Type *ArgTypes[] = {IntType, RetTy}; |
| 848 | + llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, ArgTypes, false); |
| 849 | + SpecConstantFn = llvm::Function::Create( |
| 850 | + FnTy, llvm::GlobalValue::ExternalLinkage, MangledName, M); |
| 851 | + } |
| 852 | + return SpecConstantFn; |
| 853 | +} |
0 commit comments