|
16 | 16 | #include "CIRGenCstEmitter.h"
|
17 | 17 | #include "CIRGenFunction.h"
|
18 | 18 | #include "CIRGenModule.h"
|
| 19 | +#include "CIRGenValue.h" |
19 | 20 | #include "TargetInfo.h"
|
| 21 | +#include "clang/AST/Expr.h" |
| 22 | +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" |
20 | 23 | #include "clang/CIR/MissingFeatures.h"
|
21 | 24 |
|
22 | 25 | // TODO(cir): we shouldn't need this but we currently reuse intrinsic IDs for
|
|
30 | 33 | #include "clang/Frontend/FrontendDiagnostic.h"
|
31 | 34 |
|
32 | 35 | #include "mlir/Dialect/Func/IR/FuncOps.h"
|
| 36 | +#include "mlir/IR/BuiltinAttributes.h" |
33 | 37 | #include "mlir/IR/Value.h"
|
34 | 38 | #include "clang/CIR/Dialect/IR/CIRDialect.h"
|
35 | 39 | #include "llvm/Support/ErrorHandling.h"
|
@@ -330,6 +334,58 @@ static mlir::Value MakeAtomicCmpXchgValue(CIRGenFunction &cgf,
|
330 | 334 | return returnBool ? op.getResult(1) : op.getResult(0);
|
331 | 335 | }
|
332 | 336 |
|
| 337 | +static mlir::Value MakeAtomicFenceValue(CIRGenFunction &cgf, |
| 338 | + const CallExpr *expr, |
| 339 | + cir::MemScopeKind syncScope) { |
| 340 | + QualType typ = expr->getType(); |
| 341 | + auto &builder = cgf.getBuilder(); |
| 342 | + |
| 343 | + auto intType = |
| 344 | + expr->getArg(0)->getType()->getPointeeType()->isUnsignedIntegerType() |
| 345 | + ? builder.getUIntNTy(cgf.getContext().getTypeSize(typ)) |
| 346 | + : builder.getSIntNTy(cgf.getContext().getTypeSize(typ)); |
| 347 | + |
| 348 | + auto orderingVal = |
| 349 | + emitToInt(cgf, cgf.emitScalarExpr(expr->getArg(1)), typ, intType); |
| 350 | + auto orderingAttr = |
| 351 | + orderingVal.getDefiningOp()->getAttrOfType<mlir::IntegerAttr>("value"); |
| 352 | + |
| 353 | + cir::MemOrder ordering; |
| 354 | + switch (orderingAttr.getInt()) { |
| 355 | + case 0: { |
| 356 | + ordering = cir::MemOrder::Relaxed; |
| 357 | + break; |
| 358 | + } |
| 359 | + case 1: { |
| 360 | + ordering = cir::MemOrder::Consume; |
| 361 | + break; |
| 362 | + } |
| 363 | + case 2: { |
| 364 | + ordering = cir::MemOrder::Acquire; |
| 365 | + break; |
| 366 | + } |
| 367 | + case 3: { |
| 368 | + ordering = cir::MemOrder::Release; |
| 369 | + break; |
| 370 | + } |
| 371 | + case 4: { |
| 372 | + ordering = cir::MemOrder::AcquireRelease; |
| 373 | + break; |
| 374 | + } |
| 375 | + case 5: { |
| 376 | + ordering = cir::MemOrder::SequentiallyConsistent; |
| 377 | + break; |
| 378 | + } |
| 379 | + default: |
| 380 | + llvm_unreachable("invalid memory ordering scope"); |
| 381 | + } |
| 382 | + |
| 383 | + builder.create<cir::AtomicFence>(cgf.getLoc(expr->getSourceRange()), |
| 384 | + syncScope, ordering); |
| 385 | + |
| 386 | + return mlir::Value(); |
| 387 | +} |
| 388 | + |
333 | 389 | static bool
|
334 | 390 | typeRequiresBuiltinLaunderImp(const ASTContext &astContext, QualType ty,
|
335 | 391 | llvm::SmallPtrSetImpl<const Decl *> &seen) {
|
@@ -1840,10 +1896,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
|
1840 | 1896 | llvm_unreachable("BI__atomic_clear NYI");
|
1841 | 1897 |
|
1842 | 1898 | case Builtin::BI__atomic_thread_fence:
|
| 1899 | + return RValue::get( |
| 1900 | + MakeAtomicFenceValue(*this, E, cir::MemScopeKind::MemScope_System)); |
1843 | 1901 | case Builtin::BI__atomic_signal_fence:
|
| 1902 | + return RValue::get(MakeAtomicFenceValue( |
| 1903 | + *this, E, cir::MemScopeKind::MemScope_SingleThread)); |
1844 | 1904 | case Builtin::BI__c11_atomic_thread_fence:
|
1845 | 1905 | case Builtin::BI__c11_atomic_signal_fence:
|
1846 |
| - llvm_unreachable("BI__atomic_thread_fence like NYI"); |
| 1906 | + llvm_unreachable("BI__c11_atomic_thread_fence like NYI"); |
1847 | 1907 |
|
1848 | 1908 | case Builtin::BI__builtin_signbit:
|
1849 | 1909 | case Builtin::BI__builtin_signbitf:
|
|
0 commit comments