[PATCH] D55510: [ExprConstant] Improve memchr/memcmp for type mismatch and multibyte element types
Richard Smith - zygoloid via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 10 13:42:23 PST 2018
rsmith added inline comments.
================
Comment at: lib/AST/ExprConstant.cpp:6147-6148
+ return ZeroInitialization(E);
+ if (!Result.checkNullPointerForFoldAccess(Info, E, AK_Read))
+ return false;
+ QualType CharTy =
----------------
Why do we need to do this explicitly, rather than allowing to simply happen as part of the first `handleLValueToRValueConversion` below?
================
Comment at: lib/AST/ExprConstant.cpp:6150
+ QualType CharTy =
+ Info.Ctx.getBaseElementType(getType(Result.getLValueBase()));
+ const bool IsRawByte = BuiltinOp == Builtin::BImemchr ||
----------------
Considering the LValue base here is incorrect. The object or array we're copying could be a subobject, and the complete object type (the type of the lvalue base) is irrelevant for such copies. Use `Result.Designator.getType(Info.Ctx)` to find the type that the lvalue designates. (You can bail out here if the designator is invalid; `handleLValueToRValueConversion` will always fail on such cases anyway.
================
Comment at: lib/AST/ExprConstant.cpp:6159-6160
+ // Give up on byte-oriented matching against multibyte elements.
+ if (IsRawByte && Info.Ctx.getTypeSize(CharTy) > Info.Ctx.getCharWidth())
+ return false;
// Figure out what value we're actually looking for (after converting to
----------------
Please add an assert here that the types do match in the non-raw-byte case. (They must, or the subobject designator would be invalid; the only special case is that a `void*` can point to anything, and only the `memchr` variants here take a `void*`.)
================
Comment at: lib/AST/ExprConstant.cpp:8433-8436
+ QualType CharTy1 =
+ Info.Ctx.getBaseElementType(getType(String1.getLValueBase()));
+ QualType CharTy2 =
+ Info.Ctx.getBaseElementType(getType(String2.getLValueBase()));
----------------
Per above comment, this is not correct.
================
Comment at: lib/AST/ExprConstant.cpp:8467
+ assert(MaxLength);
+ for (;;) {
+ APValue Char1, Char2;
----------------
Style nit: please use `while (true)` rather than `for (;;)`
================
Comment at: lib/AST/ExprConstant.cpp:8471-8476
+ // We have compatible in-memory widths, but a possible type and internal
+ // representation mismatch. Assuming two's complement representation,
+ // including 0 for `false` and 1 for `true`, we can check an appropriate
+ // number of elements for equality even if they are not byte-sized.
+ const APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width);
+ const APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width);
----------------
The *only* possible problem here is for `bool`, right? This comment would be clearer if it said that.
================
Comment at: lib/AST/ExprConstant.cpp:8484
+ }
+ return false;
+ }
----------------
Please add a comment before this return indicating that the result depends on byte order (and maybe a FIXME to compare the bytes in the right order rather than bailing out). We're going to need to deal with the byte order / representation problem for `std::bit_cast` pretty soon anyway.
================
Comment at: lib/AST/ExprConstant.cpp:8488-8489
+ return false;
+ if (MaxLength <= LengthPerElement)
+ break;
+ MaxLength -= LengthPerElement;
----------------
This looks wrong. If `0 < MaxLength && MaxLength < LengthPerElement`, we're supposed to compare *part of* the next element; this current approach doesn't do that. (If you did one more full-element compare, that'd be conservatively correct because we're only checking for equality, not ordering, but perhaps we should only permit cases where `MaxLength` is a multiple of `LengthPerElement`?
================
Comment at: test/CodeGenCXX/builtins.cpp:41
+ matchedFirstByteIn04030201();
+ // CHECK: call void @_ZN27MemchrMultibyteElementTests26matchedFirstByteIn04030201Ev()
+ }
----------------
Please test this in a way that doesn't rely on IR generation constant-evaluating `if` conditions. Moreover, there's nothing about IR generation that you're actually testing here, so please phrase this as a `Sema` test instead (eg, check that a VLA bound gets folded to a constant). Likewise for the other tests below.
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D55510/new/
https://reviews.llvm.org/D55510
More information about the cfe-commits
mailing list