clang 22.0.0git
CGHLSLBuiltins.cpp
Go to the documentation of this file.
1//===------- CGHLSLBuiltins.cpp - Emit LLVM Code for HLSL builtins --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit HLSL Builtin calls as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CGBuiltin.h"
14#include "CGHLSLRuntime.h"
15#include "CodeGenFunction.h"
16
17using namespace clang;
18using namespace CodeGen;
19using namespace llvm;
20
22 assert((E->getArg(0)->getType()->hasUnsignedIntegerRepresentation() &&
23 E->getArg(1)->getType()->hasUnsignedIntegerRepresentation()) &&
24 "asdouble operands types mismatch");
25 Value *OpLowBits = CGF.EmitScalarExpr(E->getArg(0));
26 Value *OpHighBits = CGF.EmitScalarExpr(E->getArg(1));
27
28 llvm::Type *ResultType = CGF.DoubleTy;
29 int N = 1;
30 if (auto *VTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) {
31 N = VTy->getNumElements();
32 ResultType = llvm::FixedVectorType::get(CGF.DoubleTy, N);
33 }
34
35 if (CGF.CGM.getTarget().getTriple().isDXIL())
36 return CGF.Builder.CreateIntrinsic(
37 /*ReturnType=*/ResultType, Intrinsic::dx_asdouble,
38 {OpLowBits, OpHighBits}, nullptr, "hlsl.asdouble");
39
40 if (!E->getArg(0)->getType()->isVectorType()) {
41 OpLowBits = CGF.Builder.CreateVectorSplat(1, OpLowBits);
42 OpHighBits = CGF.Builder.CreateVectorSplat(1, OpHighBits);
43 }
44
46 for (int i = 0; i < N; i++) {
47 Mask.push_back(i);
48 Mask.push_back(i + N);
49 }
50
51 Value *BitVec = CGF.Builder.CreateShuffleVector(OpLowBits, OpHighBits, Mask);
52
53 return CGF.Builder.CreateBitCast(BitVec, ResultType);
54}
55
57 Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
58
59 Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy);
60 Value *CMP;
61 Value *LastInstr;
62
63 if (const auto *VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>()) {
64 FZeroConst = ConstantVector::getSplat(
65 ElementCount::getFixed(VecTy->getNumElements()), FZeroConst);
66 auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
67 CMP = CGF->Builder.CreateIntrinsic(
68 CGF->Builder.getInt1Ty(), CGF->CGM.getHLSLRuntime().getAnyIntrinsic(),
69 {FCompInst});
70 } else {
71 CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);
72 }
73
74 if (CGF->CGM.getTarget().getTriple().isDXIL()) {
75 LastInstr = CGF->Builder.CreateIntrinsic(Intrinsic::dx_discard, {CMP});
76 } else if (CGF->CGM.getTarget().getTriple().isSPIRV()) {
77 BasicBlock *LT0 = CGF->createBasicBlock("lt0", CGF->CurFn);
78 BasicBlock *End = CGF->createBasicBlock("end", CGF->CurFn);
79
80 CGF->Builder.CreateCondBr(CMP, LT0, End);
81
82 CGF->Builder.SetInsertPoint(LT0);
83
84 CGF->Builder.CreateIntrinsic(Intrinsic::spv_discard, {});
85
86 LastInstr = CGF->Builder.CreateBr(End);
87 CGF->Builder.SetInsertPoint(End);
88 } else {
89 llvm_unreachable("Backend Codegen not supported.");
90 }
91
92 return LastInstr;
93}
94
96 Value *Op0 = CGF->EmitScalarExpr(E->getArg(0));
97 const auto *OutArg1 = dyn_cast<HLSLOutArgExpr>(E->getArg(1));
98 const auto *OutArg2 = dyn_cast<HLSLOutArgExpr>(E->getArg(2));
99
100 CallArgList Args;
101 LValue Op1TmpLValue =
102 CGF->EmitHLSLOutArgExpr(OutArg1, Args, OutArg1->getType());
103 LValue Op2TmpLValue =
104 CGF->EmitHLSLOutArgExpr(OutArg2, Args, OutArg2->getType());
105
107 Args.reverseWritebacks();
108
109 Value *LowBits = nullptr;
110 Value *HighBits = nullptr;
111
112 if (CGF->CGM.getTarget().getTriple().isDXIL()) {
113 llvm::Type *RetElementTy = CGF->Int32Ty;
114 if (auto *Op0VecTy = E->getArg(0)->getType()->getAs<clang::VectorType>())
115 RetElementTy = llvm::VectorType::get(
116 CGF->Int32Ty, ElementCount::getFixed(Op0VecTy->getNumElements()));
117 auto *RetTy = llvm::StructType::get(RetElementTy, RetElementTy);
118
119 CallInst *CI = CGF->Builder.CreateIntrinsic(
120 RetTy, Intrinsic::dx_splitdouble, {Op0}, nullptr, "hlsl.splitdouble");
121
122 LowBits = CGF->Builder.CreateExtractValue(CI, 0);
123 HighBits = CGF->Builder.CreateExtractValue(CI, 1);
124 } else {
125 // For Non DXIL targets we generate the instructions.
126
127 if (!Op0->getType()->isVectorTy()) {
128 FixedVectorType *DestTy = FixedVectorType::get(CGF->Int32Ty, 2);
129 Value *Bitcast = CGF->Builder.CreateBitCast(Op0, DestTy);
130
131 LowBits = CGF->Builder.CreateExtractElement(Bitcast, (uint64_t)0);
132 HighBits = CGF->Builder.CreateExtractElement(Bitcast, 1);
133 } else {
134 int NumElements = 1;
135 if (const auto *VecTy =
136 E->getArg(0)->getType()->getAs<clang::VectorType>())
137 NumElements = VecTy->getNumElements();
138
139 FixedVectorType *Uint32VecTy =
140 FixedVectorType::get(CGF->Int32Ty, NumElements * 2);
141 Value *Uint32Vec = CGF->Builder.CreateBitCast(Op0, Uint32VecTy);
142 if (NumElements == 1) {
143 LowBits = CGF->Builder.CreateExtractElement(Uint32Vec, (uint64_t)0);
144 HighBits = CGF->Builder.CreateExtractElement(Uint32Vec, 1);
145 } else {
146 SmallVector<int> EvenMask, OddMask;
147 for (int I = 0, E = NumElements; I != E; ++I) {
148 EvenMask.push_back(I * 2);
149 OddMask.push_back(I * 2 + 1);
150 }
151 LowBits = CGF->Builder.CreateShuffleVector(Uint32Vec, EvenMask);
152 HighBits = CGF->Builder.CreateShuffleVector(Uint32Vec, OddMask);
153 }
154 }
155 }
156 CGF->Builder.CreateStore(LowBits, Op1TmpLValue.getAddress());
157 auto *LastInst =
158 CGF->Builder.CreateStore(HighBits, Op2TmpLValue.getAddress());
159 CGF->EmitWritebacks(Args);
160 return LastInst;
161}
162
163// Return dot product intrinsic that corresponds to the QT scalar type
164static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) {
165 if (QT->isFloatingType())
166 return RT.getFDotIntrinsic();
167 if (QT->isSignedIntegerType())
168 return RT.getSDotIntrinsic();
169 assert(QT->isUnsignedIntegerType());
170 return RT.getUDotIntrinsic();
171}
172
173static Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT) {
175 return RT.getFirstBitSHighIntrinsic();
176 }
177
179 return RT.getFirstBitUHighIntrinsic();
180}
181
182// Return wave active sum that corresponds to the QT scalar type
183static Intrinsic::ID getWaveActiveSumIntrinsic(llvm::Triple::ArchType Arch,
184 CGHLSLRuntime &RT, QualType QT) {
185 switch (Arch) {
186 case llvm::Triple::spirv:
187 return Intrinsic::spv_wave_reduce_sum;
188 case llvm::Triple::dxil: {
189 if (QT->isUnsignedIntegerType())
190 return Intrinsic::dx_wave_reduce_usum;
191 return Intrinsic::dx_wave_reduce_sum;
192 }
193 default:
194 llvm_unreachable("Intrinsic WaveActiveSum"
195 " not supported by target architecture");
196 }
197}
198
199// Return wave active sum that corresponds to the QT scalar type
200static Intrinsic::ID getWaveActiveMaxIntrinsic(llvm::Triple::ArchType Arch,
201 CGHLSLRuntime &RT, QualType QT) {
202 switch (Arch) {
203 case llvm::Triple::spirv:
204 if (QT->isUnsignedIntegerType())
205 return Intrinsic::spv_wave_reduce_umax;
206 return Intrinsic::spv_wave_reduce_max;
207 case llvm::Triple::dxil: {
208 if (QT->isUnsignedIntegerType())
209 return Intrinsic::dx_wave_reduce_umax;
210 return Intrinsic::dx_wave_reduce_max;
211 }
212 default:
213 llvm_unreachable("Intrinsic WaveActiveMax"
214 " not supported by target architecture");
215 }
216}
217
218// Returns the mangled name for a builtin function that the SPIR-V backend
219// will expand into a spec Constant.
220static 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.
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.
237 for (QualType ParamType : ClangParamTypes) {
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
257 const CallExpr *E,
258 ReturnValueSlot ReturnValue) {
259 if (!getLangOpts().HLSL)
260 return nullptr;
261
262 switch (BuiltinID) {
263 case Builtin::BI__builtin_hlsl_adduint64: {
264 Value *OpA = EmitScalarExpr(E->getArg(0));
265 Value *OpB = EmitScalarExpr(E->getArg(1));
266 QualType Arg0Ty = E->getArg(0)->getType();
267 uint64_t NumElements = Arg0Ty->castAs<VectorType>()->getNumElements();
268 assert(Arg0Ty == E->getArg(1)->getType() &&
269 "AddUint64 operand types must match");
270 assert(Arg0Ty->hasIntegerRepresentation() &&
271 "AddUint64 operands must have an integer representation");
272 assert((NumElements == 2 || NumElements == 4) &&
273 "AddUint64 operands must have 2 or 4 elements");
274
275 llvm::Value *LowA;
276 llvm::Value *HighA;
277 llvm::Value *LowB;
278 llvm::Value *HighB;
279
280 // Obtain low and high words of inputs A and B
281 if (NumElements == 2) {
282 LowA = Builder.CreateExtractElement(OpA, (uint64_t)0, "LowA");
283 HighA = Builder.CreateExtractElement(OpA, (uint64_t)1, "HighA");
284 LowB = Builder.CreateExtractElement(OpB, (uint64_t)0, "LowB");
285 HighB = Builder.CreateExtractElement(OpB, (uint64_t)1, "HighB");
286 } else {
287 LowA = Builder.CreateShuffleVector(OpA, {0, 2}, "LowA");
288 HighA = Builder.CreateShuffleVector(OpA, {1, 3}, "HighA");
289 LowB = Builder.CreateShuffleVector(OpB, {0, 2}, "LowB");
290 HighB = Builder.CreateShuffleVector(OpB, {1, 3}, "HighB");
291 }
292
293 // Use an uadd_with_overflow to compute the sum of low words and obtain a
294 // carry value
295 llvm::Value *Carry;
296 llvm::Value *LowSum = EmitOverflowIntrinsic(
297 *this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);
298 llvm::Value *ZExtCarry =
299 Builder.CreateZExt(Carry, HighA->getType(), "CarryZExt");
300
301 // Sum the high words and the carry
302 llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB, "HighSum");
303 llvm::Value *HighSumPlusCarry =
304 Builder.CreateAdd(HighSum, ZExtCarry, "HighSumPlusCarry");
305
306 if (NumElements == 4) {
307 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},
308 "hlsl.AddUint64");
309 }
310
311 llvm::Value *Result = PoisonValue::get(OpA->getType());
312 Result = Builder.CreateInsertElement(Result, LowSum, (uint64_t)0,
313 "hlsl.AddUint64.upto0");
314 Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, (uint64_t)1,
315 "hlsl.AddUint64");
316 return Result;
317 }
318 case Builtin::BI__builtin_hlsl_resource_getpointer: {
319 Value *HandleOp = EmitScalarExpr(E->getArg(0));
320 Value *IndexOp = EmitScalarExpr(E->getArg(1));
321
322 llvm::Type *RetTy = ConvertType(E->getType());
323 return Builder.CreateIntrinsic(
324 RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),
325 ArrayRef<Value *>{HandleOp, IndexOp});
326 }
327 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {
328 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
329 return llvm::PoisonValue::get(HandleTy);
330 }
331 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {
332 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
333 Value *RegisterOp = EmitScalarExpr(E->getArg(1));
334 Value *SpaceOp = EmitScalarExpr(E->getArg(2));
335 Value *RangeOp = EmitScalarExpr(E->getArg(3));
336 Value *IndexOp = EmitScalarExpr(E->getArg(4));
337 Value *Name = EmitScalarExpr(E->getArg(5));
338 llvm::Intrinsic::ID IntrinsicID =
339 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();
340 SmallVector<Value *> Args{SpaceOp, RegisterOp, RangeOp, IndexOp, Name};
341 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
342 }
343 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {
344 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());
345 Value *SpaceOp = EmitScalarExpr(E->getArg(1));
346 Value *RangeOp = EmitScalarExpr(E->getArg(2));
347 Value *IndexOp = EmitScalarExpr(E->getArg(3));
348 Value *OrderID = EmitScalarExpr(E->getArg(4));
349 Value *Name = EmitScalarExpr(E->getArg(5));
350 llvm::Intrinsic::ID IntrinsicID =
351 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();
352 SmallVector<Value *> Args{OrderID, SpaceOp, RangeOp, IndexOp, Name};
353 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);
354 }
355 case Builtin::BI__builtin_hlsl_all: {
356 Value *Op0 = EmitScalarExpr(E->getArg(0));
357 return Builder.CreateIntrinsic(
358 /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
359 CGM.getHLSLRuntime().getAllIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
360 "hlsl.all");
361 }
362 case Builtin::BI__builtin_hlsl_and: {
363 Value *Op0 = EmitScalarExpr(E->getArg(0));
364 Value *Op1 = EmitScalarExpr(E->getArg(1));
365 return Builder.CreateAnd(Op0, Op1, "hlsl.and");
366 }
367 case Builtin::BI__builtin_hlsl_or: {
368 Value *Op0 = EmitScalarExpr(E->getArg(0));
369 Value *Op1 = EmitScalarExpr(E->getArg(1));
370 return Builder.CreateOr(Op0, Op1, "hlsl.or");
371 }
372 case Builtin::BI__builtin_hlsl_any: {
373 Value *Op0 = EmitScalarExpr(E->getArg(0));
374 return Builder.CreateIntrinsic(
375 /*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
376 CGM.getHLSLRuntime().getAnyIntrinsic(), ArrayRef<Value *>{Op0}, nullptr,
377 "hlsl.any");
378 }
379 case Builtin::BI__builtin_hlsl_asdouble:
380 return handleAsDoubleBuiltin(*this, E);
381 case Builtin::BI__builtin_hlsl_elementwise_clamp: {
382 Value *OpX = EmitScalarExpr(E->getArg(0));
383 Value *OpMin = EmitScalarExpr(E->getArg(1));
384 Value *OpMax = EmitScalarExpr(E->getArg(2));
385
386 QualType Ty = E->getArg(0)->getType();
387 if (auto *VecTy = Ty->getAs<VectorType>())
388 Ty = VecTy->getElementType();
389
390 Intrinsic::ID Intr;
391 if (Ty->isFloatingType()) {
392 Intr = CGM.getHLSLRuntime().getNClampIntrinsic();
393 } else if (Ty->isUnsignedIntegerType()) {
394 Intr = CGM.getHLSLRuntime().getUClampIntrinsic();
395 } else {
396 assert(Ty->isSignedIntegerType());
397 Intr = CGM.getHLSLRuntime().getSClampIntrinsic();
398 }
399 return Builder.CreateIntrinsic(
400 /*ReturnType=*/OpX->getType(), Intr,
401 ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "hlsl.clamp");
402 }
403 case Builtin::BI__builtin_hlsl_crossf16:
404 case Builtin::BI__builtin_hlsl_crossf32: {
405 Value *Op0 = EmitScalarExpr(E->getArg(0));
406 Value *Op1 = EmitScalarExpr(E->getArg(1));
407 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
408 E->getArg(1)->getType()->hasFloatingRepresentation() &&
409 "cross operands must have a float representation");
410 // make sure each vector has exactly 3 elements
411 assert(
412 E->getArg(0)->getType()->castAs<VectorType>()->getNumElements() == 3 &&
413 E->getArg(1)->getType()->castAs<VectorType>()->getNumElements() == 3 &&
414 "input vectors must have 3 elements each");
415 return Builder.CreateIntrinsic(
416 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getCrossIntrinsic(),
417 ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.cross");
418 }
419 case Builtin::BI__builtin_hlsl_dot: {
420 Value *Op0 = EmitScalarExpr(E->getArg(0));
421 Value *Op1 = EmitScalarExpr(E->getArg(1));
422 llvm::Type *T0 = Op0->getType();
423 llvm::Type *T1 = Op1->getType();
424
425 // If the arguments are scalars, just emit a multiply
426 if (!T0->isVectorTy() && !T1->isVectorTy()) {
427 if (T0->isFloatingPointTy())
428 return Builder.CreateFMul(Op0, Op1, "hlsl.dot");
429
430 if (T0->isIntegerTy())
431 return Builder.CreateMul(Op0, Op1, "hlsl.dot");
432
433 llvm_unreachable(
434 "Scalar dot product is only supported on ints and floats.");
435 }
436 // For vectors, validate types and emit the appropriate intrinsic
437 assert(CGM.getContext().hasSameUnqualifiedType(E->getArg(0)->getType(),
438 E->getArg(1)->getType()) &&
439 "Dot product operands must have the same type.");
440
441 auto *VecTy0 = E->getArg(0)->getType()->castAs<VectorType>();
442 assert(VecTy0 && "Dot product argument must be a vector.");
443
444 return Builder.CreateIntrinsic(
445 /*ReturnType=*/T0->getScalarType(),
446 getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
447 ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
448 }
449 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
450 Value *X = EmitScalarExpr(E->getArg(0));
451 Value *Y = EmitScalarExpr(E->getArg(1));
452 Value *Acc = EmitScalarExpr(E->getArg(2));
453
454 Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
455 // Note that the argument order disagrees between the builtin and the
456 // intrinsic here.
457 return Builder.CreateIntrinsic(
458 /*ReturnType=*/Acc->getType(), ID, ArrayRef<Value *>{Acc, X, Y},
459 nullptr, "hlsl.dot4add.i8packed");
460 }
461 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {
462 Value *X = EmitScalarExpr(E->getArg(0));
463 Value *Y = EmitScalarExpr(E->getArg(1));
464 Value *Acc = EmitScalarExpr(E->getArg(2));
465
466 Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();
467 // Note that the argument order disagrees between the builtin and the
468 // intrinsic here.
469 return Builder.CreateIntrinsic(
470 /*ReturnType=*/Acc->getType(), ID, ArrayRef<Value *>{Acc, X, Y},
471 nullptr, "hlsl.dot4add.u8packed");
472 }
473 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {
474 Value *X = EmitScalarExpr(E->getArg(0));
475
476 return Builder.CreateIntrinsic(
477 /*ReturnType=*/ConvertType(E->getType()),
479 ArrayRef<Value *>{X}, nullptr, "hlsl.firstbithigh");
480 }
481 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {
482 Value *X = EmitScalarExpr(E->getArg(0));
483
484 return Builder.CreateIntrinsic(
485 /*ReturnType=*/ConvertType(E->getType()),
486 CGM.getHLSLRuntime().getFirstBitLowIntrinsic(), ArrayRef<Value *>{X},
487 nullptr, "hlsl.firstbitlow");
488 }
489 case Builtin::BI__builtin_hlsl_lerp: {
490 Value *X = EmitScalarExpr(E->getArg(0));
491 Value *Y = EmitScalarExpr(E->getArg(1));
492 Value *S = EmitScalarExpr(E->getArg(2));
493 if (!E->getArg(0)->getType()->hasFloatingRepresentation())
494 llvm_unreachable("lerp operand must have a float representation");
495 return Builder.CreateIntrinsic(
496 /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
497 ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
498 }
499 case Builtin::BI__builtin_hlsl_normalize: {
500 Value *X = EmitScalarExpr(E->getArg(0));
501
502 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
503 "normalize operand must have a float representation");
504
505 return Builder.CreateIntrinsic(
506 /*ReturnType=*/X->getType(),
507 CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X},
508 nullptr, "hlsl.normalize");
509 }
510 case Builtin::BI__builtin_hlsl_elementwise_degrees: {
511 Value *X = EmitScalarExpr(E->getArg(0));
512
513 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
514 "degree operand must have a float representation");
515
516 return Builder.CreateIntrinsic(
517 /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(),
518 ArrayRef<Value *>{X}, nullptr, "hlsl.degrees");
519 }
520 case Builtin::BI__builtin_hlsl_elementwise_frac: {
521 Value *Op0 = EmitScalarExpr(E->getArg(0));
522 if (!E->getArg(0)->getType()->hasFloatingRepresentation())
523 llvm_unreachable("frac operand must have a float representation");
524 return Builder.CreateIntrinsic(
525 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getFracIntrinsic(),
526 ArrayRef<Value *>{Op0}, nullptr, "hlsl.frac");
527 }
528 case Builtin::BI__builtin_hlsl_elementwise_isinf: {
529 Value *Op0 = EmitScalarExpr(E->getArg(0));
530 llvm::Type *Xty = Op0->getType();
531 llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());
532 if (Xty->isVectorTy()) {
533 auto *XVecTy = E->getArg(0)->getType()->castAs<VectorType>();
534 retType = llvm::VectorType::get(
535 retType, ElementCount::getFixed(XVecTy->getNumElements()));
536 }
537 if (!E->getArg(0)->getType()->hasFloatingRepresentation())
538 llvm_unreachable("isinf operand must have a float representation");
539 return Builder.CreateIntrinsic(retType, Intrinsic::dx_isinf,
540 ArrayRef<Value *>{Op0}, nullptr, "dx.isinf");
541 }
542 case Builtin::BI__builtin_hlsl_mad: {
543 Value *M = EmitScalarExpr(E->getArg(0));
544 Value *A = EmitScalarExpr(E->getArg(1));
545 Value *B = EmitScalarExpr(E->getArg(2));
546 if (E->getArg(0)->getType()->hasFloatingRepresentation())
547 return Builder.CreateIntrinsic(
548 /*ReturnType*/ M->getType(), Intrinsic::fmuladd,
549 ArrayRef<Value *>{M, A, B}, nullptr, "hlsl.fmad");
550
551 if (E->getArg(0)->getType()->hasSignedIntegerRepresentation()) {
552 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
553 return Builder.CreateIntrinsic(
554 /*ReturnType*/ M->getType(), Intrinsic::dx_imad,
555 ArrayRef<Value *>{M, A, B}, nullptr, "dx.imad");
556
557 Value *Mul = Builder.CreateNSWMul(M, A);
558 return Builder.CreateNSWAdd(Mul, B);
559 }
560 assert(E->getArg(0)->getType()->hasUnsignedIntegerRepresentation());
561 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)
562 return Builder.CreateIntrinsic(
563 /*ReturnType=*/M->getType(), Intrinsic::dx_umad,
564 ArrayRef<Value *>{M, A, B}, nullptr, "dx.umad");
565
566 Value *Mul = Builder.CreateNUWMul(M, A);
567 return Builder.CreateNUWAdd(Mul, B);
568 }
569 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
570 Value *Op0 = EmitScalarExpr(E->getArg(0));
571 if (!E->getArg(0)->getType()->hasFloatingRepresentation())
572 llvm_unreachable("rcp operand must have a float representation");
573 llvm::Type *Ty = Op0->getType();
574 llvm::Type *EltTy = Ty->getScalarType();
575 Constant *One = Ty->isVectorTy()
576 ? ConstantVector::getSplat(
577 ElementCount::getFixed(
578 cast<FixedVectorType>(Ty)->getNumElements()),
579 ConstantFP::get(EltTy, 1.0))
580 : ConstantFP::get(EltTy, 1.0);
581 return Builder.CreateFDiv(One, Op0, "hlsl.rcp");
582 }
583 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {
584 Value *Op0 = EmitScalarExpr(E->getArg(0));
585 if (!E->getArg(0)->getType()->hasFloatingRepresentation())
586 llvm_unreachable("rsqrt operand must have a float representation");
587 return Builder.CreateIntrinsic(
588 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getRsqrtIntrinsic(),
589 ArrayRef<Value *>{Op0}, nullptr, "hlsl.rsqrt");
590 }
591 case Builtin::BI__builtin_hlsl_elementwise_saturate: {
592 Value *Op0 = EmitScalarExpr(E->getArg(0));
593 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
594 "saturate operand must have a float representation");
595 return Builder.CreateIntrinsic(
596 /*ReturnType=*/Op0->getType(),
597 CGM.getHLSLRuntime().getSaturateIntrinsic(), ArrayRef<Value *>{Op0},
598 nullptr, "hlsl.saturate");
599 }
600 case Builtin::BI__builtin_hlsl_select: {
601 Value *OpCond = EmitScalarExpr(E->getArg(0));
602 RValue RValTrue = EmitAnyExpr(E->getArg(1));
603 Value *OpTrue =
604 RValTrue.isScalar()
605 ? RValTrue.getScalarVal()
606 : RValTrue.getAggregatePointer(E->getArg(1)->getType(), *this);
607 RValue RValFalse = EmitAnyExpr(E->getArg(2));
608 Value *OpFalse =
609 RValFalse.isScalar()
610 ? RValFalse.getScalarVal()
611 : RValFalse.getAggregatePointer(E->getArg(2)->getType(), *this);
612 if (auto *VTy = E->getType()->getAs<VectorType>()) {
613 if (!OpTrue->getType()->isVectorTy())
614 OpTrue =
615 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue, "splat");
616 if (!OpFalse->getType()->isVectorTy())
617 OpFalse =
618 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse, "splat");
619 }
620
621 Value *SelectVal =
622 Builder.CreateSelect(OpCond, OpTrue, OpFalse, "hlsl.select");
623 if (!RValTrue.isScalar())
624 Builder.CreateStore(SelectVal, ReturnValue.getAddress(),
625 ReturnValue.isVolatile());
626
627 return SelectVal;
628 }
629 case Builtin::BI__builtin_hlsl_step: {
630 Value *Op0 = EmitScalarExpr(E->getArg(0));
631 Value *Op1 = EmitScalarExpr(E->getArg(1));
632 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
633 E->getArg(1)->getType()->hasFloatingRepresentation() &&
634 "step operands must have a float representation");
635 return Builder.CreateIntrinsic(
636 /*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),
637 ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
638 }
639 case Builtin::BI__builtin_hlsl_wave_active_all_true: {
640 Value *Op = EmitScalarExpr(E->getArg(0));
641 assert(Op->getType()->isIntegerTy(1) &&
642 "Intrinsic WaveActiveAllTrue operand must be a bool");
643
644 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();
645 return EmitRuntimeCall(
646 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
647 }
648 case Builtin::BI__builtin_hlsl_wave_active_any_true: {
649 Value *Op = EmitScalarExpr(E->getArg(0));
650 assert(Op->getType()->isIntegerTy(1) &&
651 "Intrinsic WaveActiveAnyTrue operand must be a bool");
652
653 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();
654 return EmitRuntimeCall(
655 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});
656 }
657 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {
658 Value *OpExpr = EmitScalarExpr(E->getArg(0));
659 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();
660 return EmitRuntimeCall(
661 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID),
662 ArrayRef{OpExpr});
663 }
664 case Builtin::BI__builtin_hlsl_wave_active_sum: {
665 // Due to the use of variadic arguments, explicitly retreive argument
666 Value *OpExpr = EmitScalarExpr(E->getArg(0));
667 Intrinsic::ID IID = getWaveActiveSumIntrinsic(
668 getTarget().getTriple().getArch(), CGM.getHLSLRuntime(),
669 E->getArg(0)->getType());
670
671 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
672 &CGM.getModule(), IID, {OpExpr->getType()}),
673 ArrayRef{OpExpr}, "hlsl.wave.active.sum");
674 }
675 case Builtin::BI__builtin_hlsl_wave_active_max: {
676 // Due to the use of variadic arguments, explicitly retreive argument
677 Value *OpExpr = EmitScalarExpr(E->getArg(0));
678 Intrinsic::ID IID = getWaveActiveMaxIntrinsic(
679 getTarget().getTriple().getArch(), CGM.getHLSLRuntime(),
680 E->getArg(0)->getType());
681
682 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
683 &CGM.getModule(), IID, {OpExpr->getType()}),
684 ArrayRef{OpExpr}, "hlsl.wave.active.max");
685 }
686 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
687 // We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
688 // defined in SPIRVBuiltins.td. So instead we manually get the matching name
689 // for the DirectX intrinsic and the demangled builtin name
690 switch (CGM.getTarget().getTriple().getArch()) {
691 case llvm::Triple::dxil:
692 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
693 &CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
694 case llvm::Triple::spirv:
696 llvm::FunctionType::get(IntTy, {}, false),
697 "__hlsl_wave_get_lane_index", {}, false, true));
698 default:
699 llvm_unreachable(
700 "Intrinsic WaveGetLaneIndex not supported by target architecture");
701 }
702 }
703 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
704 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
705 return EmitRuntimeCall(
706 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
707 }
708 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {
709 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();
710 return EmitRuntimeCall(
711 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
712 }
713 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {
714 // Due to the use of variadic arguments we must explicitly retreive them and
715 // create our function type.
716 Value *OpExpr = EmitScalarExpr(E->getArg(0));
717 Value *OpIndex = EmitScalarExpr(E->getArg(1));
718 return EmitRuntimeCall(
719 Intrinsic::getOrInsertDeclaration(
720 &CGM.getModule(), CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),
721 {OpExpr->getType()}),
722 ArrayRef{OpExpr, OpIndex}, "hlsl.wave.readlane");
723 }
724 case Builtin::BI__builtin_hlsl_elementwise_sign: {
725 auto *Arg0 = E->getArg(0);
726 Value *Op0 = EmitScalarExpr(Arg0);
727 llvm::Type *Xty = Op0->getType();
728 llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext());
729 if (Xty->isVectorTy()) {
730 auto *XVecTy = Arg0->getType()->castAs<VectorType>();
731 retType = llvm::VectorType::get(
732 retType, ElementCount::getFixed(XVecTy->getNumElements()));
733 }
734 assert((Arg0->getType()->hasFloatingRepresentation() ||
735 Arg0->getType()->hasIntegerRepresentation()) &&
736 "sign operand must have a float or int representation");
737
738 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
739 Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
740 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
741 ConstantInt::get(retType, 1), "hlsl.sign");
742 }
743
744 return Builder.CreateIntrinsic(
745 retType, CGM.getHLSLRuntime().getSignIntrinsic(),
746 ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
747 }
748 case Builtin::BI__builtin_hlsl_elementwise_radians: {
749 Value *Op0 = EmitScalarExpr(E->getArg(0));
750 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
751 "radians operand must have a float representation");
752 return Builder.CreateIntrinsic(
753 /*ReturnType=*/Op0->getType(),
754 CGM.getHLSLRuntime().getRadiansIntrinsic(), ArrayRef<Value *>{Op0},
755 nullptr, "hlsl.radians");
756 }
757 case Builtin::BI__builtin_hlsl_buffer_update_counter: {
758 Value *ResHandle = EmitScalarExpr(E->getArg(0));
759 Value *Offset = EmitScalarExpr(E->getArg(1));
760 Value *OffsetI8 = Builder.CreateIntCast(Offset, Int8Ty, true);
761 return Builder.CreateIntrinsic(
762 /*ReturnType=*/Offset->getType(),
763 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),
764 ArrayRef<Value *>{ResHandle, OffsetI8}, nullptr);
765 }
766 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {
767
768 assert((E->getArg(0)->getType()->hasFloatingRepresentation() &&
769 E->getArg(1)->getType()->hasUnsignedIntegerRepresentation() &&
770 E->getArg(2)->getType()->hasUnsignedIntegerRepresentation()) &&
771 "asuint operands types mismatch");
772 return handleHlslSplitdouble(E, this);
773 }
774 case Builtin::BI__builtin_hlsl_elementwise_clip:
775 assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
776 "clip operands types mismatch");
777 return handleHlslClip(E, this);
778 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {
779 Intrinsic::ID ID =
780 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();
781 return EmitRuntimeCall(
782 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
783 }
784 case Builtin::BI__builtin_get_spirv_spec_constant_bool:
785 case Builtin::BI__builtin_get_spirv_spec_constant_short:
786 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:
787 case Builtin::BI__builtin_get_spirv_spec_constant_int:
788 case Builtin::BI__builtin_get_spirv_spec_constant_uint:
789 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:
790 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:
791 case Builtin::BI__builtin_get_spirv_spec_constant_half:
792 case Builtin::BI__builtin_get_spirv_spec_constant_float:
793 case Builtin::BI__builtin_get_spirv_spec_constant_double: {
794 llvm::Function *SpecConstantFn = getSpecConstantFunction(E->getType());
795 llvm::Value *SpecId = EmitScalarExpr(E->getArg(0));
796 llvm::Value *DefaultVal = EmitScalarExpr(E->getArg(1));
797 llvm::Value *Args[] = {SpecId, DefaultVal};
798 return Builder.CreateCall(SpecConstantFn, Args);
799 }
800 }
801 return nullptr;
802}
803
805 const clang::QualType &SpecConstantType) {
806
807 // Find or create the declaration for the function.
808 llvm::Module *M = &CGM.getModule();
809 std::string MangledName =
810 getSpecConstantFunctionName(SpecConstantType, getContext());
811 llvm::Function *SpecConstantFn = M->getFunction(MangledName);
812
813 if (!SpecConstantFn) {
814 llvm::Type *IntType = ConvertType(getContext().IntTy);
815 llvm::Type *RetTy = ConvertType(SpecConstantType);
816 llvm::Type *ArgTypes[] = {IntType, RetTy};
817 llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, ArgTypes, false);
818 SpecConstantFn = llvm::Function::Create(
819 FnTy, llvm::GlobalValue::ExternalLinkage, MangledName, M);
820 }
821 return SpecConstantFn;
822}
llvm::Value * EmitOverflowIntrinsic(CodeGenFunction &CGF, const Intrinsic::ID IntrinsicID, llvm::Value *X, llvm::Value *Y, llvm::Value *&Carry)
Emit a call to llvm.
Definition: CGBuiltin.cpp:841
static Intrinsic::ID getWaveActiveSumIntrinsic(llvm::Triple::ArchType Arch, CGHLSLRuntime &RT, QualType QT)
static Intrinsic::ID getWaveActiveMaxIntrinsic(llvm::Triple::ArchType Arch, CGHLSLRuntime &RT, QualType QT)
static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT)
static std::string getSpecConstantFunctionName(clang::QualType SpecConstantType, ASTContext &Context)
static Value * handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF)
static Intrinsic::ID getFirstBitHighIntrinsic(CGHLSLRuntime &RT, QualType QT)
static Value * handleAsDoubleBuiltin(CodeGenFunction &CGF, const CallExpr *E)
static Value * handleHlslClip(const CallExpr *E, CodeGenFunction *CGF)
Expr * E
#define X(type, name)
Definition: Value.h:145
OffloadArch Arch
Definition: OffloadArch.cpp:10
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1201
MangleContext * createMangleContext(const TargetInfo *T=nullptr)
If T is null pointer, assume the target in ASTContext.
IdentifierTable & Idents
Definition: ASTContext.h:740
CanQualType IntTy
Definition: ASTContext.h:1231
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2898
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1750
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Definition: CGBuilder.h:140
CallArgList - Type for representing both the value and type of arguments in a call.
Definition: CGCall.h:274
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
llvm::Type * ConvertType(QualType T)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
llvm::Function * getSpecConstantFunction(const clang::QualType &SpecConstantType)
LValue EmitHLSLOutArgExpr(const HLSLOutArgExpr *E, CallArgList &Args, QualType Ty)
Definition: CGExpr.cpp:5847
void EmitWritebacks(const CallArgList &Args)
EmitWriteback - Emit callbacks for function.
Definition: CGCall.cpp:4863
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
Definition: CGExpr.cpp:264
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
llvm::LLVMContext & getLLVMContext()
llvm::Value * EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue)
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
llvm::Module & getModule() const
llvm::FunctionCallee CreateRuntimeFunction(llvm::FunctionType *Ty, StringRef Name, llvm::AttributeList ExtraAttrs=llvm::AttributeList(), bool Local=false, bool AssumeConvergent=false)
Create or return a runtime function declaration with the specified type and name.
const TargetInfo & getTarget() const
ASTContext & getContext() const
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
LValue - This represents an lvalue references.
Definition: CGValue.h:182
Address getAddress() const
Definition: CGValue.h:361
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
Definition: CGValue.h:42
llvm::Value * getAggregatePointer(QualType PointeeType, CodeGenFunction &CGF) const
Definition: CGValue.h:88
bool isScalar() const
Definition: CGValue.h:64
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
Definition: CGValue.h:71
ReturnValueSlot - Contains the address where the return value of a function can be stored,...
Definition: CGCall.h:379
The name of a declaration.
QualType getType() const
Definition: Expr.h:144
Represents a function declaration or definition.
Definition: Decl.h:1999
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition: Decl.h:2188
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Represents a parameter to a function.
Definition: Decl.h:1789
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2946
A (possibly-)qualified type.
Definition: TypeBase.h:937
Encodes a location in the source.
bool areArgsDestroyedLeftToRightInCallee() const
Are arguments to a call destroyed left to right in the callee? This is a fundamental language change,...
Definition: TargetCXXABI.h:188
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1288
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
Definition: TargetInfo.h:1360
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
Definition: Type.cpp:2209
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition: Type.cpp:2070
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2295
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2247
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition: Type.cpp:2316
bool isVectorType() const
Definition: TypeBase.h:8719
bool isFloatingType() const
Definition: Type.cpp:2308
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition: Type.cpp:2257
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
QualType getType() const
Definition: Value.cpp:237
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
unsigned getNumElements() const
Definition: TypeBase.h:4206
The JSON file list parser is used to communicate input to InstallAPI.
@ SC_Extern
Definition: Specifiers.h:251
@ SC_None
Definition: Specifiers.h:250
@ Result
The result type of a method or function.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * IntTy
int
Extra information about a function prototype.
Definition: TypeBase.h:5367