@@ -5320,6 +5320,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
53205320
53215321 return RValue::get(Carry);
53225322 }
5323+
5324+ // support for pointer tagging
5325+ case Builtin::BI__builtin_tag_pointer_mask_or:
5326+ return EmitBuiltinTagPointerMaskOr(E);
5327+ case Builtin::BI__builtin_tag_pointer_mask:
5328+ return EmitBuiltinTagPointerMask(E);
5329+ case Builtin::BI__builtin_tag_pointer_mask_as_int:
5330+ return EmitBuiltinTagPointerMaskAsInt(E);
5331+ case Builtin::BI__builtin_tag_pointer_shift_or:
5332+ return EmitBuiltinTagPointerShiftOr(E);
5333+ case Builtin::BI__builtin_tag_pointer_unshift:
5334+ return EmitBuiltinTagPointerUnshift(E);
5335+
53235336 case Builtin::BIaddressof:
53245337 case Builtin::BI__addressof:
53255338 case Builtin::BI__builtin_addressof:
@@ -21245,6 +21258,95 @@ Value *CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID,
2124521258 }
2124621259}
2124721260
21261+ /// Generate (x & ~mask) | (value & mask).
21262+ RValue CodeGenFunction::EmitBuiltinTagPointerMaskOr(const CallExpr *E) {
21263+ llvm::Value * Ptr = EmitScalarExpr(E->getArg(0));
21264+ llvm::Value * Value = EmitScalarExpr(E->getArg(1));
21265+ llvm::Value * Mask = EmitScalarExpr(E->getArg(2));
21266+
21267+ llvm::IntegerType * IntType = IntegerType::get(getLLVMContext(), CGM.getDataLayout().getIndexTypeSizeInBits(Ptr->getType()));
21268+
21269+ // TODO: avoid using bitcast and go path of ptr.tag (mirror to ptr.mask)
21270+ // to keep pointer's provenance, but this turns out a bit harder to do as it touches
21271+ // a lot of places in llvm
21272+ llvm::Value * PointerInt = Builder.CreateBitOrPointerCast(Ptr, IntType, "pointer_int");
21273+ llvm::Value * InvertedMask = Builder.CreateNot(Mask, "inverted_mask");
21274+
21275+ llvm::Value * MaskedPtr = Builder.CreateAnd(PointerInt, InvertedMask, "masked_ptr");
21276+ llvm::Value * MaskedValue = Builder.CreateAnd(Value, Mask, "masked_value");
21277+
21278+ llvm::Value * ResultInt = Builder.CreateOr(MaskedPtr, MaskedValue, "result_int");
21279+ llvm::Value * Result = Builder.CreateBitOrPointerCast(ResultInt, Ptr->getType(), "result_ptr");
21280+
21281+ return RValue::get(Result);
21282+ }
21283+
21284+ /// Generate (x << shift) | (value & ((1 << shift) - 1)).
21285+ RValue CodeGenFunction::EmitBuiltinTagPointerShiftOr(const CallExpr *E) {
21286+ llvm::Value * Ptr = EmitScalarExpr(E->getArg(0));
21287+ llvm::Value * Value = EmitScalarExpr(E->getArg(1));
21288+ llvm::Value * Shift = EmitScalarExpr(E->getArg(2));
21289+
21290+ llvm::IntegerType * IntType = IntegerType::get(getLLVMContext(), CGM.getDataLayout().getIndexTypeSizeInBits(Ptr->getType()));
21291+
21292+ // TODO: again, for now a bitcast, later ptr.shift_tag
21293+ llvm::Value * PointerInt = Builder.CreateBitOrPointerCast(Ptr, IntType, "pointer_int");
21294+ llvm::Value * ShiftedPointerInt = Builder.CreateShl(PointerInt, Shift);
21295+
21296+ auto *One = llvm::ConstantInt::get(IntType, 1);
21297+
21298+ llvm::Value * Mask = Builder.CreateSub(Builder.CreateShl(One, Shift), One, "mask");
21299+ llvm::Value * MaskedValue = Builder.CreateAdd(Value, Mask, "masked_value");
21300+ llvm::Value * PointerWithTag = Builder.CreateOr(ShiftedPointerInt, MaskedValue, "pointer_with_tag_int");
21301+
21302+ llvm::Value * Result = Builder.CreateBitOrPointerCast(PointerWithTag, Ptr->getType(), "result_ptr");
21303+ return RValue::get(Result);
21304+ }
21305+
21306+ /// Generate (x >> shift)
21307+ RValue CodeGenFunction::EmitBuiltinTagPointerUnshift(const CallExpr *E) {
21308+ llvm::Value * Ptr = EmitScalarExpr(E->getArg(0));
21309+ llvm::Value * Shift = EmitScalarExpr(E->getArg(1));
21310+
21311+ llvm::IntegerType * IntType = IntegerType::get(getLLVMContext(), CGM.getDataLayout().getIndexTypeSizeInBits(Ptr->getType()));
21312+
21313+ // for now I'm going path of bitcast
21314+ llvm::Value * PointerInt = Builder.CreateBitOrPointerCast(Ptr, IntType, "pointer_int");
21315+ llvm::Value * UnShiftedPointerInt = Builder.CreateAShr(PointerInt, Shift, "unshifted_pointer_int");
21316+
21317+ llvm::Value * Result = Builder.CreateBitOrPointerCast(UnShiftedPointerInt, Ptr->getType(), "result_ptr");
21318+ return RValue::get(Result);
21319+ }
21320+
21321+ /// Generate (x & mask).
21322+ RValue CodeGenFunction::EmitBuiltinTagPointerMask(const CallExpr *E) {
21323+ llvm::Value * Ptr = EmitScalarExpr(E->getArg(0));
21324+ llvm::Value * Mask = EmitScalarExpr(E->getArg(1));
21325+
21326+ llvm::Value *Result = Builder.CreateIntrinsic(
21327+ Intrinsic::ptrmask, {Ptr->getType(), Mask->getType()},
21328+ {Ptr, Mask}, nullptr, "result");
21329+
21330+ return RValue::get(Result);
21331+ }
21332+
21333+ /// Generate (x & mask) (but return it as number).
21334+ RValue CodeGenFunction::EmitBuiltinTagPointerMaskAsInt(const CallExpr *E) {
21335+ llvm::Value * Ptr = EmitScalarExpr(E->getArg(0));
21336+ llvm::Value * Mask = EmitScalarExpr(E->getArg(1));
21337+
21338+ llvm::IntegerType * IntType = IntegerType::get(getLLVMContext(), CGM.getDataLayout().getIndexTypeSizeInBits(Ptr->getType()));
21339+
21340+ llvm::Value *Result = Builder.CreateIntrinsic(
21341+ Intrinsic::ptrmask, {Ptr->getType(), Mask->getType()},
21342+ {Ptr, Mask}, nullptr, "result");
21343+
21344+ llvm::Value * IntResult = Builder.CreateBitOrPointerCast(Result, IntType, "int_result");
21345+
21346+ return RValue::get(IntResult);
21347+ }
21348+
21349+
2124821350namespace {
2124921351struct BuiltinAlignArgs {
2125021352 llvm::Value *Src = nullptr;
0 commit comments