Skip to content

Commit

Permalink
Merge pull request #293 from Xilinx/bump_to_ac1f2de7
Browse files Browse the repository at this point in the history
[AutoBump] Merge with ac1f2de (33)
  • Loading branch information
mgehre-amd authored Aug 22, 2024
2 parents aec0fbb + 393bc06 commit 8acc0d4
Show file tree
Hide file tree
Showing 83 changed files with 4,374 additions and 2,605 deletions.
30 changes: 24 additions & 6 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1267,10 +1267,30 @@ template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
// 'Base.Member'
const Expr *Base = E->getBase();
const ValueDecl *Member = E->getMemberDecl();

if (DiscardResult)
return this->discard(Base);

// MemberExprs are almost always lvalues, in which case we don't need to
// do the load. But sometimes they aren't.
const auto maybeLoadValue = [&]() -> bool {
if (E->isGLValue())
return true;
if (std::optional<PrimType> T = classify(E))
return this->emitLoadPop(*T, E);
return false;
};

if (const auto *VD = dyn_cast<VarDecl>(Member)) {
// I am almost confident in saying that a var decl must be static
// and therefore registered as a global variable. But this will probably
// turn out to be wrong some time in the future, as always.
if (auto GlobalIndex = P.getGlobal(VD))
return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();
return false;
}

if (Initializing) {
if (!this->delegate(Base))
return false;
Expand All @@ -1280,16 +1300,14 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
}

// Base above gives us a pointer on the stack.
// TODO: Implement non-FieldDecl members.
const ValueDecl *Member = E->getMemberDecl();
if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
return this->emitGetPtrField(F->Offset, E);
return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
return this->emitGetPtrField(F->Offset, E) && maybeLoadValue();
}

return false;
Expand Down Expand Up @@ -1624,7 +1642,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
return false;
if (!this->emitLoad(*LT, E))
return false;
if (*LT != *LHSComputationT) {
if (LT != LHSComputationT) {
if (!this->emitCast(*LT, *LHSComputationT, E))
return false;
}
Expand Down Expand Up @@ -1680,7 +1698,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
}

// And now cast from LHSComputationT to ResultT.
if (*ResultT != *LHSComputationT) {
if (ResultT != LHSComputationT) {
if (!this->emitCast(*LHSComputationT, *ResultT, E))
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Disasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
const Descriptor *Desc = G->block()->getDescriptor();
Pointer GP = getPtrGlobal(GI);

OS << GI << ": " << (void *)G->block() << " ";
OS << GI << ": " << (const void *)G->block() << " ";
{
ColorScope SC(OS, true,
GP.isInitialized()
Expand Down Expand Up @@ -268,7 +268,7 @@ LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream &OS, unsigned Indentation,
LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const {
{
ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
OS << "Block " << (void *)this << "\n";
OS << "Block " << (const void *)this << "\n";
}
unsigned NPointers = 0;
for (const Pointer *P = Pointers; P; P = P->Next) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/FunctionPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class FunctionPointer final {

const Function *getFunction() const { return Func; }
bool isZero() const { return !Func; }
bool isValid() const { return Valid; }
bool isWeak() const {
if (!Func || !Valid)
return false;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2236,6 +2236,10 @@ inline bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
<< const_cast<Expr *>(E) << E->getSourceRange();
return false;
}

if (!FuncPtr.isValid())
return false;

assert(F);

// Check argument nullability state.
Expand Down
118 changes: 118 additions & 0 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,117 @@ static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
return true;
}

/// __builtin_is_aligned()
/// __builtin_align_up()
/// __builtin_align_down()
/// The first parameter is either an integer or a pointer.
/// The second parameter is the requested alignment as an integer.
static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
unsigned BuiltinOp = Func->getBuiltinID();
unsigned CallSize = callArgSize(S, Call);

PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT);

if (Alignment < 0 || !Alignment.isPowerOf2()) {
S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
return false;
}
unsigned SrcWidth = S.getCtx().getIntWidth(Call->getArg(0)->getType());
APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
if (APSInt::compareValues(Alignment, MaxValue) > 0) {
S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
<< MaxValue << Call->getArg(0)->getType() << Alignment;
return false;
}

// The first parameter is either an integer or a pointer (but not a function
// pointer).
PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));

if (isIntegralType(FirstArgT)) {
const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize);
APSInt Align = Alignment.extOrTrunc(Src.getBitWidth());
if (BuiltinOp == Builtin::BI__builtin_align_up) {
APSInt AlignedVal =
APSInt((Src + (Align - 1)) & ~(Align - 1), Src.isUnsigned());
pushInteger(S, AlignedVal, Call->getType());
} else if (BuiltinOp == Builtin::BI__builtin_align_down) {
APSInt AlignedVal = APSInt(Src & ~(Align - 1), Src.isUnsigned());
pushInteger(S, AlignedVal, Call->getType());
} else {
assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
S.Stk.push<Boolean>((Src & (Align - 1)) == 0);
}
return true;
}

assert(FirstArgT == PT_Ptr);
const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize);

unsigned PtrOffset = Ptr.getByteOffset();
PtrOffset = Ptr.getIndex();
CharUnits BaseAlignment =
S.getCtx().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
CharUnits PtrAlign =
BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));

if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
if (PtrAlign.getQuantity() >= Alignment) {
S.Stk.push<Boolean>(true);
return true;
}
// If the alignment is not known to be sufficient, some cases could still
// be aligned at run time. However, if the requested alignment is less or
// equal to the base alignment and the offset is not aligned, we know that
// the run-time value can never be aligned.
if (BaseAlignment.getQuantity() >= Alignment &&
PtrAlign.getQuantity() < Alignment) {
S.Stk.push<Boolean>(false);
return true;
}

S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
<< Alignment;
return false;
}

assert(BuiltinOp == Builtin::BI__builtin_align_down ||
BuiltinOp == Builtin::BI__builtin_align_up);

// For align_up/align_down, we can return the same value if the alignment
// is known to be greater or equal to the requested value.
if (PtrAlign.getQuantity() >= Alignment) {
S.Stk.push<Pointer>(Ptr);
return true;
}

// The alignment could be greater than the minimum at run-time, so we cannot
// infer much about the resulting pointer value. One case is possible:
// For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
// can infer the correct index if the requested alignment is smaller than
// the base alignment so we can perform the computation on the offset.
if (BaseAlignment.getQuantity() >= Alignment) {
assert(Alignment.getBitWidth() <= 64 &&
"Cannot handle > 64-bit address-space");
uint64_t Alignment64 = Alignment.getZExtValue();
CharUnits NewOffset =
CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
? llvm::alignDown(PtrOffset, Alignment64)
: llvm::alignTo(PtrOffset, Alignment64));

S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
return true;
}

// Otherwise, we cannot constant-evaluate the result.
S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
return false;
}

bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
const InterpFrame *Frame = S.Current;
Expand Down Expand Up @@ -1291,6 +1402,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case Builtin::BI__builtin_is_aligned:
case Builtin::BI__builtin_align_up:
case Builtin::BI__builtin_align_down:
if (!interp__builtin_is_aligned_up_down(S, OpPC, Frame, F, Call))
return false;
break;

default:
S.FFDiag(S.Current->getLocation(OpPC),
diag::note_invalid_subexpr_in_const_expr)
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ void print(llvm::raw_ostream &OS, const Pointer &P, ASTContext &Ctx,
}

void InterpFrame::describe(llvm::raw_ostream &OS) const {
// We create frames for builtin functions as well, but we can't reliably
// diagnose them. The 'in call to' diagnostics for them add no value to the
// user _and_ it doesn't generally work since the argument types don't always
// match the function prototype. Just ignore them.
if (const auto *F = getFunction(); F && F->isBuiltin())
return;

const FunctionDecl *F = getCallee();
if (const auto *M = dyn_cast<CXXMethodDecl>(F);
M && M->isInstance() && !isa<CXXConstructorDecl>(F)) {
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,13 +241,10 @@ class Pointer {

/// Checks if the pointer is null.
bool isZero() const {
if (Offset != 0)
return false;

if (isBlockPointer())
return asBlockPointer().Pointee == nullptr;
assert(isIntegralPointer());
return asIntPointer().Value == 0;
return asIntPointer().Value == 0 && Offset == 0;
}
/// Checks if the pointer is live.
bool isLive() const {
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/Interp/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ void State::addCallStack(unsigned Limit) {
SmallString<128> Buffer;
llvm::raw_svector_ostream Out(Buffer);
F->describe(Out);
addDiag(CallRange.getBegin(), diag::note_constexpr_call_here)
<< Out.str() << CallRange;
if (!Buffer.empty())
addDiag(CallRange.getBegin(), diag::note_constexpr_call_here)
<< Out.str() << CallRange;
}
}
8 changes: 4 additions & 4 deletions clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ class LLVM_LIBRARY_VISIBILITY SPIR32TargetInfo : public SPIRTargetInfo {
SizeType = TargetInfo::UnsignedInt;
PtrDiffType = IntPtrType = TargetInfo::SignedInt;
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -276,7 +276,7 @@ class LLVM_LIBRARY_VISIBILITY SPIR64TargetInfo : public SPIRTargetInfo {
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong;
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand Down Expand Up @@ -336,7 +336,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo {
SizeType = TargetInfo::UnsignedInt;
PtrDiffType = IntPtrType = TargetInfo::SignedInt;
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -357,7 +357,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong;
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024");
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand Down
28 changes: 20 additions & 8 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,14 @@ static bool addExceptionArgs(const ArgList &Args, types::ID InputType,
bool EH = Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions,
false);

bool EHa = Args.hasFlag(options::OPT_fasync_exceptions,
options::OPT_fno_async_exceptions, false);
if (EHa) {
CmdArgs.push_back("-fasync-exceptions");
EH = true;
// Async exceptions are Windows MSVC only.
if (Triple.isWindowsMSVCEnvironment()) {
bool EHa = Args.hasFlag(options::OPT_fasync_exceptions,
options::OPT_fno_async_exceptions, false);
if (EHa) {
CmdArgs.push_back("-fasync-exceptions");
EH = true;
}
}

// Obj-C exceptions are enabled by default, regardless of -fexceptions. This
Expand Down Expand Up @@ -8102,7 +8105,8 @@ struct EHFlags {
/// The 'a' modifier is unimplemented and fundamentally hard in LLVM IR.
/// - c: Assume that extern "C" functions are implicitly nounwind.
/// The default is /EHs-c-, meaning cleanups are disabled.
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args,
bool isWindowsMSVC) {
EHFlags EH;

std::vector<std::string> EHArgs =
Expand All @@ -8112,8 +8116,15 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args) {
switch (EHVal[I]) {
case 'a':
EH.Asynch = maybeConsumeDash(EHVal, I);
if (EH.Asynch)
if (EH.Asynch) {
// Async exceptions are Windows MSVC only.
if (!isWindowsMSVC) {
EH.Asynch = false;
D.Diag(clang::diag::warn_drv_unused_argument) << "/EHa" << EHVal;
continue;
}
EH.Synch = false;
}
continue;
case 'c':
EH.NoUnwindC = maybeConsumeDash(EHVal, I);
Expand Down Expand Up @@ -8177,7 +8188,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,

const Driver &D = getToolChain().getDriver();

EHFlags EH = parseClangCLEHFlags(D, Args);
bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment();
EHFlags EH = parseClangCLEHFlags(D, Args, IsWindowsMSVC);
if (!isNVPTX && (EH.Synch || EH.Asynch)) {
if (types::isCXX(InputType))
CmdArgs.push_back("-fcxx-exceptions");
Expand Down
9 changes: 6 additions & 3 deletions clang/lib/Index/USRGeneration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,13 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) {
Out << '>';
}

QualType CanonicalType = D->getType().getCanonicalType();
// Mangle in type information for the arguments.
for (auto *PD : D->parameters()) {
Out << '#';
VisitType(PD->getType());
if (const auto *FPT = CanonicalType->getAs<FunctionProtoType>()) {
for (QualType PT : FPT->param_types()) {
Out << '#';
VisitType(PT);
}
}
if (D->isVariadic())
Out << '.';
Expand Down
Loading

0 comments on commit 8acc0d4

Please sign in to comment.