31 changes: 21 additions & 10 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,8 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Inc(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

Expand All @@ -585,7 +586,8 @@ bool Inc(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool IncPop(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

Expand All @@ -599,7 +601,8 @@ bool IncPop(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Dec(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

Expand All @@ -612,7 +615,8 @@ bool Dec(InterpState &S, CodePtr OpPC) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool DecPop(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

Expand Down Expand Up @@ -641,7 +645,8 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,

inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

Expand All @@ -650,7 +655,8 @@ inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {

inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

Expand All @@ -660,6 +666,9 @@ inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

Expand All @@ -669,6 +678,8 @@ inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

Expand Down Expand Up @@ -774,9 +785,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
// element in the same array are NOT equal. They have the same Base value,
// but a different Offset. This is a pretty rare case, so we fix this here
// by comparing pointers to the first elements.
if (LHS.isArrayRoot())
if (!LHS.isDummy() && LHS.isArrayRoot())
VL = LHS.atIndex(0).getByteOffset();
if (RHS.isArrayRoot())
if (!RHS.isDummy() && RHS.isArrayRoot())
VR = RHS.atIndex(0).getByteOffset();

S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
Expand Down Expand Up @@ -1895,7 +1906,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();

if (!CheckDummy(S, OpPC, Ptr))
if (Ptr.isDummy())
return true;

if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
Expand All @@ -1909,7 +1920,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
const T &Offset = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckDummy(S, OpPC, Ptr)) {
if (Ptr.isDummy()) {
S.Stk.push<Pointer>(Ptr);
return true;
}
Expand Down
32 changes: 16 additions & 16 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,14 @@ class EmitAssemblyHelper {
TargetTriple.getVendor() != llvm::Triple::Apple;
}

/// Check whether we should emit a flag for UnifiedLTO.
/// The UnifiedLTO module flag should be set when UnifiedLTO is enabled for
/// ThinLTO or Full LTO with module summaries.
bool shouldEmitUnifiedLTOModueFlag() const {
return CodeGenOpts.UnifiedLTO &&
(CodeGenOpts.PrepareForThinLTO || shouldEmitRegularLTOSummary());
}

public:
EmitAssemblyHelper(DiagnosticsEngine &_Diags,
const HeaderSearchOptions &HeaderSearchOpts,
Expand Down Expand Up @@ -1036,7 +1044,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule)
MPM.addPass(VerifierPass());

if (Action == Backend_EmitBC || Action == Backend_EmitLL) {
if (Action == Backend_EmitBC || Action == Backend_EmitLL ||
CodeGenOpts.FatLTO) {
if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
Expand All @@ -1047,11 +1056,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!ThinLinkOS)
return;
}
if (CodeGenOpts.UnifiedLTO)
TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
MPM.addPass(ThinLTOBitcodeWriterPass(
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
} else {
} else if (Action == Backend_EmitLL) {
MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
/*EmitLTOSummary=*/true));
}
Expand All @@ -1065,24 +1072,17 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
uint32_t(1));
if (CodeGenOpts.UnifiedLTO)
TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
}
if (Action == Backend_EmitBC)
if (Action == Backend_EmitBC) {
MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
EmitLTOSummary));
else
} else if (Action == Backend_EmitLL) {
MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
EmitLTOSummary));
}
}
}
if (CodeGenOpts.FatLTO) {
// Set the EnableSplitLTOUnit and UnifiedLTO module flags, since FatLTO
// uses a different action than Backend_EmitBC or Backend_EmitLL.
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit",
uint32_t(CodeGenOpts.EnableSplitLTOUnit));
if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO"))

if (shouldEmitUnifiedLTOModueFlag())
TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
}

Expand Down
30 changes: 18 additions & 12 deletions clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7023,19 +7023,25 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
S.getSingleClause<OMPUseClause>())) &&
"OMPNowaitClause clause is used separately in OMPInteropDirective.");

if (const auto *C = S.getSingleClause<OMPInitClause>()) {
llvm::Value *InteropvarPtr =
EmitLValue(C->getInteropVar()).getPointer(*this);
llvm::omp::OMPInteropType InteropType = llvm::omp::OMPInteropType::Unknown;
if (C->getIsTarget()) {
InteropType = llvm::omp::OMPInteropType::Target;
} else {
assert(C->getIsTargetSync() && "Expected interop-type target/targetsync");
InteropType = llvm::omp::OMPInteropType::TargetSync;
auto ItOMPInitClause = S.getClausesOfKind<OMPInitClause>();
if (!ItOMPInitClause.empty()) {
// Look at the multiple init clauses
for (const OMPInitClause *C : ItOMPInitClause) {
llvm::Value *InteropvarPtr =
EmitLValue(C->getInteropVar()).getPointer(*this);
llvm::omp::OMPInteropType InteropType =
llvm::omp::OMPInteropType::Unknown;
if (C->getIsTarget()) {
InteropType = llvm::omp::OMPInteropType::Target;
} else {
assert(C->getIsTargetSync() &&
"Expected interop-type target/targetsync");
InteropType = llvm::omp::OMPInteropType::TargetSync;
}
OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType,
Device, NumDependences, DependenceList,
Data.HasNowaitClause);
}
OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType, Device,
NumDependences, DependenceList,
Data.HasNowaitClause);
} else if (const auto *C = S.getSingleClause<OMPDestroyClause>()) {
llvm::Value *InteropvarPtr =
EmitLValue(C->getInteropVar()).getPointer(*this);
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
assert(Error.empty());

auto *Fn = cast<llvm::Function>(GV);
static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
Fn->addFnAttr("sign-return-address", SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());

if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
Fn->addFnAttr("sign-return-address-key",
Expand Down
8 changes: 1 addition & 7 deletions clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
diag::warn_target_unsupported_branch_protection_attribute)
<< Arch;
} else {
static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
assert(static_cast<unsigned>(BPI.SignReturnAddr) <= 2 &&
"Unexpected SignReturnAddressScopeKind");
Fn->addFnAttr(
"sign-return-address",
SignReturnAddrStr[static_cast<int>(BPI.SignReturnAddr)]);

Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
Fn->addFnAttr("branch-target-enforcement",
BPI.BranchTargetEnforcement ? "true" : "false");
}
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2763,13 +2763,13 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
StringRef BitcodeSuffix,
const llvm::Triple &Triple) {
const llvm::Triple &Triple,
const ToolChain &HostTC) {
SmallVector<StringRef, 8> LibraryPaths;

// Add path to clang lib / lib64 folder.
SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
LibraryPaths.emplace_back(DefaultLibPath.c_str());
// Check all of the standard library search paths used by the compiler.
for (const auto &LibPath : HostTC.getFilePaths())
LibraryPaths.emplace_back(LibPath);

// Add user defined library paths from LIBRARY_PATH.
std::optional<std::string> LibPath =
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args,

void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
StringRef BitcodeSuffix, const llvm::Triple &Triple);
StringRef BitcodeSuffix, const llvm::Triple &Triple,
const ToolChain &HostTC);

void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
const llvm::opt::ArgList &Args,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ void CudaToolChain::addClangTargetOptions(
return;

addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
getTriple());
getTriple(), HostTC);
}
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ using namespace llvm::MachO;

namespace clang::installapi {

// Exported NamedDecl needs to have externally visibiliy linkage and
// Exported NamedDecl needs to have external linkage and
// default visibility from LinkageComputer.
static bool isExported(const NamedDecl *D) {
auto LV = D->getLinkageAndVisibility();
Expand Down
19 changes: 17 additions & 2 deletions clang/lib/Sema/JumpDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
break;
}

case Stmt::OpenACCComputeConstructClass: {
unsigned NewParentScope = Scopes.size();
OpenACCComputeConstruct *CC = cast<OpenACCComputeConstruct>(S);
Scopes.push_back(GotoScope(
ParentScope, diag::note_acc_branch_into_compute_construct,
diag::note_acc_branch_out_of_compute_construct, CC->getBeginLoc()));
BuildScopeInformation(CC->getStructuredBlock(), NewParentScope);
return;
}

default:
if (auto *ED = dyn_cast<OMPExecutableDirective>(S)) {
if (!ED->isStandaloneDirective()) {
Expand Down Expand Up @@ -936,11 +946,16 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally);
break;
}
if (Scopes[I].InDiag == diag::note_omp_protected_structured_block) {
} else if (Scopes[I].InDiag ==
diag::note_omp_protected_structured_block) {
S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);
S.Diag(To->getBeginLoc(), diag::note_omp_exits_structured_block);
break;
} else if (Scopes[I].InDiag ==
diag::note_acc_branch_into_compute_construct) {
S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);
S.Diag(Scopes[I].Loc, diag::note_acc_branch_out_of_compute_construct);
return;
}
}
}
Expand Down
25 changes: 21 additions & 4 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,17 +2190,23 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
}

/// Checks that __builtin_popcountg was called with a single argument, which is
/// an integer.
/// an unsigned integer.
static bool SemaBuiltinPopcountg(Sema &S, CallExpr *TheCall) {
if (checkArgCount(S, TheCall, 1))
return true;

Expr *Arg = TheCall->getArg(0);
ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0));
if (ArgRes.isInvalid())
return true;

Expr *Arg = ArgRes.get();
TheCall->setArg(0, Arg);

QualType ArgTy = Arg->getType();

if (!ArgTy->isIntegerType()) {
if (!ArgTy->isUnsignedIntegerType()) {
S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
<< 1 << /*integer ty*/ 7 << ArgTy;
<< 1 << /*unsigned integer ty*/ 7 << ArgTy;
return true;
}
return false;
Expand Down Expand Up @@ -16538,6 +16544,17 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
}
}

// Complain if we are converting a lambda expression to a boolean value
if (const auto *MCallExpr = dyn_cast<CXXMemberCallExpr>(E)) {
if (const auto *MRecordDecl = MCallExpr->getRecordDecl();
MRecordDecl && MRecordDecl->isLambda()) {
Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
<< /*LambdaPointerConversionOperatorType=*/3
<< MRecordDecl->getSourceRange() << Range << IsEqual;
return;
}
}

// Expect to find a single Decl. Skip anything more complicated.
ValueDecl *D = nullptr;
if (DeclRefExpr *R = dyn_cast<DeclRefExpr>(E)) {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4962,7 +4962,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
if (RC->getModifier() != OMPC_REDUCTION_inscan)
continue;
for (Expr *E : RC->copy_array_temps())
MarkDeclarationsReferencedInExpr(E);
if (E)
MarkDeclarationsReferencedInExpr(E);
}
if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
for (Expr *E : AC->varlists())
Expand Down
16 changes: 16 additions & 0 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
Diag(IdentLoc, diag::warn_reserved_extern_symbol)
<< TheDecl << static_cast<int>(Status);

// If this label is in a compute construct scope, we need to make sure we
// check gotos in/out.
if (getCurScope()->isInOpenACCComputeConstructScope())
setFunctionHasBranchProtectedScope();

// Otherwise, things are good. Fill in the declaration and return it.
LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
TheDecl->setStmt(LS);
Expand Down Expand Up @@ -3304,6 +3309,12 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
LabelDecl *TheDecl) {
setFunctionHasBranchIntoScope();

// If this goto is in a compute construct scope, we need to make sure we check
// gotos in/out.
if (getCurScope()->isInOpenACCComputeConstructScope())
setFunctionHasBranchProtectedScope();

TheDecl->markUsed(Context);
return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
}
Expand Down Expand Up @@ -3332,6 +3343,11 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,

setFunctionHasIndirectGoto();

// If this goto is in a compute construct scope, we need to make sure we
// check gotos in/out.
if (getCurScope()->isInOpenACCComputeConstructScope())
setFunctionHasBranchProtectedScope();

return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
}

Expand Down
5 changes: 5 additions & 0 deletions clang/test/AST/Interp/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,3 +564,8 @@ namespace LocalVLA {
#endif
}
}

char melchizedek[2200000000];
typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t;
constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok
constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok
8 changes: 4 additions & 4 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ const int b = 3;
_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
// pedantic-expected-warning {{not an integer constant expression}}

/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
const int c; // ref-note {{declared here}} \
// pedantic-ref-note {{declared here}}
const int c; // all-note {{declared here}}
_Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{initializer of 'c' is unknown}} \
// pedantic-ref-error {{not an integral constant expression}} \
// pedantic-ref-note {{initializer of 'c' is unknown}} \
// expected-error {{not an integral constant expression}} \
// pedantic-expected-error {{not an integral constant expression}}
// expected-note {{initializer of 'c' is unknown}} \
// pedantic-expected-error {{not an integral constant expression}} \
// pedantic-expected-note {{initializer of 'c' is unknown}}

_Static_assert(&c != 0, ""); // ref-warning {{always true}} \
// pedantic-ref-warning {{always true}} \
Expand Down
3 changes: 2 additions & 1 deletion clang/test/AST/Interp/cxx98.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ template struct C<cval>;

/// FIXME: This example does not get properly diagnosed in the new interpreter.
extern const int recurse1;
const int recurse2 = recurse1; // ref-note {{here}}
const int recurse2 = recurse1; // both-note {{declared here}}
const int recurse1 = 1;
int array1[recurse1];
int array2[recurse2]; // ref-warning 2{{variable length array}} \
// ref-note {{initializer of 'recurse2' is not a constant expression}} \
// expected-warning {{variable length array}} \
// expected-note {{read of non-const variable 'recurse2'}} \
// expected-error {{variable length array}}

int NCI; // both-note {{declared here}}
Expand Down
1 change: 1 addition & 0 deletions clang/test/CXX/drs/dr18xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ namespace dr1837 { // dr1837: 3.3
struct A {
int f();
bool b = [] {
// since-cxx11-warning@-1 {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
struct Local {
static_assert(sizeof(this->f()) == sizeof(int), "");
};
Expand Down
9 changes: 5 additions & 4 deletions clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ void nesting() {

namespace overloading {
void bool_conversion() {
if ([](){}) {
if ([](){}) { // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
}

bool b = []{};
bool b = []{}; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
b = (bool)[]{};
}

Expand Down Expand Up @@ -108,8 +108,9 @@ void call_with_lambda() {
using decltype(a)::operator id<void(*)()>; // expected-note {{here}}
} extern d;

bool r1 = c;
bool r2 = d; // expected-error {{private}}
bool r1 = c; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
bool r2 = d; // expected-error {{private}} \
expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
}

namespace PR13117 {
Expand Down
28 changes: 14 additions & 14 deletions clang/test/CodeGen/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,38 +948,38 @@ void test_builtin_popcountg(unsigned char uc, unsigned short us,
volatile int pop;
pop = __builtin_popcountg(uc);
// CHECK: %1 = load i8, ptr %uc.addr, align 1
// CHECK-NEXT: %conv = zext i8 %1 to i32
// CHECK-NEXT: %2 = call i32 @llvm.ctpop.i32(i32 %conv)
// CHECK-NEXT: store volatile i32 %2, ptr %pop, align 4
// CHECK-NEXT: %2 = call i8 @llvm.ctpop.i8(i8 %1)
// CHECK-NEXT: %cast = sext i8 %2 to i32
// CHECK-NEXT: store volatile i32 %cast, ptr %pop, align 4
pop = __builtin_popcountg(us);
// CHECK-NEXT: %3 = load i16, ptr %us.addr, align 2
// CHECK-NEXT: %conv1 = zext i16 %3 to i32
// CHECK-NEXT: %4 = call i32 @llvm.ctpop.i32(i32 %conv1)
// CHECK-NEXT: store volatile i32 %4, ptr %pop, align 4
// CHECK-NEXT: %4 = call i16 @llvm.ctpop.i16(i16 %3)
// CHECK-NEXT: %cast1 = sext i16 %4 to i32
// CHECK-NEXT: store volatile i32 %cast1, ptr %pop, align 4
pop = __builtin_popcountg(ui);
// CHECK-NEXT: %5 = load i32, ptr %ui.addr, align 4
// CHECK-NEXT: %6 = call i32 @llvm.ctpop.i32(i32 %5)
// CHECK-NEXT: store volatile i32 %6, ptr %pop, align 4
pop = __builtin_popcountg(ul);
// CHECK-NEXT: %7 = load i64, ptr %ul.addr, align 8
// CHECK-NEXT: %8 = call i64 @llvm.ctpop.i64(i64 %7)
// CHECK-NEXT: %cast = trunc i64 %8 to i32
// CHECK-NEXT: store volatile i32 %cast, ptr %pop, align 4
// CHECK-NEXT: %cast2 = trunc i64 %8 to i32
// CHECK-NEXT: store volatile i32 %cast2, ptr %pop, align 4
pop = __builtin_popcountg(ull);
// CHECK-NEXT: %9 = load i64, ptr %ull.addr, align 8
// CHECK-NEXT: %10 = call i64 @llvm.ctpop.i64(i64 %9)
// CHECK-NEXT: %cast2 = trunc i64 %10 to i32
// CHECK-NEXT: store volatile i32 %cast2, ptr %pop, align 4
// CHECK-NEXT: %cast3 = trunc i64 %10 to i32
// CHECK-NEXT: store volatile i32 %cast3, ptr %pop, align 4
pop = __builtin_popcountg(ui128);
// CHECK-NEXT: %11 = load i128, ptr %ui128.addr, align 16
// CHECK-NEXT: %12 = call i128 @llvm.ctpop.i128(i128 %11)
// CHECK-NEXT: %cast3 = trunc i128 %12 to i32
// CHECK-NEXT: store volatile i32 %cast3, ptr %pop, align 4
// CHECK-NEXT: %cast4 = trunc i128 %12 to i32
// CHECK-NEXT: store volatile i32 %cast4, ptr %pop, align 4
pop = __builtin_popcountg(ubi128);
// CHECK-NEXT: %13 = load i128, ptr %ubi128.addr, align 8
// CHECK-NEXT: %14 = call i128 @llvm.ctpop.i128(i128 %13)
// CHECK-NEXT: %cast4 = trunc i128 %14 to i32
// CHECK-NEXT: store volatile i32 %cast4, ptr %pop, align 4
// CHECK-NEXT: %cast5 = trunc i128 %14 to i32
// CHECK-NEXT: store volatile i32 %cast5, ptr %pop, align 4
// CHECK-NEXT: ret void
}

Expand Down
21 changes: 20 additions & 1 deletion clang/test/CodeGen/fat-lto-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.split.bc %t.full.split.o
// RUN: llvm-dis %t.full.split.bc -o - | FileCheck %s --check-prefixes=FULL,SPLIT,NOUNIFIED

/// Full LTO always sets EnableSplitLTOUnit when the summary is used.
// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -emit-obj < %s -o %t.full.nosplit.o
// RUN: llvm-readelf -S %t.full.nosplit.o | FileCheck %s --check-prefixes=ELF
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.nosplit.bc %t.full.nosplit.o
// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=FULL,NOSPLIT,NOUNIFIED
// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=FULL,SPLIT,NOUNIFIED

// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -fsplit-lto-unit -ffat-lto-objects -emit-obj < %s -o %t.thin.split.o
// RUN: llvm-readelf -S %t.thin.split.o | FileCheck %s --check-prefixes=ELF
Expand All @@ -34,6 +35,21 @@
// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \
// RUN: | FileCheck %s --check-prefixes=ASM

/// Make sure that FatLTO generates .llvm.lto sections that are the same as the output from normal LTO compilations
// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=full -ffat-lto-objects -c %s -o %t.fatlto.full.o
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.full.bc %t.fatlto.full.o
// RUN: llvm-dis < %t.fatlto.full.bc -o %t.fatlto.full.ll
// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=full -c %s -o %t.nofat.full.bc
// RUN: llvm-dis < %t.nofat.full.bc -o %t.nofat.full.ll
// RUN: diff %t.fatlto.full.ll %t.nofat.full.ll

// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=thin -ffat-lto-objects -c %s -o %t.fatlto.thin.o
// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.thin.bc %t.fatlto.thin.o
// RUN: llvm-dis < %t.fatlto.thin.bc -o %t.fatlto.thin.ll
// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=thin -c %s -o %t.nofat.thin.bc
// RUN: llvm-dis < %t.nofat.thin.bc -o %t.nofat.thin.ll
// RUN: diff %t.fatlto.thin.ll %t.nofat.thin.ll

/// Be sure we enable split LTO units correctly under -ffat-lto-objects.
// SPLIT: ![[#]] = !{i32 1, !"EnableSplitLTOUnit", i32 1}
// NOSPLIT: ![[#]] = !{i32 1, !"EnableSplitLTOUnit", i32 0}
Expand All @@ -51,6 +67,9 @@
// ASM-NEXT: .asciz "BC
// ASM-NEXT: .size .Lllvm.embedded.object

const char* foo = "foo";

int test(void) {
const char* bar = "bar";
return 0xabcd;
}
2 changes: 1 addition & 1 deletion clang/test/Driver/darwin-header-search-libcxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
// RUN: ln -sf %t/install/bin/clang %t/symlinked1/bin/clang
// RUN: mkdir -p %t/symlinked1/include/c++/v1

// RUN: %t/symlinked1/bin/clang -### %s -fsyntax-only 2>&1 \
// RUN: %t/symlinked1/bin/clang -### %s -no-canonical-prefixes -fsyntax-only 2>&1 \
// RUN: --target=x86_64-apple-darwin \
// RUN: -stdlib=libc++ \
// RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
Expand Down
12 changes: 7 additions & 5 deletions clang/test/Driver/mingw-sysroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,12 @@
// CHECK_TESTROOT_GCC_EXPLICIT: "-internal-isystem" "{{[^"]+}}/testroot-gcc{{/|\\\\}}include"


// If there's a matching sysroot next to the clang binary itself, prefer that
// If -no-canonical-prefixes and there's a matching sysroot next to the clang binary itself, prefer that
// over a gcc in the path:

// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG %s
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC2 %s
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s -no-canonical-prefixes 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG %s
// CHECK_TESTROOT_GCC2: "{{[^"]+}}/testroot-gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
// CHECK_TESTROOT_CLANG: "{{[^"]+}}/testroot-clang{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"


Expand Down Expand Up @@ -82,7 +84,7 @@
// that indicates that we did choose the right base, even if this particular directory
// actually doesn't exist here.

// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -no-canonical-prefixes --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s
// CHECK_TESTROOT_CLANG_NATIVE: "{{[^"]+}}/testroot-clang-native{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"


Expand All @@ -93,12 +95,12 @@
// that defaults to x86_64 mingw, but it's easier to test this in cross setups
// with symlinks, like the other tests here.)

// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -m32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_I686 %s
// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang -no-canonical-prefixes --target=x86_64-w64-mingw32 -m32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_I686 %s
// CHECK_TESTROOT_CLANG_I686: "{{[^"]+}}/testroot-clang{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"


// If the user calls clang with a custom literal triple, make sure this maps
// to sysroots with the matching spelling.

// RUN: %T/testroot-custom-triple/bin/clang --target=x86_64-w64-mingw32foo -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CUSTOM_TRIPLE %s
// RUN: %T/testroot-custom-triple/bin/clang -no-canonical-prefixes --target=x86_64-w64-mingw32foo -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CUSTOM_TRIPLE %s
// CHECK_TESTROOT_CUSTOM_TRIPLE: "{{[^"]+}}/testroot-custom-triple{{/|\\\\}}x86_64-w64-mingw32foo{{/|\\\\}}include"
2 changes: 1 addition & 1 deletion clang/test/Driver/no-canonical-prefixes.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
// RUN: | FileCheck --check-prefix=NON-CANONICAL %s
//
// FIXME: This should really be '.real'.
// CANONICAL: InstalledDir: {{.*}}.fake
// CANONICAL: InstalledDir: {{.*}}bin
// CANONICAL: {{[/|\\]*}}clang{{.*}}" -cc1
//
// NON-CANONICAL: InstalledDir: .{{$}}
Expand Down
13 changes: 8 additions & 5 deletions clang/test/Driver/program-path-priority.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
// RUN: touch %t/notreal-none-elf-gcc && chmod +x %t/notreal-none-elf-gcc
// RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s 2>&1 | \
// RUN: FileCheck --check-prefix=PROG_PATH_NOTREAL_GCC %s
// PROG_PATH_NOTREAL_GCC: notreal-none-elf-gcc"
// PROG_PATH_NOTREAL_GCC: notreal-none-unknown-elf

/// <triple>-gcc on the PATH is found
// RUN: mkdir -p %t/env
Expand All @@ -57,7 +57,7 @@
// RUN: touch %t/gcc && chmod +x %t/gcc
// RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s 2>&1 | \
// RUN: FileCheck --check-prefix=NOTREAL_GCC_PREFERRED %s
// NOTREAL_GCC_PREFERRED: notreal-none-elf-gcc"
// NOTREAL_GCC_PREFERRED: notreal-none-unknown-elf"
// NOTREAL_GCC_PREFERRED-NOT: /gcc"

/// <triple>-gcc on the PATH is preferred to gcc in program path
Expand Down Expand Up @@ -125,6 +125,9 @@
/// Only if there is nothing in the prefix will we search other paths
/// -f in case $DEFAULT_TRIPLE == %target_triple
// RUN: rm -f %t/prefix/$DEFAULT_TRIPLE-gcc %t/prefix/%target_triple-gcc %t/prefix/gcc
// RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s -B %t/prefix 2>&1 | \
// RUN: FileCheck --check-prefix=EMPTY_PREFIX_DIR %s
// EMPTY_PREFIX_DIR: notreal-none-elf-gcc"
// RUN: env "PATH=" %t/clang -### -canonical-prefixes --target=notreal-none-elf %s -B %t/prefix 2>&1 | \
// RUN: FileCheck --check-prefix=EMPTY_PREFIX_DIR1 %s
// EMPTY_PREFIX_DIR1: gcc"
// RUN: env "PATH=" %t/clang -### -no-canonical-prefixes --target=notreal-none-elf %s -B %t/prefix 2>&1 | \
// RUN: FileCheck --check-prefix=EMPTY_PREFIX_DIR2 %s
// EMPTY_PREFIX_DIR2: notreal-none-elf-gcc"
4 changes: 2 additions & 2 deletions clang/test/Driver/rocm-detect.hip
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
// RUN: rm -rf %t/rocm-spack
// RUN: cp -r %S/Inputs/rocm-spack %t
// RUN: ln -fs %clang %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang
// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \
// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -no-canonical-prefixes -v \
// RUN: -resource-dir=%t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/lib/clang \
// RUN: -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 --print-rocm-search-dirs %s 2>&1 \
// RUN: | FileCheck -check-prefixes=SPACK %s
Expand All @@ -111,7 +111,7 @@
// ROCm release. --hip-path and --rocm-device-lib-path can be used to specify them.

// RUN: cp -r %t/rocm-spack/hip-* %t/rocm-spack/hip-4.0.0-abcd
// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \
// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -no-canonical-prefixes -v \
// RUN: -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 \
// RUN: --hip-path=%t/rocm-spack/hip-4.0.0-abcd \
// RUN: %s 2>&1 | FileCheck -check-prefixes=SPACK-SET %s
Expand Down
35 changes: 35 additions & 0 deletions clang/test/OpenMP/interop_codegen.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// expected-no-diagnostics
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s

#ifndef HEADER
#define HEADER

typedef void *omp_interop_t;
#define omp_interop_none 0
#define omp_ipr_fr_id -1
typedef long omp_intptr_t;
#define NULL 0

extern omp_intptr_t omp_get_interop_int(const omp_interop_t, int, int *);

int main() {
omp_interop_t obj = omp_interop_none;
omp_interop_t i1 = omp_interop_none;
omp_interop_t i2 = omp_interop_none;
omp_interop_t i3 = omp_interop_none;
omp_interop_t i4 = omp_interop_none;
omp_interop_t i5 = omp_interop_none;

#pragma omp interop init(targetsync: i1) init(targetsync: obj)
int id = (int )omp_get_interop_int(obj, omp_ipr_fr_id, NULL);
int id1 = (int )omp_get_interop_int(i1, omp_ipr_fr_id, NULL);


}
#endif

// CHECK-LABEL: define {{.+}}main{{.+}}
// CHECK: call {{.+}}__tgt_interop_init({{.+}}i1{{.*}})
// CHECK: call {{.+}}__tgt_interop_init({{.+}}obj{{.*}})
18 changes: 18 additions & 0 deletions clang/test/OpenMP/scan_ast_print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ T tmain(T argc) {
static T a;
#pragma omp for reduction(inscan, +: a)
for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(a)
}
#pragma omp parallel for reduction(inscan, +:a)
for (int i = 0; i < 10; ++i) {
#pragma omp scan inclusive(a)
}
return a + argc;
Expand All @@ -25,15 +29,29 @@ T tmain(T argc) {
// CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a){{$}}

// CHECK: #pragma omp parallel for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a){{$}}

// CHECK: static int a;
// CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a)

// CHECK: #pragma omp parallel for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a)

// CHECK: static char a;
// CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a)

// CHECK: #pragma omp parallel for reduction(inscan, +: a)
// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
// CHECK-NEXT: #pragma omp scan inclusive(a)

int main(int argc, char **argv) {
static int a;
// CHECK: static int a;
Expand Down
18 changes: 9 additions & 9 deletions clang/test/Preprocessor/riscv-target-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
// CHECK-NOT: __riscv_xventanacondops {{.*$}}
// CHECK-NOT: __riscv_za128rs {{.*$}}
// CHECK-NOT: __riscv_za64rs {{.*$}}
// CHECK-NOT: __riscv_zacas {{.*$}}
// CHECK-NOT: __riscv_zawrs {{.*$}}
// CHECK-NOT: __riscv_zba {{.*$}}
// CHECK-NOT: __riscv_zbb {{.*$}}
Expand Down Expand Up @@ -166,7 +167,6 @@
// CHECK-NOT: __riscv_ssqosid{{.*$}}
// CHECK-NOT: __riscv_supm{{.*$}}
// CHECK-NOT: __riscv_zaamo {{.*$}}
// CHECK-NOT: __riscv_zacas {{.*$}}
// CHECK-NOT: __riscv_zalasr {{.*$}}
// CHECK-NOT: __riscv_zalrsc {{.*$}}
// CHECK-NOT: __riscv_zcmop {{.*$}}
Expand Down Expand Up @@ -660,6 +660,14 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-ZA64RS-EXT %s
// CHECK-ZA64RS-EXT: __riscv_za64rs 1000000{{$}}

// RUN: %clang --target=riscv32 \
// RUN: -march=rv32i_zacas1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
// RUN: %clang --target=riscv64 \
// RUN: -march=rv64i_zacas1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}

// RUN: %clang --target=riscv32-unknown-linux-gnu \
// RUN: -march=rv32izawrs -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZAWRS-EXT %s
Expand Down Expand Up @@ -1485,14 +1493,6 @@
// RUN: -o - | FileCheck --check-prefix=CHECK-ZAAMO-EXT %s
// CHECK-ZAAMO-EXT: __riscv_zaamo 2000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zacas1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
// RUN: %clang --target=riscv64 -menable-experimental-extensions \
// RUN: -march=rv64i_zacas1p0 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}

// RUN: %clang --target=riscv32 -menable-experimental-extensions \
// RUN: -march=rv32i_zalasr0p1 -E -dM %s \
// RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
Expand Down
17 changes: 13 additions & 4 deletions clang/test/Sema/builtin-popcountg.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s
// RUN: %clang_cc1 -std=c23 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s

typedef int int2 __attribute__((ext_vector_type(2)));

void test_builtin_popcountg(int i, double d, int2 i2) {
void test_builtin_popcountg(short s, int i, __int128 i128, _BitInt(128) bi128,
double d, int2 i2) {
__builtin_popcountg();
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
__builtin_popcountg(i, i);
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
__builtin_popcountg(s);
// expected-error@-1 {{1st argument must be a type of unsigned integer (was 'short')}}
__builtin_popcountg(i);
// expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int')}}
__builtin_popcountg(i128);
// expected-error@-1 {{1st argument must be a type of unsigned integer (was '__int128')}}
__builtin_popcountg(bi128);
// expected-error@-1 {{1st argument must be a type of unsigned integer (was '_BitInt(128)')}}
__builtin_popcountg(d);
// expected-error@-1 {{1st argument must be a type of integer (was 'double')}}
// expected-error@-1 {{1st argument must be a type of unsigned integer (was 'double')}}
__builtin_popcountg(i2);
// expected-error@-1 {{1st argument must be a type of integer (was 'int2' (vector of 2 'int' values))}}
// expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int2' (vector of 2 'int' values))}}
}
12 changes: 12 additions & 0 deletions clang/test/SemaCXX/warn-bool-conversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ struct S2 {

bool f5();
bool f6(int);
#if __cplusplus >= 201103L
auto f7 = []{};
auto f8 = [](){};

void foo() {
bool b;
b = f7; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
b = f8; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
bool is_true = [](){ return true; };
// expected-warning@-1{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
}
#endif

void bar() {
bool b;
Expand Down
197 changes: 197 additions & 0 deletions clang/test/SemaOpenACC/no-branch-in-out.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,200 @@ void Return() {
}
}
}

void Goto() {
int j;
#pragma acc parallel // expected-note{{invalid branch out of OpenACC Compute Construct}}
while(j) {
if (j <3)
goto LABEL; // expected-error{{cannot jump from this goto statement to its label}}
}

LABEL:
{}

goto LABEL_IN; // expected-error{{cannot jump from this goto statement to its label}}

#pragma acc parallel // expected-note{{invalid branch into OpenACC Compute Construct}}
for(int i = 0; i < 5; ++i) {
LABEL_IN:
{}
}

#pragma acc parallel
for(int i = 0; i < 5; ++i) {
LABEL_NOT_CALLED:
{}
}

#pragma acc parallel
{
goto ANOTHER_LOOP; // expected-error{{cannot jump from this goto statement to its label}}

}
#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}

{
ANOTHER_LOOP:
{}
}

#pragma acc parallel
{
while (j) {
--j;
if (j < 3)
goto LABEL2;

if (j > 4)
break;
}
LABEL2:
{}
}

#pragma acc parallel
do {
if (j < 3)
goto LABEL3;

if (j > 4)
break; // expected-error{{invalid branch out of OpenACC Compute Construct}}

LABEL3:
{}
} while (j);

LABEL4:
{}
#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
{
goto LABEL4;// expected-error{{cannot jump from this goto statement to its label}}
}

#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}

{
LABEL5:
{}
}

{
goto LABEL5;// expected-error{{cannot jump from this goto statement to its label}}
}

#pragma acc parallel
{
LABEL6:
{}
goto LABEL6;

}

#pragma acc parallel
goto LABEL7; // expected-error{{cannot jump from this goto statement to its label}}
#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
{
LABEL7:{}
}

#pragma acc parallel
LABEL8:{}
#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
{
goto LABEL8;// expected-error{{cannot jump from this goto statement to its label}}
}


#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
{
LABEL9:{}
}

({goto LABEL9;});// expected-error{{cannot jump from this goto statement to its label}}

#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
{
({goto LABEL10;});// expected-error{{cannot jump from this goto statement to its label}}
}

LABEL10:{}

({goto LABEL11;});// expected-error{{cannot jump from this goto statement to its label}}
#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
{
LABEL11:{}
}

LABEL12:{}
#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
{
({goto LABEL12;});// expected-error{{cannot jump from this goto statement to its label}}
}

#pragma acc parallel
{
({goto LABEL13;});
LABEL13:{}
}

#pragma acc parallel
{
LABEL14:{}
({goto LABEL14;});
}
}

void IndirectGoto1() {
void* ptr;
#pragma acc parallel
{
LABEL1:{}
ptr = &&LABEL1;

goto *ptr;

}
}

void IndirectGoto2() {
void* ptr;
LABEL2:{} // #GOTOLBL2
ptr = &&LABEL2;
#pragma acc parallel // #GOTOPAR2
{
// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
// expected-note@#GOTOLBL2{{possible target of indirect goto statement}}
// expected-note@#GOTOPAR2{{invalid branch out of OpenACC Compute Construct}}
goto *ptr;
}
}

void IndirectGoto3() {
void* ptr;
#pragma acc parallel // #GOTOPAR3
{
LABEL3:{} // #GOTOLBL3
ptr = &&LABEL3;
}
// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
// expected-note@#GOTOLBL3{{possible target of indirect goto statement}}
// expected-note@#GOTOPAR3{{invalid branch into OpenACC Compute Construct}}
goto *ptr;
}

void IndirectGoto4() {
void* ptr;
#pragma acc parallel // #GOTOPAR4
{
LABEL4:{}
ptr = &&LABEL4;
// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
// expected-note@#GOTOLBL5{{possible target of indirect goto statement}}
// expected-note@#GOTOPAR4{{invalid branch out of OpenACC Compute Construct}}
goto *ptr;
}
LABEL5:// #GOTOLBL5

ptr=&&LABEL5;
}
1 change: 0 additions & 1 deletion clang/tools/clang-installapi/ClangInstallAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) {
auto DriverArgs = llvm::ArrayRef(Args).slice(1);
clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(),
*Diag, "clang installapi tool");
Driver.setInstalledDir(llvm::sys::path::parent_path(ProgName));
auto TargetAndMode =
clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName);
Driver.setTargetAndMode(TargetAndMode);
Expand Down
23 changes: 0 additions & 23 deletions clang/tools/driver/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,28 +323,6 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
DiagClient->setPrefix(std::string(ExeBasename));
}

static void SetInstallDir(SmallVectorImpl<const char *> &argv,
Driver &TheDriver, bool CanonicalPrefixes) {
// Attempt to find the original path used to invoke the driver, to determine
// the installed path. We do this manually, because we want to support that
// path being a symlink.
SmallString<128> InstalledPath(argv[0]);

// Do a PATH lookup, if there are no directory components.
if (llvm::sys::path::filename(InstalledPath) == InstalledPath)
if (llvm::ErrorOr<std::string> Tmp = llvm::sys::findProgramByName(
llvm::sys::path::filename(InstalledPath.str())))
InstalledPath = *Tmp;

// FIXME: We don't actually canonicalize this, we just make it absolute.
if (CanonicalPrefixes)
llvm::sys::fs::make_absolute(InstalledPath);

StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath));
if (llvm::sys::fs::exists(InstalledPathParent))
TheDriver.setInstalledDir(InstalledPathParent);
}

static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV,
const llvm::ToolContext &ToolContext) {
// If we call the cc1 tool from the clangDriver library (through
Expand Down Expand Up @@ -484,7 +462,6 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);

Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
SetInstallDir(Args, TheDriver, CanonicalPrefixes);
auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName);
TheDriver.setTargetAndMode(TargetAndMode);
// If -canonical-prefixes is set, GetExecutablePath will have resolved Path
Expand Down
7 changes: 7 additions & 0 deletions compiler-rt/lib/scudo/standalone/allocator_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ template <class SizeClassAllocator> struct TransferBatch {
B->Count = static_cast<u16>(B->Count - N);
}
void clear() { Count = 0; }
bool empty() { return Count == 0; }
void add(CompactPtrT P) {
DCHECK_LT(Count, MaxNumCached);
Batch[Count++] = P;
Expand All @@ -48,6 +49,12 @@ template <class SizeClassAllocator> struct TransferBatch {
memcpy(Array, Batch, sizeof(Batch[0]) * Count);
clear();
}

void moveNToArray(CompactPtrT *Array, u16 N) {
DCHECK_LE(N, Count);
memcpy(Array, Batch + Count - N, sizeof(Batch[0]) * N);
Count = static_cast<u16>(Count - N);
}
u16 getCount() const { return Count; }
bool isEmpty() const { return Count == 0U; }
CompactPtrT get(u16 I) const {
Expand Down
106 changes: 55 additions & 51 deletions compiler-rt/lib/scudo/standalone/primary32.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,38 +191,21 @@ template <typename Config> class SizeClassAllocator32 {
return BlockSize > PageSize;
}

// Note that the `MaxBlockCount` will be used when we support arbitrary blocks
// count. Now it's the same as the number of blocks stored in the
// `TransferBatch`.
u16 popBlocks(CacheT *C, uptr ClassId, CompactPtrT *ToArray,
UNUSED const u16 MaxBlockCount) {
TransferBatchT *B = popBatch(C, ClassId);
if (!B)
return 0;

const u16 Count = B->getCount();
DCHECK_GT(Count, 0U);
B->moveToArray(ToArray);

if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, B);

return Count;
}

TransferBatchT *popBatch(CacheT *C, uptr ClassId) {
const u16 MaxBlockCount) {
DCHECK_LT(ClassId, NumClasses);
SizeClassInfo *Sci = getSizeClassInfo(ClassId);
ScopedLock L(Sci->Mutex);
TransferBatchT *B = popBatchImpl(C, ClassId, Sci);
if (UNLIKELY(!B)) {

u16 PopCount = popBlocksImpl(C, ClassId, Sci, ToArray, MaxBlockCount);
if (UNLIKELY(PopCount == 0)) {
if (UNLIKELY(!populateFreeList(C, ClassId, Sci)))
return nullptr;
B = popBatchImpl(C, ClassId, Sci);
// if `populateFreeList` succeeded, we are supposed to get free blocks.
DCHECK_NE(B, nullptr);
return 0U;
PopCount = popBlocksImpl(C, ClassId, Sci, ToArray, MaxBlockCount);
DCHECK_NE(PopCount, 0U);
}
return B;

return PopCount;
}

// Push the array of free blocks to the designated batch group.
Expand Down Expand Up @@ -510,7 +493,7 @@ template <typename Config> class SizeClassAllocator32 {
// by TransferBatch is also free for use. We don't need to recycle the
// TransferBatch. Note that the correctness is maintained by the invariant,
//
// The unit of each popBatch() request is entire TransferBatch. Return
// Each popBlocks() request returns the entire TransferBatch. Returning
// part of the blocks in a TransferBatch is invalid.
//
// This ensures that TransferBatch won't leak the address itself while it's
Expand Down Expand Up @@ -634,7 +617,7 @@ template <typename Config> class SizeClassAllocator32 {
BG->Batches.push_front(TB);
BG->PushedBlocks = 0;
BG->BytesInBGAtLastCheckpoint = 0;
BG->MaxCachedPerBatch = CacheT::getMaxCached(getSizeByClassId(ClassId));
BG->MaxCachedPerBatch = TransferBatchT::MaxNumCached;

return BG;
};
Expand Down Expand Up @@ -726,14 +709,11 @@ template <typename Config> class SizeClassAllocator32 {
InsertBlocks(Cur, Array + Size - Count, Count);
}

// Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest
// group id will be considered first.
//
// The region mutex needs to be held while calling this method.
TransferBatchT *popBatchImpl(CacheT *C, uptr ClassId, SizeClassInfo *Sci)
u16 popBlocksImpl(CacheT *C, uptr ClassId, SizeClassInfo *Sci,
CompactPtrT *ToArray, const u16 MaxBlockCount)
REQUIRES(Sci->Mutex) {
if (Sci->FreeListInfo.BlockList.empty())
return nullptr;
return 0U;

SinglyLinkedList<TransferBatchT> &Batches =
Sci->FreeListInfo.BlockList.front()->Batches;
Expand All @@ -746,33 +726,57 @@ template <typename Config> class SizeClassAllocator32 {
// Block used by `BatchGroup` is from BatchClassId. Turn the block into
// `TransferBatch` with single block.
TransferBatchT *TB = reinterpret_cast<TransferBatchT *>(BG);
TB->clear();
TB->add(
compactPtr(SizeClassMap::BatchClassId, reinterpret_cast<uptr>(TB)));
ToArray[0] =
compactPtr(SizeClassMap::BatchClassId, reinterpret_cast<uptr>(TB));
Sci->FreeListInfo.PoppedBlocks += 1;
return TB;
return 1U;
}

// So far, instead of always filling the blocks to `MaxBlockCount`, we only
// examine single `TransferBatch` to minimize the time spent on the primary
// allocator. Besides, the sizes of `TransferBatch` and
// `CacheT::getMaxCached()` may also impact the time spent on accessing the
// primary allocator.
// TODO(chiahungduan): Evaluate if we want to always prepare `MaxBlockCount`
// blocks and/or adjust the size of `TransferBatch` according to
// `CacheT::getMaxCached()`.
TransferBatchT *B = Batches.front();
Batches.pop_front();
DCHECK_NE(B, nullptr);
DCHECK_GT(B->getCount(), 0U);

if (Batches.empty()) {
BatchGroupT *BG = Sci->FreeListInfo.BlockList.front();
Sci->FreeListInfo.BlockList.pop_front();

// We don't keep BatchGroup with zero blocks to avoid empty-checking while
// allocating. Note that block used by constructing BatchGroup is recorded
// as free blocks in the last element of BatchGroup::Batches. Which means,
// once we pop the last TransferBatch, the block is implicitly
// deallocated.
// BachClassId should always take all blocks in the TransferBatch. Read the
// comment in `pushBatchClassBlocks()` for more details.
const u16 PopCount = ClassId == SizeClassMap::BatchClassId
? B->getCount()
: Min(MaxBlockCount, B->getCount());
B->moveNToArray(ToArray, PopCount);

// TODO(chiahungduan): The deallocation of unused BatchClassId blocks can be
// done without holding `Mutex`.
if (B->empty()) {
Batches.pop_front();
// `TransferBatch` of BatchClassId is self-contained, no need to
// deallocate. Read the comment in `pushBatchClassBlocks()` for more
// details.
if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, BG);
C->deallocate(SizeClassMap::BatchClassId, B);

if (Batches.empty()) {
BatchGroupT *BG = Sci->FreeListInfo.BlockList.front();
Sci->FreeListInfo.BlockList.pop_front();

// We don't keep BatchGroup with zero blocks to avoid empty-checking
// while allocating. Note that block used for constructing BatchGroup is
// recorded as free blocks in the last element of BatchGroup::Batches.
// Which means, once we pop the last TransferBatch, the block is
// implicitly deallocated.
if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, BG);
}
}

Sci->FreeListInfo.PoppedBlocks += B->getCount();
return B;
Sci->FreeListInfo.PoppedBlocks += PopCount;
return PopCount;
}

NOINLINE bool populateFreeList(CacheT *C, uptr ClassId, SizeClassInfo *Sci)
Expand Down
153 changes: 82 additions & 71 deletions compiler-rt/lib/scudo/standalone/primary64.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "allocator_common.h"
#include "bytemap.h"
#include "common.h"
#include "condition_variable.h"
#include "list.h"
#include "local_cache.h"
#include "mem_map.h"
Expand All @@ -22,8 +23,6 @@
#include "string_utils.h"
#include "thread_annotations.h"

#include "condition_variable.h"

namespace scudo {

// SizeClassAllocator64 is an allocator tuned for 64-bit address space.
Expand Down Expand Up @@ -221,41 +220,24 @@ template <typename Config> class SizeClassAllocator64 {
DCHECK_EQ(BlocksInUse, BatchClassUsedInFreeLists);
}

// Note that the `MaxBlockCount` will be used when we support arbitrary blocks
// count. Now it's the same as the number of blocks stored in the
// `TransferBatch`.
u16 popBlocks(CacheT *C, uptr ClassId, CompactPtrT *ToArray,
UNUSED const u16 MaxBlockCount) {
TransferBatchT *B = popBatch(C, ClassId);
if (!B)
return 0;

const u16 Count = B->getCount();
DCHECK_GT(Count, 0U);
B->moveToArray(ToArray);

if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, B);

return Count;
}

TransferBatchT *popBatch(CacheT *C, uptr ClassId) {
const u16 MaxBlockCount) {
DCHECK_LT(ClassId, NumClasses);
RegionInfo *Region = getRegionInfo(ClassId);
u16 PopCount = 0;

{
ScopedLock L(Region->FLLock);
TransferBatchT *B = popBatchImpl(C, ClassId, Region);
if (LIKELY(B))
return B;
PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount);
if (PopCount != 0U)
return PopCount;
}

bool ReportRegionExhausted = false;
TransferBatchT *B = nullptr;

if (conditionVariableEnabled()) {
B = popBatchWithCV(C, ClassId, Region, ReportRegionExhausted);
PopCount = popBlocksWithCV(C, ClassId, Region, ToArray, MaxBlockCount,
ReportRegionExhausted);
} else {
while (true) {
// When two threads compete for `Region->MMLock`, we only want one of
Expand All @@ -264,13 +246,15 @@ template <typename Config> class SizeClassAllocator64 {
ScopedLock ML(Region->MMLock);
{
ScopedLock FL(Region->FLLock);
if ((B = popBatchImpl(C, ClassId, Region)))
break;
PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount);
if (PopCount != 0U)
return PopCount;
}

const bool RegionIsExhausted = Region->Exhausted;
if (!RegionIsExhausted)
B = populateFreeListAndPopBatch(C, ClassId, Region);
PopCount = populateFreeListAndPopBlocks(C, ClassId, Region, ToArray,
MaxBlockCount);
ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted;
break;
}
Expand All @@ -286,7 +270,7 @@ template <typename Config> class SizeClassAllocator64 {
reportOutOfBatchClass();
}

return B;
return PopCount;
}

// Push the array of free blocks to the designated batch group.
Expand Down Expand Up @@ -640,7 +624,7 @@ template <typename Config> class SizeClassAllocator64 {
// by TransferBatch is also free for use. We don't need to recycle the
// TransferBatch. Note that the correctness is maintained by the invariant,
//
// The unit of each popBatch() request is entire TransferBatch. Return
// Each popBlocks() request returns the entire TransferBatch. Returning
// part of the blocks in a TransferBatch is invalid.
//
// This ensures that TransferBatch won't leak the address itself while it's
Expand Down Expand Up @@ -763,7 +747,7 @@ template <typename Config> class SizeClassAllocator64 {
BG->Batches.push_front(TB);
BG->PushedBlocks = 0;
BG->BytesInBGAtLastCheckpoint = 0;
BG->MaxCachedPerBatch = CacheT::getMaxCached(getSizeByClassId(ClassId));
BG->MaxCachedPerBatch = TransferBatchT::MaxNumCached;

return BG;
};
Expand Down Expand Up @@ -855,9 +839,10 @@ template <typename Config> class SizeClassAllocator64 {
InsertBlocks(Cur, Array + Size - Count, Count);
}

TransferBatchT *popBatchWithCV(CacheT *C, uptr ClassId, RegionInfo *Region,
bool &ReportRegionExhausted) {
TransferBatchT *B = nullptr;
u16 popBlocksWithCV(CacheT *C, uptr ClassId, RegionInfo *Region,
CompactPtrT *ToArray, const u16 MaxBlockCount,
bool &ReportRegionExhausted) {
u16 PopCount = 0;

while (true) {
// We only expect one thread doing the freelist refillment and other
Expand All @@ -878,7 +863,8 @@ template <typename Config> class SizeClassAllocator64 {

const bool RegionIsExhausted = Region->Exhausted;
if (!RegionIsExhausted)
B = populateFreeListAndPopBatch(C, ClassId, Region);
PopCount = populateFreeListAndPopBlocks(C, ClassId, Region, ToArray,
MaxBlockCount);
ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted;

{
Expand All @@ -905,7 +891,8 @@ template <typename Config> class SizeClassAllocator64 {
// blocks were used up right after the refillment. Therefore, we have to
// check if someone is still populating the freelist.
ScopedLock FL(Region->FLLock);
if (LIKELY(B = popBatchImpl(C, ClassId, Region)))
PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount);
if (PopCount != 0U)
break;

if (!Region->isPopulatingFreeList)
Expand All @@ -918,21 +905,19 @@ template <typename Config> class SizeClassAllocator64 {
// `pushBatchClassBlocks()` and `mergeGroupsToReleaseBack()`.
Region->FLLockCV.wait(Region->FLLock);

if (LIKELY(B = popBatchImpl(C, ClassId, Region)))
PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount);
if (PopCount != 0U)
break;
}

return B;
return PopCount;
}

// Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest
// group id will be considered first.
//
// The region mutex needs to be held while calling this method.
TransferBatchT *popBatchImpl(CacheT *C, uptr ClassId, RegionInfo *Region)
u16 popBlocksImpl(CacheT *C, uptr ClassId, RegionInfo *Region,
CompactPtrT *ToArray, const u16 MaxBlockCount)
REQUIRES(Region->FLLock) {
if (Region->FreeListInfo.BlockList.empty())
return nullptr;
return 0U;

SinglyLinkedList<TransferBatchT> &Batches =
Region->FreeListInfo.BlockList.front()->Batches;
Expand All @@ -945,39 +930,64 @@ template <typename Config> class SizeClassAllocator64 {
// Block used by `BatchGroup` is from BatchClassId. Turn the block into
// `TransferBatch` with single block.
TransferBatchT *TB = reinterpret_cast<TransferBatchT *>(BG);
TB->clear();
TB->add(
compactPtr(SizeClassMap::BatchClassId, reinterpret_cast<uptr>(TB)));
ToArray[0] =
compactPtr(SizeClassMap::BatchClassId, reinterpret_cast<uptr>(TB));
Region->FreeListInfo.PoppedBlocks += 1;
return TB;
return 1U;
}

// So far, instead of always filling blocks to `MaxBlockCount`, we only
// examine single `TransferBatch` to minimize the time spent in the primary
// allocator. Besides, the sizes of `TransferBatch` and
// `CacheT::getMaxCached()` may also impact the time spent on accessing the
// primary allocator.
// TODO(chiahungduan): Evaluate if we want to always prepare `MaxBlockCount`
// blocks and/or adjust the size of `TransferBatch` according to
// `CacheT::getMaxCached()`.
TransferBatchT *B = Batches.front();
Batches.pop_front();
DCHECK_NE(B, nullptr);
DCHECK_GT(B->getCount(), 0U);

if (Batches.empty()) {
BatchGroupT *BG = Region->FreeListInfo.BlockList.front();
Region->FreeListInfo.BlockList.pop_front();

// We don't keep BatchGroup with zero blocks to avoid empty-checking while
// allocating. Note that block used by constructing BatchGroup is recorded
// as free blocks in the last element of BatchGroup::Batches. Which means,
// once we pop the last TransferBatch, the block is implicitly
// deallocated.
// BachClassId should always take all blocks in the TransferBatch. Read the
// comment in `pushBatchClassBlocks()` for more details.
const u16 PopCount = ClassId == SizeClassMap::BatchClassId
? B->getCount()
: Min(MaxBlockCount, B->getCount());
B->moveNToArray(ToArray, PopCount);

// TODO(chiahungduan): The deallocation of unused BatchClassId blocks can be
// done without holding `FLLock`.
if (B->empty()) {
Batches.pop_front();
// `TransferBatch` of BatchClassId is self-contained, no need to
// deallocate. Read the comment in `pushBatchClassBlocks()` for more
// details.
if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, BG);
C->deallocate(SizeClassMap::BatchClassId, B);

if (Batches.empty()) {
BatchGroupT *BG = Region->FreeListInfo.BlockList.front();
Region->FreeListInfo.BlockList.pop_front();

// We don't keep BatchGroup with zero blocks to avoid empty-checking
// while allocating. Note that block used for constructing BatchGroup is
// recorded as free blocks in the last element of BatchGroup::Batches.
// Which means, once we pop the last TransferBatch, the block is
// implicitly deallocated.
if (ClassId != SizeClassMap::BatchClassId)
C->deallocate(SizeClassMap::BatchClassId, BG);
}
}

Region->FreeListInfo.PoppedBlocks += B->getCount();
Region->FreeListInfo.PoppedBlocks += PopCount;

return B;
return PopCount;
}

// Refill the freelist and return one batch.
NOINLINE TransferBatchT *populateFreeListAndPopBatch(CacheT *C, uptr ClassId,
RegionInfo *Region)
NOINLINE u16 populateFreeListAndPopBlocks(CacheT *C, uptr ClassId,
RegionInfo *Region,
CompactPtrT *ToArray,
const u16 MaxBlockCount)
REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) {
const uptr Size = getSizeByClassId(ClassId);
const u16 MaxCount = CacheT::getMaxCached(Size);
Expand All @@ -994,15 +1004,15 @@ template <typename Config> class SizeClassAllocator64 {
const uptr RegionBase = RegionBeg - getRegionBaseByClassId(ClassId);
if (UNLIKELY(RegionBase + MappedUser + MapSize > RegionSize)) {
Region->Exhausted = true;
return nullptr;
return 0U;
}

if (UNLIKELY(!Region->MemMapInfo.MemMap.remap(
RegionBeg + MappedUser, MapSize, "scudo:primary",
MAP_ALLOWNOMEM | MAP_RESIZABLE |
(useMemoryTagging<Config>(Options.load()) ? MAP_MEMTAG
: 0)))) {
return nullptr;
return 0U;
}
Region->MemMapInfo.MappedUser += MapSize;
C->getStats().add(StatMapped, MapSize);
Expand Down Expand Up @@ -1049,8 +1059,9 @@ template <typename Config> class SizeClassAllocator64 {
pushBatchClassBlocks(Region, ShuffleArray, NumberOfBlocks);
}

TransferBatchT *B = popBatchImpl(C, ClassId, Region);
DCHECK_NE(B, nullptr);
const u16 PopCount =
popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount);
DCHECK_NE(PopCount, 0U);

// Note that `PushedBlocks` and `PoppedBlocks` are supposed to only record
// the requests from `PushBlocks` and `PopBatch` which are external
Expand All @@ -1062,7 +1073,7 @@ template <typename Config> class SizeClassAllocator64 {
C->getStats().add(StatFree, AllocatedUser);
Region->MemMapInfo.AllocatedUser += AllocatedUser;

return B;
return PopCount;
}

void getStats(ScopedString *Str, uptr ClassId, RegionInfo *Region)
Expand Down Expand Up @@ -1186,7 +1197,7 @@ template <typename Config> class SizeClassAllocator64 {
}

// Note that we have extracted the `GroupsToRelease` from region freelist.
// It's safe to let pushBlocks()/popBatches() access the remaining region
// It's safe to let pushBlocks()/popBlocks() access the remaining region
// freelist. In the steps 3 and 4, we will temporarily release the FLLock
// and lock it again before step 5.

Expand Down
34 changes: 15 additions & 19 deletions compiler-rt/lib/scudo/standalone/tests/primary_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,37 +237,33 @@ struct SmallRegionsConfig {
// For the 32-bit one, it requires actually exhausting memory, so we skip it.
TEST(ScudoPrimaryTest, Primary64OOM) {
using Primary = scudo::SizeClassAllocator64<SmallRegionsConfig>;
using TransferBatch = Primary::TransferBatchT;
Primary Allocator;
Allocator.init(/*ReleaseToOsInterval=*/-1);
typename Primary::CacheT Cache;
scudo::GlobalStats Stats;
Stats.init();
Cache.init(&Stats, &Allocator);
bool AllocationFailed = false;
std::vector<TransferBatch *> Batches;
std::vector<void *> Blocks;
const scudo::uptr ClassId = Primary::SizeClassMap::LargestClassId;
const scudo::uptr Size = Primary::getSizeByClassId(ClassId);
typename Primary::CacheT::CompactPtrT Blocks[TransferBatch::MaxNumCached];
const scudo::u16 MaxCachedBlockCount = Primary::CacheT::getMaxCached(Size);

for (scudo::uptr I = 0; I < 10000U; I++) {
TransferBatch *B = Allocator.popBatch(&Cache, ClassId);
if (!B) {
AllocationFailed = true;
break;
for (scudo::uptr J = 0; J < MaxCachedBlockCount; ++J) {
void *Ptr = Cache.allocate(ClassId);
if (Ptr == nullptr) {
AllocationFailed = true;
break;
}
memset(Ptr, 'B', Size);
Blocks.push_back(Ptr);
}
for (scudo::u16 J = 0; J < B->getCount(); J++)
memset(Allocator.decompactPtr(ClassId, B->get(J)), 'B', Size);
Batches.push_back(B);
}
while (!Batches.empty()) {
TransferBatch *B = Batches.back();
Batches.pop_back();
const scudo::u16 Count = B->getCount();
B->moveToArray(Blocks);
Allocator.pushBlocks(&Cache, ClassId, Blocks, Count);
Cache.deallocate(Primary::SizeClassMap::BatchClassId, B);
}

for (auto *Ptr : Blocks)
Cache.deallocate(ClassId, Ptr);

Cache.destroy(nullptr);
Allocator.releaseToOS(scudo::ReleaseToOS::Force);
scudo::ScopedString Str;
Expand Down Expand Up @@ -342,7 +338,7 @@ SCUDO_TYPED_TEST(ScudoPrimaryTest, PrimaryThreaded) {
V.push_back(std::make_pair(ClassId, P));
}

// Try to interleave pushBlocks(), popBatch() and releaseToOS().
// Try to interleave pushBlocks(), popBlocks() and releaseToOS().
Allocator->releaseToOS(scudo::ReleaseToOS::Force);

while (!V.empty()) {
Expand Down
4 changes: 2 additions & 2 deletions flang/include/flang/Lower/LoweringOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ LOWERINGOPT(Name, Bits, Default)
/// If true, lower transpose without a runtime call.
ENUM_LOWERINGOPT(OptimizeTranspose, unsigned, 1, 1)

/// If true, enable polymorphic type lowering feature. Off by default.
ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 0)
/// If true, enable polymorphic type lowering feature. On by default.
ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 1)

/// If true, lower to High level FIR before lowering to FIR. On by default.
ENUM_LOWERINGOPT(LowerToHighLevelFIR, unsigned, 1, 1)
Expand Down
5 changes: 4 additions & 1 deletion flang/include/flang/Runtime/reduction.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,12 @@ double RTDECL(Norm2_8)(
#if LDBL_MANT_DIG == 64
long double RTDECL(Norm2_10)(
const Descriptor &, const char *source, int line, int dim = 0);
#elif LDBL_MANT_DIG == 113
#endif
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
long double RTDECL(Norm2_16)(
const Descriptor &, const char *source, int line, int dim = 0);
void RTDECL(Norm2DimReal16)(
Descriptor &, const Descriptor &, int dim, const char *source, int line);
#endif
void RTDECL(Norm2Dim)(
Descriptor &, const Descriptor &, int dim, const char *source, int line);
Expand Down
25 changes: 24 additions & 1 deletion flang/lib/Optimizer/Builder/Runtime/Reduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,22 @@ struct ForcedNorm2Real16 {
}
};

/// Placeholder for real*16 version of Norm2Dim Intrinsic
struct ForcedNorm2DimReal16 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Norm2DimReal16));
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto boxTy =
fir::runtime::getModel<const Fortran::runtime::Descriptor &>()(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(
ctx, {fir::ReferenceType::get(boxTy), boxTy, intTy, strTy, intTy},
mlir::NoneType::get(ctx));
};
}
};

/// Placeholder for real*10 version of Product Intrinsic
struct ForcedProductReal10 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal10));
Expand Down Expand Up @@ -876,7 +892,14 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder,
void fir::runtime::genNorm2Dim(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox,
mlir::Value dim) {
auto func = fir::runtime::getRuntimeFunc<mkRTKey(Norm2Dim)>(loc, builder);
mlir::func::FuncOp func;
auto ty = arrayBox.getType();
auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty);
auto eleTy = arrTy.cast<fir::SequenceType>().getEleTy();
if (eleTy.isF128())
func = fir::runtime::getRuntimeFunc<ForcedNorm2DimReal16>(loc, builder);
else
func = fir::runtime::getRuntimeFunc<mkRTKey(Norm2Dim)>(loc, builder);
auto fTy = func.getFunctionType();
auto sourceFile = fir::factory::locationToFilename(builder, loc);
auto sourceLine =
Expand Down
1 change: 1 addition & 0 deletions flang/runtime/Float128Math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ set(sources
log.cpp
log10.cpp
lround.cpp
norm2.cpp
pow.cpp
round.cpp
sin.cpp
Expand Down
16 changes: 16 additions & 0 deletions flang/runtime/Float128Math/math-entries.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ namespace Fortran::runtime {
};

// Define fallback callers.
DEFINE_FALLBACK(Abs)
DEFINE_FALLBACK(Acos)
DEFINE_FALLBACK(Acosh)
DEFINE_FALLBACK(Asin)
Expand Down Expand Up @@ -99,6 +100,7 @@ DEFINE_FALLBACK(Yn)
// Use STD math functions. They provide IEEE-754 128-bit float
// support either via 'long double' or __float128.
// The Bessel's functions are not present in STD namespace.
DEFINE_SIMPLE_ALIAS(Abs, std::abs)
DEFINE_SIMPLE_ALIAS(Acos, std::acos)
DEFINE_SIMPLE_ALIAS(Acosh, std::acosh)
DEFINE_SIMPLE_ALIAS(Asin, std::asin)
Expand Down Expand Up @@ -155,6 +157,7 @@ DEFINE_SIMPLE_ALIAS(Yn, ynl)
#elif HAS_QUADMATHLIB
// Define wrapper callers for libquadmath.
#include "quadmath.h"
DEFINE_SIMPLE_ALIAS(Abs, fabsq)
DEFINE_SIMPLE_ALIAS(Acos, acosq)
DEFINE_SIMPLE_ALIAS(Acosh, acoshq)
DEFINE_SIMPLE_ALIAS(Asin, asinq)
Expand Down Expand Up @@ -191,6 +194,19 @@ DEFINE_SIMPLE_ALIAS(Y0, y0q)
DEFINE_SIMPLE_ALIAS(Y1, y1q)
DEFINE_SIMPLE_ALIAS(Yn, ynq)
#endif

extern "C" {
// Declarations of the entry points that might be referenced
// within the Float128Math library itself.
// Note that not all of these entry points are actually
// defined in this library. Some of them are used just
// as template parameters to call the corresponding callee directly.
CppTypeFor<TypeCategory::Real, 16> RTDECL(AbsF128)(
CppTypeFor<TypeCategory::Real, 16> x);
CppTypeFor<TypeCategory::Real, 16> RTDECL(SqrtF128)(
CppTypeFor<TypeCategory::Real, 16> x);
} // extern "C"

} // namespace Fortran::runtime

#endif // FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_
59 changes: 59 additions & 0 deletions flang/runtime/Float128Math/norm2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===-- runtime/Float128Math/norm2.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "math-entries.h"
#include "reduction-templates.h"
#include <cmath>

#if LDBL_MANT_DIG == 113 || HAS_FLOAT128

namespace {
using namespace Fortran::runtime;

using AccumType = Norm2AccumType<16>;

struct ABSTy {
static AccumType compute(AccumType x) {
return Sqrt<RTNAME(AbsF128)>::invoke(x);
}
};

struct SQRTTy {
static AccumType compute(AccumType x) {
return Sqrt<RTNAME(SqrtF128)>::invoke(x);
}
};

using Float128Norm2Accumulator = Norm2Accumulator<16, ABSTy, SQRTTy>;
} // namespace

namespace Fortran::runtime {
extern "C" {

CppTypeFor<TypeCategory::Real, 16> RTDEF(Norm2_16)(
const Descriptor &x, const char *source, int line, int dim) {
auto accumulator{::Float128Norm2Accumulator(x)};
return GetTotalReduction<TypeCategory::Real, 16>(
x, source, line, dim, nullptr, accumulator, "NORM2");
}

void RTDEF(Norm2DimReal16)(Descriptor &result, const Descriptor &x, int dim,
const char *source, int line) {
Terminator terminator{source, line};
auto type{x.type().GetCategoryAndKind()};
RUNTIME_CHECK(terminator, type);
RUNTIME_CHECK(
terminator, type->first == TypeCategory::Real && type->second == 16);
DoMaxMinNorm2<TypeCategory::Real, 16, ::Float128Norm2Accumulator>(
result, x, dim, nullptr, "NORM2", terminator);
}

} // extern "C"
} // namespace Fortran::runtime

#endif
107 changes: 12 additions & 95 deletions flang/runtime/extrema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,35 +528,6 @@ inline RT_API_ATTRS CppTypeFor<CAT, KIND> TotalNumericMaxOrMin(
NumericExtremumAccumulator<CAT, KIND, IS_MAXVAL>{x}, intrinsic);
}

template <TypeCategory CAT, int KIND, typename ACCUMULATOR>
static RT_API_ATTRS void DoMaxMinNorm2(Descriptor &result, const Descriptor &x,
int dim, const Descriptor *mask, const char *intrinsic,
Terminator &terminator) {
using Type = CppTypeFor<CAT, KIND>;
ACCUMULATOR accumulator{x};
if (dim == 0 || x.rank() == 1) {
// Total reduction

// Element size of the destination descriptor is the same
// as the element size of the source.
result.Establish(x.type(), x.ElementBytes(), nullptr, 0, nullptr,
CFI_attribute_allocatable);
if (int stat{result.Allocate()}) {
terminator.Crash(
"%s: could not allocate memory for result; STAT=%d", intrinsic, stat);
}
DoTotalReduction<Type>(x, dim, mask, accumulator, intrinsic, terminator);
accumulator.GetResult(result.OffsetElement<Type>());
} else {
// Partial reduction

// Element size of the destination descriptor is the same
// as the element size of the source.
PartialReduction<ACCUMULATOR, CAT, KIND>(result, x, x.ElementBytes(), dim,
mask, terminator, intrinsic, accumulator);
}
}

template <TypeCategory CAT, bool IS_MAXVAL> struct MaxOrMinHelper {
template <int KIND> struct Functor {
RT_API_ATTRS void operator()(Descriptor &result, const Descriptor &x,
Expand Down Expand Up @@ -802,66 +773,11 @@ RT_EXT_API_GROUP_END

// NORM2

RT_VAR_GROUP_BEGIN

// Use at least double precision for accumulators.
// Don't use __float128, it doesn't work with abs() or sqrt() yet.
static constexpr RT_CONST_VAR_ATTRS int largestLDKind {
#if LDBL_MANT_DIG == 113
16
#elif LDBL_MANT_DIG == 64
10
#else
8
#endif
};

RT_VAR_GROUP_END

template <int KIND> class Norm2Accumulator {
public:
using Type = CppTypeFor<TypeCategory::Real, KIND>;
using AccumType =
CppTypeFor<TypeCategory::Real, std::clamp(KIND, 8, largestLDKind)>;
explicit RT_API_ATTRS Norm2Accumulator(const Descriptor &array)
: array_{array} {}
RT_API_ATTRS void Reinitialize() { max_ = sum_ = 0; }
template <typename A>
RT_API_ATTRS void GetResult(A *p, int /*zeroBasedDim*/ = -1) const {
// m * sqrt(1 + sum((others(:)/m)**2))
*p = static_cast<Type>(max_ * std::sqrt(1 + sum_));
}
RT_API_ATTRS bool Accumulate(Type x) {
auto absX{std::abs(static_cast<AccumType>(x))};
if (!max_) {
max_ = absX;
} else if (absX > max_) {
auto t{max_ / absX}; // < 1.0
auto tsq{t * t};
sum_ *= tsq; // scale sum to reflect change to the max
sum_ += tsq; // include a term for the previous max
max_ = absX;
} else { // absX <= max_
auto t{absX / max_};
sum_ += t * t;
}
return true;
}
template <typename A>
RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) {
return Accumulate(*array_.Element<A>(at));
}

private:
const Descriptor &array_;
AccumType max_{0}; // value (m) with largest magnitude
AccumType sum_{0}; // sum((others(:)/m)**2)
};

template <int KIND> struct Norm2Helper {
RT_API_ATTRS void operator()(Descriptor &result, const Descriptor &x, int dim,
const Descriptor *mask, Terminator &terminator) const {
DoMaxMinNorm2<TypeCategory::Real, KIND, Norm2Accumulator<KIND>>(
DoMaxMinNorm2<TypeCategory::Real, KIND,
typename Norm2AccumulatorGetter<KIND>::Type>(
result, x, dim, mask, "NORM2", terminator);
}
};
Expand All @@ -872,26 +788,27 @@ RT_EXT_API_GROUP_BEGIN
// TODO: REAL(2 & 3)
CppTypeFor<TypeCategory::Real, 4> RTDEF(Norm2_4)(
const Descriptor &x, const char *source, int line, int dim) {
return GetTotalReduction<TypeCategory::Real, 4>(
x, source, line, dim, nullptr, Norm2Accumulator<4>{x}, "NORM2");
return GetTotalReduction<TypeCategory::Real, 4>(x, source, line, dim, nullptr,
Norm2AccumulatorGetter<4>::create(x), "NORM2");
}
CppTypeFor<TypeCategory::Real, 8> RTDEF(Norm2_8)(
const Descriptor &x, const char *source, int line, int dim) {
return GetTotalReduction<TypeCategory::Real, 8>(
x, source, line, dim, nullptr, Norm2Accumulator<8>{x}, "NORM2");
return GetTotalReduction<TypeCategory::Real, 8>(x, source, line, dim, nullptr,
Norm2AccumulatorGetter<8>::create(x), "NORM2");
}
#if LDBL_MANT_DIG == 64
CppTypeFor<TypeCategory::Real, 10> RTDEF(Norm2_10)(
const Descriptor &x, const char *source, int line, int dim) {
return GetTotalReduction<TypeCategory::Real, 10>(
x, source, line, dim, nullptr, Norm2Accumulator<10>{x}, "NORM2");
return GetTotalReduction<TypeCategory::Real, 10>(x, source, line, dim,
nullptr, Norm2AccumulatorGetter<10>::create(x), "NORM2");
}
#endif
#if LDBL_MANT_DIG == 113
// The __float128 implementation resides in FortranFloat128Math library.
CppTypeFor<TypeCategory::Real, 16> RTDEF(Norm2_16)(
const Descriptor &x, const char *source, int line, int dim) {
return GetTotalReduction<TypeCategory::Real, 16>(
x, source, line, dim, nullptr, Norm2Accumulator<16>{x}, "NORM2");
return GetTotalReduction<TypeCategory::Real, 16>(x, source, line, dim,
nullptr, Norm2AccumulatorGetter<16>::create(x), "NORM2");
}
#endif

Expand All @@ -901,7 +818,7 @@ void RTDEF(Norm2Dim)(Descriptor &result, const Descriptor &x, int dim,
auto type{x.type().GetCategoryAndKind()};
RUNTIME_CHECK(terminator, type);
if (type->first == TypeCategory::Real) {
ApplyFloatingPointKind<Norm2Helper, void>(
ApplyFloatingPointKind<Norm2Helper, void, true>(
type->second, terminator, result, x, dim, nullptr, terminator);
} else {
terminator.Crash("NORM2: bad type code %d", x.type().raw());
Expand Down
115 changes: 115 additions & 0 deletions flang/runtime/reduction-templates.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "tools.h"
#include "flang/Runtime/cpp-type.h"
#include "flang/Runtime/descriptor.h"
#include <algorithm>

namespace Fortran::runtime {

Expand Down Expand Up @@ -332,5 +333,119 @@ template <typename ACCUMULATOR> struct PartialLocationHelper {
};
};

// NORM2 templates

RT_VAR_GROUP_BEGIN

// Use at least double precision for accumulators.
// Don't use __float128, it doesn't work with abs() or sqrt() yet.
static constexpr RT_CONST_VAR_ATTRS int Norm2LargestLDKind {
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
16
#elif LDBL_MANT_DIG == 64
10
#else
8
#endif
};

RT_VAR_GROUP_END

template <TypeCategory CAT, int KIND, typename ACCUMULATOR>
inline RT_API_ATTRS void DoMaxMinNorm2(Descriptor &result, const Descriptor &x,
int dim, const Descriptor *mask, const char *intrinsic,
Terminator &terminator) {
using Type = CppTypeFor<CAT, KIND>;
ACCUMULATOR accumulator{x};
if (dim == 0 || x.rank() == 1) {
// Total reduction

// Element size of the destination descriptor is the same
// as the element size of the source.
result.Establish(x.type(), x.ElementBytes(), nullptr, 0, nullptr,
CFI_attribute_allocatable);
if (int stat{result.Allocate()}) {
terminator.Crash(
"%s: could not allocate memory for result; STAT=%d", intrinsic, stat);
}
DoTotalReduction<Type>(x, dim, mask, accumulator, intrinsic, terminator);
accumulator.GetResult(result.OffsetElement<Type>());
} else {
// Partial reduction

// Element size of the destination descriptor is the same
// as the element size of the source.
PartialReduction<ACCUMULATOR, CAT, KIND>(result, x, x.ElementBytes(), dim,
mask, terminator, intrinsic, accumulator);
}
}

// The data type used by Norm2Accumulator.
template <int KIND>
using Norm2AccumType =
CppTypeFor<TypeCategory::Real, std::clamp(KIND, 8, Norm2LargestLDKind)>;

template <int KIND, typename ABS, typename SQRT> class Norm2Accumulator {
public:
using Type = CppTypeFor<TypeCategory::Real, KIND>;
using AccumType = Norm2AccumType<KIND>;
explicit RT_API_ATTRS Norm2Accumulator(const Descriptor &array)
: array_{array} {}
RT_API_ATTRS void Reinitialize() { max_ = sum_ = 0; }
template <typename A>
RT_API_ATTRS void GetResult(A *p, int /*zeroBasedDim*/ = -1) const {
// m * sqrt(1 + sum((others(:)/m)**2))
*p = static_cast<Type>(max_ * SQRT::compute(1 + sum_));
}
RT_API_ATTRS bool Accumulate(Type x) {
auto absX{ABS::compute(static_cast<AccumType>(x))};
if (!max_) {
max_ = absX;
} else if (absX > max_) {
auto t{max_ / absX}; // < 1.0
auto tsq{t * t};
sum_ *= tsq; // scale sum to reflect change to the max
sum_ += tsq; // include a term for the previous max
max_ = absX;
} else { // absX <= max_
auto t{absX / max_};
sum_ += t * t;
}
return true;
}
template <typename A>
RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) {
return Accumulate(*array_.Element<A>(at));
}

private:
const Descriptor &array_;
AccumType max_{0}; // value (m) with largest magnitude
AccumType sum_{0}; // sum((others(:)/m)**2)
};

// Helper class for creating Norm2Accumulator instance
// based on the given KIND. This helper returns and instance
// that uses std::abs and std::sqrt for the computations.
template <int KIND> class Norm2AccumulatorGetter {
using AccumType = Norm2AccumType<KIND>;

public:
struct ABSTy {
static constexpr RT_API_ATTRS AccumType compute(AccumType &&x) {
return std::abs(std::forward<AccumType>(x));
}
};
struct SQRTTy {
static constexpr RT_API_ATTRS AccumType compute(AccumType &&x) {
return std::sqrt(std::forward<AccumType>(x));
}
};

using Type = Norm2Accumulator<KIND, ABSTy, SQRTTy>;

static RT_API_ATTRS Type create(const Descriptor &x) { return Type(x); }
};

} // namespace Fortran::runtime
#endif // FORTRAN_RUNTIME_REDUCTION_TEMPLATES_H_
11 changes: 9 additions & 2 deletions flang/runtime/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ inline RT_API_ATTRS RESULT ApplyIntegerKind(
}
}

template <template <int KIND> class FUNC, typename RESULT, typename... A>
template <template <int KIND> class FUNC, typename RESULT,
bool NEEDSMATH = false, typename... A>
inline RT_API_ATTRS RESULT ApplyFloatingPointKind(
int kind, Terminator &terminator, A &&...x) {
switch (kind) {
Expand All @@ -287,7 +288,13 @@ inline RT_API_ATTRS RESULT ApplyFloatingPointKind(
break;
case 16:
if constexpr (HasCppTypeFor<TypeCategory::Real, 16>) {
return FUNC<16>{}(std::forward<A>(x)...);
// If FUNC implemenation relies on FP math functions,
// then we should not be here. The compiler should have
// generated a call to an entry in FortranFloat128Math
// library.
if constexpr (!NEEDSMATH) {
return FUNC<16>{}(std::forward<A>(x)...);
}
}
break;
}
Expand Down
4 changes: 2 additions & 2 deletions flang/test/Driver/flang-experimental-polymorphism-flag.f90
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
! Test -flang-experimental-hlfir flag
! RUN: %flang_fc1 -flang-experimental-polymorphism -emit-fir -o - %s | FileCheck %s
! RUN: not %flang_fc1 -emit-fir -o - %s 2>&1 | FileCheck %s --check-prefix NO-POLYMORPHISM
! RUN: %flang_fc1 -emit-fir -o - %s 2>&1 | FileCheck %s --check-prefix NO-POLYMORPHISM

! CHECK: func.func @_QPtest(%{{.*}}: !fir.class<none> {fir.bindc_name = "poly"})
subroutine test(poly)
class(*) :: poly
end subroutine test

! NO-POLYMORPHISM: not yet implemented: support for polymorphic types
! NO-POLYMORPHISM: func.func @_QPtest
16 changes: 16 additions & 0 deletions flang/test/Lower/Intrinsics/norm2.f90
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,19 @@ subroutine norm2_test_dim_3(a,r)
! CHECK-DAG: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?x?xf32>>>) -> !fir.heap<!fir.array<?x?xf32>>
! CHECK-DAG: fir.freemem %[[addr]]
end subroutine norm2_test_dim_3

! CHECK-LABEL: func @_QPnorm2_test_real16(
! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?x?x?xf128>>{{.*}}, %[[arg1:.*]]: !fir.box<!fir.array<?x?xf128>>{{.*}})
subroutine norm2_test_real16(a,r)
real(16) :: a(:,:,:)
real(16) :: r(:,:)
! CHECK-DAG: %[[dim:.*]] = arith.constant 3 : i32
! CHECK-DAG: %[[r:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xf128>>>
! CHECK-DAG: %[[res:.*]] = fir.convert %[[r]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf128>>>>) -> !fir.ref<!fir.box<none>>
! CHECK: %[[arr:.*]] = fir.convert %[[arg0]] : (!fir.box<!fir.array<?x?x?xf128>>) -> !fir.box<none>
r = norm2(a,dim=3)
! CHECK: %{{.*}} = fir.call @_FortranANorm2DimReal16(%[[res]], %[[arr]], %[[dim]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
! CHECK: %[[box:.*]] = fir.load %[[r]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xf128>>>>
! CHECK-DAG: %[[addr:.*]] = fir.box_addr %[[box]] : (!fir.box<!fir.heap<!fir.array<?x?xf128>>>) -> !fir.heap<!fir.array<?x?xf128>>
! CHECK-DAG: fir.freemem %[[addr]]
end subroutine norm2_test_real16
2 changes: 2 additions & 0 deletions libc/.clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ CheckOptions:
value: UPPER_CASE
- key: readability-identifier-naming.ConstexprVariableCase
value: UPPER_CASE
- key: readability-identifier-naming.ConstexprFunctionCase
value: lower_case
- key: readability-identifier-naming.GetConfigPerFile
value: true
2 changes: 1 addition & 1 deletion libc/cmake/modules/compiler_features/check_float128.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "src/__support/macros/properties/float.h"
#include "src/__support/macros/properties/types.h"

#ifndef LIBC_COMPILER_HAS_FLOAT128
#error unsupported
Expand Down
36 changes: 36 additions & 0 deletions libc/config/baremetal/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,42 @@ include "config/public_api.td"

include "spec/stdc.td"

def AssertMacro : MacroDef<"assert"> {
let Defn = [{
#undef assert

#ifdef NDEBUG
#define assert(e) (void)0
#else

#ifdef __cplusplus
extern "C"
#endif
_Noreturn void __assert_fail(const char *, const char *, unsigned, const char *) __NOEXCEPT;

#define assert(e) \
((e) ? (void)0 : __assert_fail(#e, __FILE__, __LINE__, __PRETTY_FUNCTION__))

#endif
}];
}

def StaticAssertMacro : MacroDef<"static_assert"> {
let Defn = [{
#ifndef __cplusplus
#undef static_assert
#define static_assert _Static_assert
#endif
}];
}

def AssertAPI : PublicAPI<"assert.h"> {
let Macros = [
AssertMacro,
StaticAssertMacro,
];
}

def CTypeAPI : PublicAPI<"ctype.h"> {
}

Expand Down
3 changes: 3 additions & 0 deletions libc/config/baremetal/arm/entrypoints.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set(TARGET_LIBC_ENTRYPOINTS
# assert.h entrypoints
libc.src.assert.__assert_fail

# ctype.h entrypoints
libc.src.ctype.isalnum
libc.src.ctype.isalpha
Expand Down
1 change: 1 addition & 0 deletions libc/config/baremetal/arm/headers.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
set(TARGET_PUBLIC_HEADERS
libc.include.assert
libc.include.ctype
libc.include.fenv
libc.include.errno
Expand Down
3 changes: 3 additions & 0 deletions libc/config/baremetal/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
set(TARGET_LIBC_ENTRYPOINTS
# assert.h entrypoints
libc.src.assert.__assert_fail

# ctype.h entrypoints
libc.src.ctype.isalnum
libc.src.ctype.isalpha
Expand Down
1 change: 1 addition & 0 deletions libc/config/baremetal/riscv/headers.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
set(TARGET_PUBLIC_HEADERS
libc.include.assert
libc.include.ctype
libc.include.fenv
libc.include.errno
Expand Down
2 changes: 1 addition & 1 deletion libc/docs/dev/code_style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ We define two kinds of macros:
e.g., ``LIBC_COMPILER_IS_CLANG``.
* ``cpu_features.h`` - Target cpu feature availability.
e.g., ``LIBC_TARGET_CPU_HAS_AVX2``.
* ``float.h`` - Floating point type properties and availability.
* ``types.h`` - Type properties and availability.
e.g., ``LIBC_COMPILER_HAS_FLOAT128``.
* ``os.h`` - Target os properties.
e.g., ``LIBC_TARGET_OS_IS_LINUX``.
Expand Down
6 changes: 3 additions & 3 deletions libc/include/__llvm-libc-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC___COMMON_H
#define LLVM_LIBC___COMMON_H
#ifndef LLVM_LIBC_COMMON_H
#define LLVM_LIBC_COMMON_H

#ifdef __cplusplus

Expand Down Expand Up @@ -51,4 +51,4 @@

#endif // __cplusplus

#endif // LLVM_LIBC___COMMON_H
#endif // LLVM_LIBC_COMMON_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/containerof-macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H
#define __LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H
#ifndef LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H
#define LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H

#include <llvm-libc-macros/offsetof-macro.h>

Expand All @@ -17,4 +17,4 @@
(type *)(void *)((const char *)__ptr - offsetof(type, member)); \
})

#endif // __LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H
#endif // LLVM_LIBC_MACROS_CONTAINEROF_MACRO_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/fcntl-macros.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef __LLVM_LIBC_MACROS_FCNTL_MACROS_H
#define __LLVM_LIBC_MACROS_FCNTL_MACROS_H
#ifndef LLVM_LIBC_MACROS_FCNTL_MACROS_H
#define LLVM_LIBC_MACROS_FCNTL_MACROS_H

#ifdef __linux__
#include "linux/fcntl-macros.h"
#endif

#endif // __LLVM_LIBC_MACROS_FCNTL_MACROS_H
#endif // LLVM_LIBC_MACROS_FCNTL_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/features-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_FEATURES_MACROS_H
#define __LLVM_LIBC_MACROS_FEATURES_MACROS_H
#ifndef LLVM_LIBC_MACROS_FEATURES_MACROS_H
#define LLVM_LIBC_MACROS_FEATURES_MACROS_H

#define __LLVM_LIBC__ 1

#endif // __LLVM_LIBC_MACROS_FEATURES_MACROS_H
#endif // LLVM_LIBC_MACROS_FEATURES_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/fenv-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_FENV_MACROS_H
#define __LLVM_LIBC_MACROS_FENV_MACROS_H
#ifndef LLVM_LIBC_MACROS_FENV_MACROS_H
#define LLVM_LIBC_MACROS_FENV_MACROS_H

#define FE_DIVBYZERO 1
#define FE_INEXACT 2
Expand All @@ -24,4 +24,4 @@

#define FE_DFL_ENV ((fenv_t *)-1)

#endif // __LLVM_LIBC_MACROS_FENV_MACROS_H
#endif // LLVM_LIBC_MACROS_FENV_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/file-seek-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
#define __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
#ifndef LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
#define LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H

#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

#endif // __LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
#endif // LLVM_LIBC_MACROS_FILE_SEEK_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/float-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_FLOAT_MACROS_H
#define __LLVM_LIBC_MACROS_FLOAT_MACROS_H
#ifndef LLVM_LIBC_MACROS_FLOAT_MACROS_H
#define LLVM_LIBC_MACROS_FLOAT_MACROS_H

// Suppress `#include_next is a language extension` warnings.
#ifdef __clang__
Expand Down Expand Up @@ -169,4 +169,4 @@

// TODO: Add FLT16 and FLT128 constants.

#endif // __LLVM_LIBC_MACROS_FLOAT_MACROS_H
#endif // LLVM_LIBC_MACROS_FLOAT_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/generic-error-number-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
#define __LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
#ifndef LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
#define LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H

#define EPERM 1
#define ENOENT 2
Expand Down Expand Up @@ -45,4 +45,4 @@
#define ERANGE 34
#define EILSEQ 35

#endif // __LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
#endif // LLVM_LIBC_MACROS_GENERIC_ERROR_NUMBER_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/gpu/time-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
#define __LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
#ifndef LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
#define LLVM_LIBC_MACROS_GPU_TIME_MACROS_H

#define CLOCKS_PER_SEC 1000000

#endif // __LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
#endif // LLVM_LIBC_MACROS_GPU_TIME_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/inttypes-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef __LLVM_LIBC_MACROS_INTTYPES_MACROS_H
#define __LLVM_LIBC_MACROS_INTTYPES_MACROS_H
#ifndef LLVM_LIBC_MACROS_INTTYPES_MACROS_H
#define LLVM_LIBC_MACROS_INTTYPES_MACROS_H

// fprintf/scanf format macros.
// POSIX.1-2008, Technical Corrigendum 1, XBD/TC1-2008/0050 [211] is applied.
Expand Down Expand Up @@ -286,4 +286,4 @@
#define SCNxMAX __UINTMAX_FMTx__
#define SCNxPTR __UINTPTR_FMTx__

#endif // __LLVM_LIBC_MACROS_INTTYPES_MACROS_H
#endif // LLVM_LIBC_MACROS_INTTYPES_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/limits-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LIMITS_MACROS_H
#define __LLVM_LIBC_MACROS_LIMITS_MACROS_H
#ifndef LLVM_LIBC_MACROS_LIMITS_MACROS_H
#define LLVM_LIBC_MACROS_LIMITS_MACROS_H

// Define all C23 macro constants of limits.h

Expand Down Expand Up @@ -225,4 +225,4 @@
#define ULLONG_MIN 0ULL
#endif // ULLONG_MIN

#endif // __LLVM_LIBC_MACROS_LIMITS_MACROS_H
#endif // LLVM_LIBC_MACROS_LIMITS_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/fcntl-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H

// File creation flags
#define O_CLOEXEC 02000000
Expand Down Expand Up @@ -68,4 +68,4 @@
#define F_GETFL 3
#define F_SETFL 4

#endif // __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sched-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H

// Definitions of SCHED_* macros must match was linux as at:
// https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/sched.h
Expand All @@ -26,4 +26,4 @@
#define CPU_COUNT_S(setsize, set) __sched_getcpucount(setsize, set)
#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t), set)

#endif // __LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SCHED_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/signal-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SIGNUM_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SIGNUM_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SIGNAL_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SIGNAL_MACROS_H

#define SIGHUP 1
#define SIGINT 2
Expand Down Expand Up @@ -101,4 +101,4 @@
#define CLD_STOPPED 5 // child has stopped
#define CLD_CONTINUED 6 // stopped child has continued

#endif // __LLVM_LIBC_MACROS_LINUX_SIGNUM_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SIGNAL_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-ioctl-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H

// TODO (michaelrj): Finish defining these macros.
// Just defining this macro for the moment since it's all that we need right
Expand All @@ -16,4 +16,4 @@
// think is worth digging into right now.
#define TIOCGETD 0x5424

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_IOCTL_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-random-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H

// Getrandom flags
#define GRND_RANDOM 0x0001
#define GRND_NONBLOCK 0x0002
#define GRND_INSECURE 0x0004

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_RANDOM_MACROS_H
5 changes: 5 additions & 0 deletions libc/include/llvm-libc-macros/linux/sys-resource-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_MACROS_LINUX_SYS_RESOURCE_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_RESOURCE_MACROS_H

#define RLIMIT_CPU 0
#define RLIMIT_FSIZE 1
#define RLIMIT_DATA 2
Expand All @@ -24,3 +27,5 @@
#define RLIMIT_RTTIME 15

#define RLIM_INFINITY (~0UL)

#endif // LLVM_LIBC_MACROS_LINUX_SYS_RESOURCE_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-socket-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H

// IEEE Std 1003.1-2017 - basedefs/sys_socket.h.html
// Macro values come from the Linux syscall interface.
Expand All @@ -25,4 +25,4 @@
#define SOCK_SEQPACKET 5
#define SOCK_PACKET 10

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_SOCKET_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-stat-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H

// Definitions from linux/stat.h
#define S_IFMT 0170000
Expand Down Expand Up @@ -45,4 +45,4 @@
#define S_IWOTH 00002
#define S_IXOTH 00001

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_STAT_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-time-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H

// Add two timevals and put the result in timeval_ptr_result. If the resulting
// usec value is greater than 999,999 then the microseconds are turned into full
Expand Down Expand Up @@ -50,4 +50,4 @@
? ((timeval_ptr_a)->tv_usec CMP(timeval_ptr_b)->tv_usec) \
: ((timeval_ptr_a)->tv_sec CMP(timeval_ptr_b)->tv_sec))

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_TIME_MACROS_H
6 changes: 3 additions & 3 deletions libc/include/llvm-libc-macros/linux/sys-wait-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//

#ifndef __LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H
#define __LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H
#ifndef LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H
#define LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H

// Wait flags
#define WNOHANG 1 // Do not block
Expand Down Expand Up @@ -41,4 +41,4 @@
#define P_PGID 2
#define P_PIDFD 3

#endif // __LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H
#endif // LLVM_LIBC_MACROS_LINUX_SYS_WAIT_MACROS_H
Loading