220 changes: 141 additions & 79 deletions flang/lib/Lower/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2266,31 +2266,68 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
return storeOp;
}

struct CreateBodyOfOpInfo {
struct OpWithBodyGenInfo {
/// A type for a code-gen callback function. This takes as argument the op for
/// which the code is being generated and returns the arguments of the op's
/// region.
using GenOMPRegionEntryCBFn =
std::function<llvm::SmallVector<const Fortran::semantics::Symbol *>(
mlir::Operation *)>;

OpWithBodyGenInfo(Fortran::lower::AbstractConverter &converter,
mlir::Location loc, Fortran::lower::pft::Evaluation &eval)
: converter(converter), loc(loc), eval(eval) {}

OpWithBodyGenInfo &setGenNested(bool value) {
genNested = value;
return *this;
}

OpWithBodyGenInfo &setOuterCombined(bool value) {
outerCombined = value;
return *this;
}

OpWithBodyGenInfo &setClauses(const Fortran::parser::OmpClauseList *value) {
clauses = value;
return *this;
}

OpWithBodyGenInfo &setDataSharingProcessor(DataSharingProcessor *value) {
dsp = value;
return *this;
}

OpWithBodyGenInfo &setGenRegionEntryCb(GenOMPRegionEntryCBFn value) {
genRegionEntryCB = value;
return *this;
}

/// [inout] converter to use for the clauses.
Fortran::lower::AbstractConverter &converter;
mlir::Location &loc;
/// [in] location in source code.
mlir::Location loc;
/// [in] current PFT node/evaluation.
Fortran::lower::pft::Evaluation &eval;
/// [in] whether to generate FIR for nested evaluations
bool genNested = true;
const Fortran::parser::OmpClauseList *clauses = nullptr;
const llvm::SmallVector<const Fortran::semantics::Symbol *> &args = {};
/// [in] is this an outer operation - prevents privatization.
bool outerCombined = false;
/// [in] list of clauses to process.
const Fortran::parser::OmpClauseList *clauses = nullptr;
/// [in] if provided, processes the construct's data-sharing attributes.
DataSharingProcessor *dsp = nullptr;
/// [in] if provided, emits the op's region entry. Otherwise, an emtpy block
/// is created in the region.
GenOMPRegionEntryCBFn genRegionEntryCB = nullptr;
};

/// Create the body (block) for an OpenMP Operation.
///
/// \param [in] op - the operation the body belongs to.
/// \param [inout] converter - converter to use for the clauses.
/// \param [in] loc - location in source code.
/// \param [in] eval - current PFT node/evaluation.
/// \param [in] genNested - whether to generate FIR for nested evaluations
/// \oaran [in] clauses - list of clauses to process.
/// \param [in] args - block arguments (induction variable[s]) for the
//// region.
/// \param [in] outerCombined - is this an outer operation - prevents
/// privatization.
/// \param [in] op - the operation the body belongs to.
/// \param [in] info - options controlling code-gen for the construction.
template <typename Op>
static void createBodyOfOp(Op &op, CreateBodyOfOpInfo info) {
static void createBodyOfOp(Op &op, OpWithBodyGenInfo &info) {
fir::FirOpBuilder &firOpBuilder = info.converter.getFirOpBuilder();

auto insertMarker = [](fir::FirOpBuilder &builder) {
Expand All @@ -2303,28 +2340,15 @@ static void createBodyOfOp(Op &op, CreateBodyOfOpInfo info) {
// argument. Also update the symbol's address with the mlir argument value.
// e.g. For loops the argument is the induction variable. And all further
// uses of the induction variable should use this mlir value.
if (info.args.size()) {
std::size_t loopVarTypeSize = 0;
for (const Fortran::semantics::Symbol *arg : info.args)
loopVarTypeSize = std::max(loopVarTypeSize, arg->GetUltimate().size());
mlir::Type loopVarType = getLoopVarType(info.converter, loopVarTypeSize);
llvm::SmallVector<mlir::Type> tiv(info.args.size(), loopVarType);
llvm::SmallVector<mlir::Location> locs(info.args.size(), info.loc);
firOpBuilder.createBlock(&op.getRegion(), {}, tiv, locs);
// The argument is not currently in memory, so make a temporary for the
// argument, and store it there, then bind that location to the argument.
mlir::Operation *storeOp = nullptr;
for (auto [argIndex, argSymbol] : llvm::enumerate(info.args)) {
mlir::Value indexVal =
fir::getBase(op.getRegion().front().getArgument(argIndex));
storeOp = createAndSetPrivatizedLoopVar(info.converter, info.loc,
indexVal, argSymbol);
auto regionArgs =
[&]() -> llvm::SmallVector<const Fortran::semantics::Symbol *> {
if (info.genRegionEntryCB != nullptr) {
return info.genRegionEntryCB(op);
}
firOpBuilder.setInsertionPointAfter(storeOp);
} else {
firOpBuilder.createBlock(&op.getRegion());
}

firOpBuilder.createBlock(&op.getRegion());
return {};
}();
// Mark the earliest insertion point.
mlir::Operation *marker = insertMarker(firOpBuilder);

Expand Down Expand Up @@ -2421,8 +2445,8 @@ static void createBodyOfOp(Op &op, CreateBodyOfOpInfo info) {
assert(tempDsp.has_value());
tempDsp->processStep2(op, isLoop);
} else {
if (isLoop && info.args.size() > 0)
info.dsp->setLoopIV(info.converter.getSymbolAddress(*info.args[0]));
if (isLoop && regionArgs.size() > 0)
info.dsp->setLoopIV(info.converter.getSymbolAddress(*regionArgs[0]));
info.dsp->processStep2(op, isLoop);
}
}
Expand Down Expand Up @@ -2497,24 +2521,11 @@ static void genBodyOfTargetDataOp(
genNestedEvaluations(converter, eval);
}

struct GenOpWithBodyInfo {
Fortran::lower::AbstractConverter &converter;
Fortran::lower::pft::Evaluation &eval;
bool genNested = false;
mlir::Location currentLocation;
bool outerCombined = false;
const Fortran::parser::OmpClauseList *clauseList = nullptr;
};

template <typename OpTy, typename... Args>
static OpTy genOpWithBody(GenOpWithBodyInfo info, Args &&...args) {
static OpTy genOpWithBody(OpWithBodyGenInfo &info, Args &&...args) {
auto op = info.converter.getFirOpBuilder().create<OpTy>(
info.currentLocation, std::forward<Args>(args)...);
createBodyOfOp<OpTy>(
op, {info.converter, info.currentLocation, info.eval, info.genNested,
info.clauseList,
/*args*/ llvm::SmallVector<const Fortran::semantics::Symbol *>{},
info.outerCombined});
info.loc, std::forward<Args>(args)...);
createBodyOfOp<OpTy>(op, info);
return op;
}

Expand All @@ -2523,7 +2534,8 @@ genMasterOp(Fortran::lower::AbstractConverter &converter,
Fortran::lower::pft::Evaluation &eval, bool genNested,
mlir::Location currentLocation) {
return genOpWithBody<mlir::omp::MasterOp>(
{converter, eval, genNested, currentLocation},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested),
/*resultTypes=*/mlir::TypeRange());
}

Expand All @@ -2532,7 +2544,8 @@ genOrderedRegionOp(Fortran::lower::AbstractConverter &converter,
Fortran::lower::pft::Evaluation &eval, bool genNested,
mlir::Location currentLocation) {
return genOpWithBody<mlir::omp::OrderedRegionOp>(
{converter, eval, genNested, currentLocation},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested),
/*simd=*/false);
}

Expand Down Expand Up @@ -2560,7 +2573,10 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols);

return genOpWithBody<mlir::omp::ParallelOp>(
{converter, eval, genNested, currentLocation, outerCombined, &clauseList},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setOuterCombined(outerCombined)
.setClauses(&clauseList),
/*resultTypes=*/mlir::TypeRange(), ifClauseOperand,
numThreadsClauseOperand, allocateOperands, allocatorOperands,
reductionVars,
Expand All @@ -2579,8 +2595,9 @@ genSectionOp(Fortran::lower::AbstractConverter &converter,
// Currently only private/firstprivate clause is handled, and
// all privatization is done within `omp.section` operations.
return genOpWithBody<mlir::omp::SectionOp>(
{converter, eval, genNested, currentLocation,
/*outerCombined=*/false, &sectionsClauseList});
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setClauses(&sectionsClauseList));
}

static mlir::omp::SingleOp
Expand All @@ -2600,8 +2617,9 @@ genSingleOp(Fortran::lower::AbstractConverter &converter,
ClauseProcessor(converter, endClauseList).processNowait(nowaitAttr);

return genOpWithBody<mlir::omp::SingleOp>(
{converter, eval, genNested, currentLocation,
/*outerCombined=*/false, &beginClauseList},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setClauses(&beginClauseList),
allocateOperands, allocatorOperands, nowaitAttr);
}

Expand Down Expand Up @@ -2633,8 +2651,9 @@ genTaskOp(Fortran::lower::AbstractConverter &converter,
currentLocation, llvm::omp::Directive::OMPD_task);

return genOpWithBody<mlir::omp::TaskOp>(
{converter, eval, genNested, currentLocation,
/*outerCombined=*/false, &clauseList},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setClauses(&clauseList),
ifClauseOperand, finalClauseOperand, untiedAttr, mergeableAttr,
/*in_reduction_vars=*/mlir::ValueRange(),
/*in_reductions=*/nullptr, priorityClauseOperand,
Expand All @@ -2656,8 +2675,9 @@ genTaskGroupOp(Fortran::lower::AbstractConverter &converter,
cp.processTODO<Fortran::parser::OmpClause::TaskReduction>(
currentLocation, llvm::omp::Directive::OMPD_taskgroup);
return genOpWithBody<mlir::omp::TaskGroupOp>(
{converter, eval, genNested, currentLocation,
/*outerCombined=*/false, &clauseList},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setClauses(&clauseList),
/*task_reduction_vars=*/mlir::ValueRange(),
/*task_reductions=*/nullptr, allocateOperands, allocatorOperands);
}
Expand Down Expand Up @@ -3040,7 +3060,10 @@ genTeamsOp(Fortran::lower::AbstractConverter &converter,
currentLocation, llvm::omp::Directive::OMPD_teams);

return genOpWithBody<mlir::omp::TeamsOp>(
{converter, eval, genNested, currentLocation, outerCombined, &clauseList},
OpWithBodyGenInfo(converter, currentLocation, eval)
.setGenNested(genNested)
.setOuterCombined(outerCombined)
.setClauses(&clauseList),
/*num_teams_lower=*/nullptr, numTeamsClauseOperand, ifClauseOperand,
threadLimitClauseOperand, allocateOperands, allocatorOperands,
reductionVars,
Expand Down Expand Up @@ -3237,6 +3260,33 @@ static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
}
}

static llvm::SmallVector<const Fortran::semantics::Symbol *>
genLoopVars(mlir::Operation *op, Fortran::lower::AbstractConverter &converter,
mlir::Location &loc,
const llvm::SmallVector<const Fortran::semantics::Symbol *> &args) {
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
auto &region = op->getRegion(0);

std::size_t loopVarTypeSize = 0;
for (const Fortran::semantics::Symbol *arg : args)
loopVarTypeSize = std::max(loopVarTypeSize, arg->GetUltimate().size());
mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
llvm::SmallVector<mlir::Type> tiv(args.size(), loopVarType);
llvm::SmallVector<mlir::Location> locs(args.size(), loc);
firOpBuilder.createBlock(&region, {}, tiv, locs);
// The argument is not currently in memory, so make a temporary for the
// argument, and store it there, then bind that location to the argument.
mlir::Operation *storeOp = nullptr;
for (auto [argIndex, argSymbol] : llvm::enumerate(args)) {
mlir::Value indexVal = fir::getBase(region.front().getArgument(argIndex));
storeOp =
createAndSetPrivatizedLoopVar(converter, loc, indexVal, argSymbol);
}
firOpBuilder.setInsertionPointAfter(storeOp);

return args;
}

static void
createSimdLoop(Fortran::lower::AbstractConverter &converter,
Fortran::lower::pft::Evaluation &eval,
Expand Down Expand Up @@ -3284,10 +3334,16 @@ createSimdLoop(Fortran::lower::AbstractConverter &converter,

auto *nestedEval = getCollapsedLoopEval(
eval, Fortran::lower::getCollapseValue(loopOpClauseList));

auto ivCallback = [&](mlir::Operation *op) {
return genLoopVars(op, converter, loc, iv);
};

createBodyOfOp<mlir::omp::SimdLoopOp>(
simdLoopOp, {converter, loc, *nestedEval,
/*genNested=*/true, &loopOpClauseList, iv,
/*outerCombined=*/false, &dsp});
simdLoopOp, OpWithBodyGenInfo(converter, loc, *nestedEval)
.setClauses(&loopOpClauseList)
.setDataSharingProcessor(&dsp)
.setGenRegionEntryCb(ivCallback));
}

static void createWsLoop(Fortran::lower::AbstractConverter &converter,
Expand Down Expand Up @@ -3360,10 +3416,16 @@ static void createWsLoop(Fortran::lower::AbstractConverter &converter,

auto *nestedEval = getCollapsedLoopEval(
eval, Fortran::lower::getCollapseValue(beginClauseList));
createBodyOfOp<mlir::omp::WsLoopOp>(wsLoopOp,
{converter, loc, *nestedEval,
/*genNested=*/true, &beginClauseList, iv,
/*outerCombined=*/false, &dsp});

auto ivCallback = [&](mlir::Operation *op) {
return genLoopVars(op, converter, loc, iv);
};

createBodyOfOp<mlir::omp::WsLoopOp>(
wsLoopOp, OpWithBodyGenInfo(converter, loc, *nestedEval)
.setClauses(&beginClauseList)
.setDataSharingProcessor(&dsp)
.setGenRegionEntryCb(ivCallback));
}

static void createSimdWsLoop(
Expand Down Expand Up @@ -3644,8 +3706,8 @@ genOMP(Fortran::lower::AbstractConverter &converter,
currentLocation, mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(),
global.getSymName()));
}();
createBodyOfOp<mlir::omp::CriticalOp>(criticalOp,
{converter, currentLocation, eval});
auto genInfo = OpWithBodyGenInfo(converter, currentLocation, eval);
createBodyOfOp<mlir::omp::CriticalOp>(criticalOp, genInfo);
}

static void
Expand Down Expand Up @@ -3687,11 +3749,11 @@ genOMP(Fortran::lower::AbstractConverter &converter,
}

// SECTIONS construct
genOpWithBody<mlir::omp::SectionsOp>({converter, eval,
/*genNested=*/false, currentLocation},
/*reduction_vars=*/mlir::ValueRange(),
/*reductions=*/nullptr, allocateOperands,
allocatorOperands, nowaitClauseOperand);
genOpWithBody<mlir::omp::SectionsOp>(
OpWithBodyGenInfo(converter, currentLocation, eval).setGenNested(false),
/*reduction_vars=*/mlir::ValueRange(),
/*reductions=*/nullptr, allocateOperands, allocatorOperands,
nowaitClauseOperand);

const auto &sectionBlocks =
std::get<Fortran::parser::OmpSectionBlocks>(sectionsConstruct.t);
Expand Down
8 changes: 6 additions & 2 deletions flang/lib/Optimizer/Builder/MutableBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,22 +406,26 @@ static bool readToBoxValue(const fir::MutableBoxValue &box,
fir::ExtendedValue
fir::factory::genMutableBoxRead(fir::FirOpBuilder &builder, mlir::Location loc,
const fir::MutableBoxValue &box,
bool mayBePolymorphic) {
bool mayBePolymorphic,
bool preserveLowerBounds) {
if (box.hasAssumedRank())
TODO(loc, "assumed rank allocatables or pointers");
llvm::SmallVector<mlir::Value> lbounds;
llvm::SmallVector<mlir::Value> extents;
llvm::SmallVector<mlir::Value> lengths;
if (readToBoxValue(box, mayBePolymorphic)) {
auto reader = MutablePropertyReader(builder, loc, box);
reader.getLowerBounds(lbounds);
if (preserveLowerBounds)
reader.getLowerBounds(lbounds);
return fir::BoxValue{reader.getIrBox(), lbounds,
box.nonDeferredLenParams()};
}
// Contiguous intrinsic type entity: all the data can be extracted from the
// fir.box.
auto addr =
MutablePropertyReader(builder, loc, box).read(lbounds, extents, lengths);
if (!preserveLowerBounds)
lbounds.clear();
auto rank = box.rank();
if (box.isCharacter()) {
auto len = lengths.empty() ? mlir::Value{} : lengths[0];
Expand Down
30 changes: 18 additions & 12 deletions flang/lib/Optimizer/HLFIR/Transforms/BufferizeHLFIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,22 @@ createArrayTemp(mlir::Location loc, fir::FirOpBuilder &builder,
return {hlfir::Entity{declareOp.getBase()}, trueVal};
}

/// Copy \p source into a new temporary and package the temporary into a
/// <temp,cleanup> tuple. The temporary may be heap or stack allocated.
static mlir::Value copyInTempAndPackage(mlir::Location loc,
fir::FirOpBuilder &builder,
hlfir::Entity source) {
auto [temp, cleanup] = hlfir::createTempFromMold(loc, builder, source);
builder.create<hlfir::AssignOp>(loc, source, temp, temp.isAllocatable(),
/*keep_lhs_length_if_realloc=*/false,
/*temporary_lhs=*/true);
// Dereference allocatable temporary directly to simplify processing
// of its uses.
if (temp.isAllocatable())
temp = hlfir::derefPointersAndAllocatables(loc, builder, temp);
return packageBufferizedExpr(loc, builder, temp, cleanup);
}

struct AsExprOpConversion : public mlir::OpConversionPattern<hlfir::AsExprOp> {
using mlir::OpConversionPattern<hlfir::AsExprOp>::OpConversionPattern;
explicit AsExprOpConversion(mlir::MLIRContext *ctx)
Expand All @@ -178,12 +194,7 @@ struct AsExprOpConversion : public mlir::OpConversionPattern<hlfir::AsExprOp> {
}
// Otherwise, create a copy in a new buffer.
hlfir::Entity source = hlfir::Entity{adaptor.getVar()};
auto [temp, cleanup] = hlfir::createTempFromMold(loc, builder, source);
builder.create<hlfir::AssignOp>(loc, source, temp, temp.isAllocatable(),
/*keep_lhs_length_if_realloc=*/false,
/*temporary_lhs=*/true);
mlir::Value bufferizedExpr =
packageBufferizedExpr(loc, builder, temp, cleanup);
mlir::Value bufferizedExpr = copyInTempAndPackage(loc, builder, source);
rewriter.replaceOp(asExpr, bufferizedExpr);
return mlir::success();
}
Expand Down Expand Up @@ -542,12 +553,7 @@ struct AssociateOpConversion
// non-trivial value with more than one use. We will have to make a copy and
// use that
hlfir::Entity source = hlfir::Entity{bufferizedExpr};
auto [temp, cleanup] = hlfir::createTempFromMold(loc, builder, source);
builder.create<hlfir::AssignOp>(loc, source, temp, temp.isAllocatable(),
/*keep_lhs_length_if_realloc=*/false,
/*temporary_lhs=*/true);
mlir::Value bufferTuple =
packageBufferizedExpr(loc, builder, temp, cleanup);
mlir::Value bufferTuple = copyInTempAndPackage(loc, builder, source);
bufferizedExpr = getBufferizedExprStorage(bufferTuple);
replaceWith(bufferizedExpr, hlfir::Entity{bufferizedExpr}.getFirBase(),
getBufferizedExprMustFreeFlag(bufferTuple));
Expand Down
38 changes: 38 additions & 0 deletions flang/test/HLFIR/as_expr-codegen-polymorphic.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Test hlfir.as_expr codegen for polymorphic expressions.

// RUN: fir-opt %s -bufferize-hlfir | FileCheck %s

!t = !fir.type<t{i:i32}>
func.func @as_expr_class(%arg0 : !fir.class<!t>, %arg1: !fir.ref<!t>) {
%0 = hlfir.as_expr %arg0 : (!fir.class<!t>) -> !hlfir.expr<!t?>
hlfir.assign %0 to %arg1 : !hlfir.expr<!t?>, !fir.ref<!t>
return
}
// CHECK-LABEL: func.func @as_expr_class(
// CHECK: %[[VAL_5:.*]] = arith.constant true
// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = ".tmp"} : (!fir.ref<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>>)
// ... copy ...
// CHECK: %[[VAL_11:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>>
// CHECK: %[[VAL_12:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
// CHECK: %[[VAL_13:.*]] = fir.insert_value %[[VAL_12]], %[[VAL_5]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
// CHECK: %[[VAL_14:.*]] = fir.insert_value %[[VAL_13]], %[[VAL_11]], [0 : index] : (tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>, !fir.class<!fir.heap<!fir.type<t{i:i32}>>>) -> tuple<!fir.class<!fir.heap<!fir.type<t{i:i32}>>>, i1>
// CHECK: hlfir.assign %[[VAL_11]] to %{{.*}} : !fir.class<!fir.heap<!fir.type<t{i:i32}>>>, !fir.ref<!fir.type<t{i:i32}>>


func.func @as_expr_class_2(%arg0 : !fir.class<!fir.array<?x!t>>) {
%0 = hlfir.as_expr %arg0 : (!fir.class<!fir.array<?x!t>>) -> !hlfir.expr<?x!t?>
%c1 = arith.constant 1 : index
%1 = hlfir.apply %0, %c1 : (!hlfir.expr<?x!t?>, index) -> !hlfir.expr<!t?>
return
}
// CHECK-LABEL: func.func @as_expr_class_2(
// CHECK: %[[VAL_9:.*]] = arith.constant true
// CHECK: %[[VAL_10:.*]]:2 = hlfir.declare %{{.*}} {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = ".tmp"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>>)
// CHECK: %[[VAL_11:.*]] = arith.constant 1 : i32
// ... copy ...
// CHECK: %[[VAL_15:.*]] = fir.load %[[VAL_10]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>>
// CHECK: %[[VAL_16:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
// CHECK: %[[VAL_17:.*]] = fir.insert_value %[[VAL_16]], %[[VAL_9]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
// CHECK: %[[VAL_18:.*]] = fir.insert_value %[[VAL_17]], %[[VAL_15]], [0 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>, !fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, i1>
// CHECK: %[[VAL_19:.*]] = arith.constant 1 : index
// CHECK: %[[VAL_20:.*]] = hlfir.designate %[[VAL_15]] (%[[VAL_19]]) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<t{i:i32}>>>>, index) -> !fir.class<!fir.type<t{i:i32}>>
25 changes: 12 additions & 13 deletions flang/test/HLFIR/bufferize-poly-expr.fir
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ func.func @test_poly_expr_without_associate() {
// CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_4]]#1 : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> !fir.box<none>
// CHECK: %[[VAL_12:.*]] = fir.call @_FortranAAllocatableApplyMold(%[[VAL_10]], %[[VAL_11]], %[[VAL_9]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32) -> none
// CHECK: hlfir.assign %[[VAL_4]]#0 to %[[VAL_8]]#0 realloc temporary_lhs : !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
// CHECK: %[[VAL_13:.*]] = fir.undefined tuple<!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, i1>
// CHECK: %[[VAL_14:.*]] = fir.insert_value %[[VAL_13]], %[[VAL_7]], [1 : index] : (tuple<!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, i1>, i1) -> tuple<!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, i1>
// CHECK: %[[VAL_15:.*]] = fir.insert_value %[[VAL_14]], %[[VAL_8]]#0, [0 : index] : (tuple<!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, i1>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>) -> tuple<!fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, i1>
// CHECK: hlfir.assign %[[VAL_8]]#0 to %[[VAL_2]]#0 realloc : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
// CHECK: %[[VAL_16:.*]] = fir.load %[[VAL_8]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
// CHECK: %[[VAL_17:.*]] = fir.box_addr %[[VAL_16]] : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> !fir.heap<!fir.type<_QFtestTt{c:i32}>>
// CHECK: %[[VAL_8B:.*]] = fir.load %[[VAL_8]]#0
// CHECK: %[[VAL_13:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>
// CHECK: %[[VAL_14:.*]] = fir.insert_value %[[VAL_13]], %[[VAL_7]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>
// CHECK: %[[VAL_15:.*]] = fir.insert_value %[[VAL_14]], %[[VAL_8B]], [0 : index] : (tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>, !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> tuple<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, i1>
// CHECK: hlfir.assign %[[VAL_8B]] to %[[VAL_2]]#0 realloc : !fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>, !fir.ref<!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>>
// CHECK: %[[VAL_17:.*]] = fir.box_addr %[[VAL_8B]] : (!fir.class<!fir.heap<!fir.type<_QFtestTt{c:i32}>>>) -> !fir.heap<!fir.type<_QFtestTt{c:i32}>>
// CHECK: fir.freemem %[[VAL_17]] : !fir.heap<!fir.type<_QFtestTt{c:i32}>>
// CHECK: return
// CHECK: }
Expand Down Expand Up @@ -81,25 +81,24 @@ func.func @test_poly_expr_with_associate(%arg1: !fir.class<!fir.array<3x!fir.typ
// CHECK: %[[VAL_17:.*]] = fir.convert %[[VAL_5]] : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>) -> !fir.box<none>
// CHECK: %[[VAL_18:.*]] = fir.call @_FortranAAllocatableApplyMold(%[[VAL_16]], %[[VAL_17]], %[[VAL_15]]) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i32) -> none
// CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_14]]#0 realloc temporary_lhs : !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>
// CHECK: %[[VAL_19:.*]] = fir.undefined tuple<!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>, i1>
// CHECK: %[[VAL_20:.*]] = fir.insert_value %[[VAL_19]], %[[VAL_13]], [1 : index] : (tuple<!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>, i1>, i1) -> tuple<!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>, i1>
// CHECK: %[[VAL_21:.*]] = fir.insert_value %[[VAL_20]], %[[VAL_14]]#0, [0 : index] : (tuple<!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>, i1>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>) -> tuple<!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>, i1>
// CHECK: %[[VAL_14B:.*]] = fir.load %[[VAL_14]]#0
// CHECK: %[[VAL_19:.*]] = fir.undefined tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, i1>
// CHECK: %[[VAL_20:.*]] = fir.insert_value %[[VAL_19]], %[[VAL_13]], [1 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, i1>, i1) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, i1>
// CHECK: %[[VAL_21:.*]] = fir.insert_value %[[VAL_20]], %[[VAL_14B]], [0 : index] : (tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, i1>, !fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>) -> tuple<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, i1>
// CHECK: %[[VAL_22:.*]] = arith.constant 0 : index
// CHECK: %[[VAL_23:.*]]:3 = fir.box_dims %[[VAL_5]], %[[VAL_22]] : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, index) -> (index, index, index)
// CHECK: %[[VAL_24:.*]] = fir.shape %[[VAL_23]]#1 : (index) -> !fir.shape<1>
// CHECK: %[[VAL_25:.*]] = fir.load %[[VAL_14]]#0 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>
// CHECK: %[[VAL_26:.*]] = fir.load %[[VAL_14]]#1 : !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>
// CHECK: %[[VAL_27:.*]] = fir.convert %[[VAL_2]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>>) -> !fir.box<none>
// CHECK: %[[VAL_28:.*]] = fir.call @_FortranADestroy(%[[VAL_27]]) fastmath<contract> : (!fir.box<none>) -> none
// CHECK: %[[VAL_29:.*]] = arith.constant 3 : index
// CHECK: %[[VAL_30:.*]] = fir.shape %[[VAL_29]] : (index) -> !fir.shape<1>
// CHECK: %[[VAL_31:.*]] = arith.constant 1 : index
// CHECK: fir.do_loop %[[VAL_32:.*]] = %[[VAL_31]] to %[[VAL_29]] step %[[VAL_31]] {
// CHECK: %[[VAL_33:.*]] = hlfir.designate %[[VAL_3]]#0 (%[[VAL_32]]) : (!fir.class<!fir.array<3x!fir.type<_QMtest_typeTt1{i:i32}>>>, index) -> !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>
// CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_25]] (%[[VAL_32]]) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, index) -> !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>
// CHECK: %[[VAL_34:.*]] = hlfir.designate %[[VAL_14B]] (%[[VAL_32]]) : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>, index) -> !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>
// CHECK: fir.dispatch "assign"(%[[VAL_33]] : !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>) (%[[VAL_33]], %[[VAL_34]] : !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>, !fir.class<!fir.type<_QMtest_typeTt1{i:i32}>>) {pass_arg_pos = 0 : i32}
// CHECK: }
// CHECK: %[[VAL_35:.*]] = fir.box_addr %[[VAL_26]] : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>
// CHECK: %[[VAL_35:.*]] = fir.box_addr %[[VAL_14B]] : (!fir.class<!fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>>) -> !fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>
// CHECK: fir.freemem %[[VAL_35]] : !fir.heap<!fir.array<?x!fir.type<_QMtest_typeTt1{i:i32}>>>
// CHECK: return
// CHECK: }
25 changes: 20 additions & 5 deletions flang/test/Lower/HLFIR/function-return-as-expr.f90
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,26 @@ function inner()
end function inner
end subroutine test4
! CHECK-LABEL: func.func @_QPtest4() {
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = ".tmp.func_result"} : (!fir.ref<!fir.class<!fir.heap<none>>>) -> (!fir.ref<!fir.class<!fir.heap<none>>>, !fir.ref<!fir.class<!fir.heap<none>>>)
! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_6]]#0 : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[VAL_8:.*]] = arith.constant false
! CHECK: %[[VAL_9:.*]] = hlfir.as_expr %[[VAL_7]] move %[[VAL_8]] : (!fir.class<!fir.heap<none>>, i1) -> !hlfir.expr<none?>
! CHECK: hlfir.assign %[[VAL_9]] to %{{.*}}#0 realloc : !hlfir.expr<none?>, !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_0:.*]] : !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = ".tmp.func_result"} : (!fir.class<!fir.heap<none>>) -> (!fir.class<!fir.heap<none>>, !fir.class<!fir.heap<none>>)
! CHECK: hlfir.assign %[[VAL_7]]#0 to %{{.*}}#0 realloc : !fir.class<!fir.heap<none>>, !fir.ref<!fir.class<!fir.heap<none>>>
! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.class<!fir.heap<none>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranADestroy(%[[VAL_10]]) fastmath<contract> : (!fir.box<none>) -> none

subroutine test4b
class(*), allocatable :: p(:, :)
p = inner()
contains
function inner()
class(*), allocatable :: inner(:, :)
end function inner
end subroutine test4b
! CHECK-LABEL: func.func @_QPtest4b() {
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_0:.*]] : !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = ".tmp.func_result"} : (!fir.class<!fir.heap<!fir.array<?x?xnone>>>) -> (!fir.class<!fir.heap<!fir.array<?x?xnone>>>, !fir.class<!fir.heap<!fir.array<?x?xnone>>>)
! CHECK: hlfir.assign %[[VAL_7]]#0 to %{{.*}}#0 realloc : !fir.class<!fir.heap<!fir.array<?x?xnone>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>
! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_0]] : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x?xnone>>>>) -> !fir.box<none>
! CHECK: fir.call @_FortranADestroy(%[[VAL_10]]) fastmath<contract> : (!fir.box<none>) -> none

subroutine test5
use types
Expand Down
10 changes: 10 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.stdbit.stdc_leading_ones_ui
libc.src.stdbit.stdc_leading_ones_ul
libc.src.stdbit.stdc_leading_ones_ull
libc.src.stdbit.stdc_trailing_zeros_uc
libc.src.stdbit.stdc_trailing_zeros_us
libc.src.stdbit.stdc_trailing_zeros_ui
libc.src.stdbit.stdc_trailing_zeros_ul
libc.src.stdbit.stdc_trailing_zeros_ull
libc.src.stdbit.stdc_trailing_ones_uc
libc.src.stdbit.stdc_trailing_ones_us
libc.src.stdbit.stdc_trailing_ones_ui
libc.src.stdbit.stdc_trailing_ones_ul
libc.src.stdbit.stdc_trailing_ones_ull

# stdlib.h entrypoints
libc.src.stdlib.abs
Expand Down
1 change: 1 addition & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ add_gen_header(
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.imaxdiv_t
.llvm-libc-macros.inttypes_macros
)

add_gen_header(
Expand Down
1 change: 1 addition & 0 deletions libc/include/inttypes.h.def
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLVM_LIBC_INTTYPES_H

#include <__llvm-libc-common.h>
#include <llvm-libc-macros/inttypes-macros.h>
#include <stdint.h>

%%public_api()
Expand Down
6 changes: 6 additions & 0 deletions libc/include/llvm-libc-macros/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,9 @@ add_macro_header(
HDR
wchar-macros.h
)

add_macro_header(
inttypes_macros
HDR
inttypes-macros.h
)
289 changes: 289 additions & 0 deletions libc/include/llvm-libc-macros/inttypes-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
//===-- Definition of macros from inttypes.h ------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#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.

// clang provides these macros, so we don't need to define them.
// TODO: ISO C23 will provide binary notations.

#ifndef __clang__
#if __UINTPTR_MAX__ == __UINT64_MAX__
#define __PRI64 "l"
#define __PRIPTR "l"
#elif __UINTPTR_MAX__ == __UINT32_MAX__
#define __PRI64 "ll"
#define __PRIPTR ""
#else
// CHERI achitecture for example, has 128-bit pointers that use special "P"
// format.
#error "Unsupported pointer format"
#endif
#define __INT8_FMTd__ "hhd"
#define __INT16_FMTd__ "hd"
#define __INT32_FMTd__ "d"
#define __INT64_FMTd__ __PRI64 "d"
#define __INT_LEAST8_FMTd__ "hhd"
#define __INT_LEAST16_FMTd__ "hd"
#define __INT_LEAST32_FMTd__ "d"
#define __INT_LEAST64_FMTd__ __PRI64 "d"
#define __INT_FAST8_FMTd__ "hhd"
#define __INT_FAST16_FMTd__ "hd"
#define __INT_FAST32_FMTd__ "d"
#define __INT_FAST64_FMTd__ __PRI64 "d"
#define __INTMAX_FMTd__ __PRI64 "d"
#define __INTPTR_FMTd__ __PRIPTR "d"

#define __INT8_FMTi__ "hhi"
#define __INT16_FMTi__ "hi"
#define __INT32_FMTi__ "i"
#define __INT64_FMTi__ __PRI64 "i"
#define __INT_LEAST8_FMTi__ "hhi"
#define __INT_LEAST16_FMTi__ "hi"
#define __INT_LEAST32_FMTi__ "i"
#define __INT_LEAST64_FMTi__ __PRI64 "i"
#define __INT_FAST8_FMTi__ "hhi"
#define __INT_FAST16_FMTi__ "hi"
#define __INT_FAST32_FMTi__ "i"
#define __INT_FAST64_FMTi__ __PRI64 "i"
#define __INTMAX_FMTi__ __PRI64 "i"
#define __INTPTR_FMTi__ __PRIPTR "i"

#define __UINT8_FMTo__ "hho"
#define __UINT16_FMTo__ "ho"
#define __UINT32_FMTo__ "o"
#define __UINT64_FMTo__ __PRI64 "o"
#define __UINT_LEAST8_FMTo__ "hho"
#define __UINT_LEAST16_FMTo__ "ho"
#define __UINT_LEAST32_FMTo__ "o"
#define __UINT_LEAST64_FMTo__ __PRI64 "o"
#define __UINT_FAST8_FMTo__ "hho"
#define __UINT_FAST16_FMTo__ "ho"
#define __UINT_FAST32_FMTo__ "o"
#define __UINT_FAST64_FMTo__ __PRI64 "o"
#define __UINTMAX_FMTo__ __PRI64 "o"
#define __UINTPTR_FMTo__ __PRIPTR "o"

#define __UINT8_FMTu__ "hhu"
#define __UINT16_FMTu__ "hu"
#define __UINT32_FMTu__ "u"
#define __UINT64_FMTu__ __PRI64 "u"
#define __UINT_LEAST8_FMTu__ "hhu"
#define __UINT_LEAST16_FMTu__ "hu"
#define __UINT_LEAST32_FMTu__ "u"
#define __UINT_LEAST64_FMTu__ __PRI64 "u"
#define __UINT_FAST8_FMTu__ "hhu"
#define __UINT_FAST16_FMTu__ "hu"
#define __UINT_FAST32_FMTu__ "u"
#define __UINT_FAST64_FMTu__ __PRI64 "u"
#define __UINTMAX_FMTu__ __PRI64 "u"
#define __UINTPTR_FMTu__ __PRIPTR "u"

#define __UINT8_FMTx__ "hhx"
#define __UINT16_FMTx__ "hx"
#define __UINT32_FMTx__ "x"
#define __UINT64_FMTx__ __PRI64 "x"
#define __UINT_LEAST8_FMTx__ "hhx"
#define __UINT_LEAST16_FMTx__ "hx"
#define __UINT_LEAST32_FMTx__ "x"
#define __UINT_LEAST64_FMTx__ __PRI64 "x"
#define __UINT_FAST8_FMTx__ "hhx"
#define __UINT_FAST16_FMTx__ "hx"
#define __UINT_FAST32_FMTx__ "x"
#define __UINT_FAST64_FMTx__ __PRI64 "x"
#define __UINTMAX_FMTx__ __PRI64 "x"
#define __UINTPTR_FMTx__ __PRIPTR "x"

#define __UINT8_FMTX__ "hhX"
#define __UINT16_FMTX__ "hX"
#define __UINT32_FMTX__ "X"
#define __UINT64_FMTX__ __PRI64 "X"
#define __UINT_LEAST8_FMTX__ "hhX"
#define __UINT_LEAST16_FMTX__ "hX"
#define __UINT_LEAST32_FMTX__ "X"
#define __UINT_LEAST64_FMTX__ __PRI64 "X"
#define __UINT_FAST8_FMTX__ "hhX"
#define __UINT_FAST16_FMTX__ "hX"
#define __UINT_FAST32_FMTX__ "X"
#define __UINT_FAST64_FMTX__ __PRI64 "X"
#define __UINTMAX_FMTX__ __PRI64 "X"
#define __UINTPTR_FMTX__ __PRIPTR "X"
#endif

// The fprintf() macros for signed integers.
#define PRId8 __INT8_FMTd__
#define PRId16 __INT16_FMTd__
#define PRId32 __INT32_FMTd__
#define PRId64 __INT64_FMTd__
#define PRIdLEAST8 __INT_LEAST8_FMTd__
#define PRIdLEAST16 __INT_LEAST16_FMTd__
#define PRIdLEAST32 __INT_LEAST32_FMTd__
#define PRIdLEAST64 __INT_LEAST64_FMTd__
#define PRIdFAST8 __INT_FAST8_FMTd__
#define PRIdFAST16 __INT_FAST16_FMTd__
#define PRIdFAST32 __INT_FAST32_FMTd__
#define PRIdFAST64 __INT_FAST64_FMTd__
#define PRIdMAX __INTMAX_FMTd__
#define PRIdPTR __INTPTR_FMTd__

#define PRIi8 __INT8_FMTi__
#define PRIi16 __INT16_FMTi__
#define PRIi32 __INT32_FMTi__
#define PRIi64 __INT64_FMTi__
#define PRIiLEAST8 __INT_LEAST8_FMTi__
#define PRIiLEAST16 __INT_LEAST16_FMTi__
#define PRIiLEAST32 __INT_LEAST32_FMTi__
#define PRIiLEAST64 __INT_LEAST64_FMTi__
#define PRIiFAST8 __INT_FAST8_FMTi__
#define PRIiFAST16 __INT_FAST16_FMTi__
#define PRIiFAST32 __INT_FAST32_FMTi__
#define PRIiFAST64 __INT_FAST64_FMTi__
#define PRIiMAX __INTMAX_FMTi__
#define PRIiPTR __INTPTR_FMTi__

// The fprintf() macros for unsigned integers.
#define PRIo8 __UINT8_FMTo__
#define PRIo16 __UINT16_FMTo__
#define PRIo32 __UINT32_FMTo__
#define PRIo64 __UINT64_FMTo__
#define PRIoLEAST8 __UINT_LEAST8_FMTo__
#define PRIoLEAST16 __UINT_LEAST16_FMTo__
#define PRIoLEAST32 __UINT_LEAST32_FMTo__
#define PRIoLEAST64 __UINT_LEAST64_FMTo__
#define PRIoFAST8 __UINT_FAST8_FMTo__
#define PRIoFAST16 __UINT_FAST16_FMTo__
#define PRIoFAST32 __UINT_FAST32_FMTo__
#define PRIoFAST64 __UINT_FAST64_FMTo__
#define PRIoMAX __UINTMAX_FMTo__
#define PRIoPTR __UINTPTR_FMTo__

#define PRIu8 __UINT8_FMTu__
#define PRIu16 __UINT16_FMTu__
#define PRIu32 __UINT32_FMTu__
#define PRIu64 __UINT64_FMTu__
#define PRIuLEAST8 __UINT_LEAST8_FMTu__
#define PRIuLEAST16 __UINT_LEAST16_FMTu__
#define PRIuLEAST32 __UINT_LEAST32_FMTu__
#define PRIuLEAST64 __UINT_LEAST64_FMTu__
#define PRIuFAST8 __UINT_FAST8_FMTu__
#define PRIuFAST16 __UINT_FAST16_FMTu__
#define PRIuFAST32 __UINT_FAST32_FMTu__
#define PRIuFAST64 __UINT_FAST64_FMTu__
#define PRIuMAX __UINTMAX_FMTu__
#define PRIuPTR __UINTPTR_FMTu__

#define PRIx8 __UINT8_FMTx__
#define PRIx16 __UINT16_FMTx__
#define PRIx32 __UINT32_FMTx__
#define PRIx64 __UINT64_FMTx__
#define PRIxLEAST8 __UINT_LEAST8_FMTx__
#define PRIxLEAST16 __UINT_LEAST16_FMTx__
#define PRIxLEAST32 __UINT_LEAST32_FMTx__
#define PRIxLEAST64 __UINT_LEAST64_FMTx__
#define PRIxFAST8 __UINT_FAST8_FMTx__
#define PRIxFAST16 __UINT_FAST16_FMTx__
#define PRIxFAST32 __UINT_FAST32_FMTx__
#define PRIxFAST64 __UINT_FAST64_FMTx__
#define PRIxMAX __UINTMAX_FMTx__
#define PRIxPTR __UINTPTR_FMTx__

#define PRIX8 __UINT8_FMTX__
#define PRIX16 __UINT16_FMTX__
#define PRIX32 __UINT32_FMTX__
#define PRIX64 __UINT64_FMTX__
#define PRIXLEAST8 __UINT_LEAST8_FMTX__
#define PRIXLEAST16 __UINT_LEAST16_FMTX__
#define PRIXLEAST32 __UINT_LEAST32_FMTX__
#define PRIXLEAST64 __UINT_LEAST64_FMTX__
#define PRIXFAST8 __UINT_FAST8_FMTX__
#define PRIXFAST16 __UINT_FAST16_FMTX__
#define PRIXFAST32 __UINT_FAST32_FMTX__
#define PRIXFAST64 __UINT_FAST64_FMTX__
#define PRIXMAX __UINTMAX_FMTX__
#define PRIXPTR __UINTPTR_FMTX__

// The fscanf() macros for signed integers.
#define SCNd8 __INT8_FMTd__
#define SCNd16 __INT16_FMTd__
#define SCNd32 __INT32_FMTd__
#define SCNd64 __INT64_FMTd__
#define SCNdLEAST8 __INT_LEAST8_FMTd__
#define SCNdLEAST16 __INT_LEAST16_FMTd__
#define SCNdLEAST32 __INT_LEAST32_FMTd__
#define SCNdLEAST64 __INT_LEAST64_FMTd__
#define SCNdFAST8 __INT_FAST8_FMTd__
#define SCNdFAST16 __INT_FAST16_FMTd__
#define SCNdFAST32 __INT_FAST32_FMTd__
#define SCNdFAST64 __INT_FAST64_FMTd__
#define SCNdMAX __INTMAX_FMTd__
#define SCNdPTR __INTPTR_FMTd__

#define SCNi8 __INT8_FMTi__
#define SCNi16 __INT16_FMTi__
#define SCNi32 __INT32_FMTi__
#define SCNi64 __INT64_FMTi__
#define SCNiLEAST8 __INT_LEAST8_FMTi__
#define SCNiLEAST16 __INT_LEAST16_FMTi__
#define SCNiLEAST32 __INT_LEAST32_FMTi__
#define SCNiLEAST64 __INT_LEAST64_FMTi__
#define SCNiFAST8 __INT_FAST8_FMTi__
#define SCNiFAST16 __INT_FAST16_FMTi__
#define SCNiFAST32 __INT_FAST32_FMTi__
#define SCNiFAST64 __INT_FAST64_FMTi__
#define SCNiMAX __INTMAX_FMTi__
#define SCNiPTR __INTPTR_FMTi__

// The fscanf() macros for unsigned integers.
#define SCNo8 __UINT8_FMTo__
#define SCNo16 __UINT16_FMTo__
#define SCNo32 __UINT32_FMTo__
#define SCNo64 __UINT64_FMTo__
#define SCNoLEAST8 __UINT_LEAST8_FMTo__
#define SCNoLEAST16 __UINT_LEAST16_FMTo__
#define SCNoLEAST32 __UINT_LEAST32_FMTo__
#define SCNoLEAST64 __UINT_LEAST64_FMTo__
#define SCNoFAST8 __UINT_FAST8_FMTo__
#define SCNoFAST16 __UINT_FAST16_FMTo__
#define SCNoFAST32 __UINT_FAST32_FMTo__
#define SCNoFAST64 __UINT_FAST64_FMTo__
#define SCNoMAX __UINTMAX_FMTo__
#define SCNoPTR __UINTPTR_FMTo__

#define SCNu8 __UINT8_FMTu__
#define SCNu16 __UINT16_FMTu__
#define SCNu32 __UINT32_FMTu__
#define SCNu64 __UINT64_FMTu__
#define SCNuLEAST8 __UINT_LEAST8_FMTu__
#define SCNuLEAST16 __UINT_LEAST16_FMTu__
#define SCNuLEAST32 __UINT_LEAST32_FMTu__
#define SCNuLEAST64 __UINT_LEAST64_FMTu__
#define SCNuFAST8 __UINT_FAST8_FMTu__
#define SCNuFAST16 __UINT_FAST16_FMTu__
#define SCNuFAST32 __UINT_FAST32_FMTu__
#define SCNuFAST64 __UINT_FAST64_FMTu__
#define SCNuMAX __UINTMAX_FMTu__
#define SCNuPTR __UINTPTR_FMTu__

#define SCNx8 __UINT8_FMTx__
#define SCNx16 __UINT16_FMTx__
#define SCNx32 __UINT32_FMTx__
#define SCNx64 __UINT64_FMTx__
#define SCNxLEAST8 __UINT_LEAST8_FMTx__
#define SCNxLEAST16 __UINT_LEAST16_FMTx__
#define SCNxLEAST32 __UINT_LEAST32_FMTx__
#define SCNxLEAST64 __UINT_LEAST64_FMTx__
#define SCNxFAST8 __UINT_FAST8_FMTx__
#define SCNxFAST16 __UINT_FAST16_FMTx__
#define SCNxFAST32 __UINT_FAST32_FMTx__
#define SCNxFAST64 __UINT_FAST64_FMTx__
#define SCNxMAX __UINTMAX_FMTx__
#define SCNxPTR __UINTPTR_FMTx__

#endif // __LLVM_LIBC_MACROS_INTTYPES_MACROS_H
45 changes: 45 additions & 0 deletions libc/include/llvm-libc-macros/stdbit-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#ifndef __LLVM_LIBC_MACROS_STDBIT_MACROS_H
#define __LLVM_LIBC_MACROS_STDBIT_MACROS_H

// TODO(https://github.com/llvm/llvm-project/issues/80509): support _BitInt().
#ifdef __cplusplus
inline unsigned stdc_leading_zeros(unsigned char x) {
return stdc_leading_zeros_uc(x);
Expand Down Expand Up @@ -40,6 +41,36 @@ inline unsigned stdc_leading_ones(unsigned long x) {
inline unsigned stdc_leading_ones(unsigned long long x) {
return stdc_leading_ones_ull(x);
}
inline unsigned stdc_trailing_zeros(unsigned char x) {
return stdc_trailing_zeros_uc(x);
}
inline unsigned stdc_trailing_zeros(unsigned short x) {
return stdc_trailing_zeros_us(x);
}
inline unsigned stdc_trailing_zeros(unsigned x) {
return stdc_trailing_zeros_ui(x);
}
inline unsigned stdc_trailing_zeros(unsigned long x) {
return stdc_trailing_zeros_ul(x);
}
inline unsigned stdc_trailing_zeros(unsigned long long x) {
return stdc_trailing_zeros_ull(x);
}
inline unsigned stdc_trailing_ones(unsigned char x) {
return stdc_trailing_ones_uc(x);
}
inline unsigned stdc_trailing_ones(unsigned short x) {
return stdc_trailing_ones_us(x);
}
inline unsigned stdc_trailing_ones(unsigned x) {
return stdc_trailing_ones_ui(x);
}
inline unsigned stdc_trailing_ones(unsigned long x) {
return stdc_trailing_ones_ul(x);
}
inline unsigned stdc_trailing_ones(unsigned long long x) {
return stdc_trailing_ones_ull(x);
}
#else
#define stdc_leading_zeros(x) \
_Generic((x), \
Expand All @@ -55,6 +86,20 @@ inline unsigned stdc_leading_ones(unsigned long long x) {
unsigned: stdc_leading_ones_ui, \
unsigned long: stdc_leading_ones_ul, \
unsigned long long: stdc_leading_ones_ull)(x)
#define stdc_trailing_zeros(x) \
_Generic((x), \
unsigned char: stdc_trailing_zeros_uc, \
unsigned short: stdc_trailing_zeros_us, \
unsigned: stdc_trailing_zeros_ui, \
unsigned long: stdc_trailing_zeros_ul, \
unsigned long long: stdc_trailing_zeros_ull)(x)
#define stdc_trailing_ones(x) \
_Generic((x), \
unsigned char: stdc_trailing_ones_uc, \
unsigned short: stdc_trailing_ones_us, \
unsigned: stdc_trailing_ones_ui, \
unsigned long: stdc_trailing_ones_ul, \
unsigned long long: stdc_trailing_ones_ull)(x)
#endif // __cplusplus

#endif // __LLVM_LIBC_MACROS_STDBIT_MACROS_H
17 changes: 15 additions & 2 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -775,7 +775,10 @@ def StdC : StandardSpec<"stdc"> {
HeaderSpec StdBit = HeaderSpec<
"stdbit.h",
[
Macro<"stdc_leading_zeros">
Macro<"stdc_leading_zeros">,
Macro<"stdc_leading_ones">,
Macro<"stdc_trailing_zeros">,
Macro<"stdc_trailing_ones">
], // Macros
[], // Types
[], // Enumerations
Expand All @@ -789,7 +792,17 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"stdc_leading_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
FunctionSpec<"stdc_leading_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
FunctionSpec<"stdc_leading_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
FunctionSpec<"stdc_leading_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>
FunctionSpec<"stdc_leading_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
FunctionSpec<"stdc_trailing_zeros_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
FunctionSpec<"stdc_trailing_zeros_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
FunctionSpec<"stdc_trailing_zeros_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
FunctionSpec<"stdc_trailing_zeros_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
FunctionSpec<"stdc_trailing_zeros_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>,
FunctionSpec<"stdc_trailing_ones_uc", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedCharType>]>,
FunctionSpec<"stdc_trailing_ones_us", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedShortType>]>,
FunctionSpec<"stdc_trailing_ones_ui", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedIntType>]>,
FunctionSpec<"stdc_trailing_ones_ul", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongType>]>,
FunctionSpec<"stdc_trailing_ones_ull", RetValSpec<UnsignedIntType>, [ArgSpec<UnsignedLongLongType>]>
] // Functions
>;

Expand Down
6 changes: 5 additions & 1 deletion libc/src/__support/float_to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,8 @@ template <> class FloatToString<long double> {
int int_block_index = 0;

static constexpr size_t BLOCK_BUFFER_LEN =
internal::div_ceil(internal::log10_pow2(FLOAT_AS_INT_WIDTH), BLOCK_SIZE);
internal::div_ceil(internal::log10_pow2(FLOAT_AS_INT_WIDTH), BLOCK_SIZE) +
1;
BlockInt block_buffer[BLOCK_BUFFER_LEN] = {0};
size_t block_buffer_valid = 0;

Expand Down Expand Up @@ -693,6 +694,7 @@ template <> class FloatToString<long double> {
int_block_index = 0;

while (float_as_int > 0) {
LIBC_ASSERT(int_block_index < static_cast<int>(BLOCK_BUFFER_LEN));
block_buffer[int_block_index] = grab_digits(float_as_int);
++int_block_index;
}
Expand Down Expand Up @@ -785,6 +787,8 @@ template <> class FloatToString<long double> {
if (block_index > static_cast<int>(block_buffer_valid) || block_index < 0)
return 0;

LIBC_ASSERT(block_index < static_cast<int>(BLOCK_BUFFER_LEN));

return block_buffer[block_index];
}

Expand Down
2 changes: 1 addition & 1 deletion libc/src/errno/libc_errno.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ LIBC_NAMESPACE::Errno::operator int() { return errno; }

namespace LIBC_NAMESPACE {
// Define the global `libc_errno` instance.
LIBC_NAMESPACE::Errno libc_errno;
Errno libc_errno;
} // namespace LIBC_NAMESPACE
2 changes: 1 addition & 1 deletion libc/src/errno/libc_errno.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct Errno {
operator int();
};

extern LIBC_NAMESPACE::Errno libc_errno;
extern Errno libc_errno;

} // namespace LIBC_NAMESPACE

Expand Down
119 changes: 20 additions & 99 deletions libc/src/stdbit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,99 +1,20 @@
add_entrypoint_object(
stdc_leading_zeros_uc
SRCS
stdc_leading_zeros_uc.cpp
HDRS
stdc_leading_zeros_uc.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_zeros_us
SRCS
stdc_leading_zeros_us.cpp
HDRS
stdc_leading_zeros_us.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_zeros_ui
SRCS
stdc_leading_zeros_ui.cpp
HDRS
stdc_leading_zeros_ui.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_zeros_ul
SRCS
stdc_leading_zeros_ul.cpp
HDRS
stdc_leading_zeros_ul.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_zeros_ull
SRCS
stdc_leading_zeros_ull.cpp
HDRS
stdc_leading_zeros_ull.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_ones_uc
SRCS
stdc_leading_ones_uc.cpp
HDRS
stdc_leading_ones_uc.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_ones_us
SRCS
stdc_leading_ones_us.cpp
HDRS
stdc_leading_ones_us.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_ones_ui
SRCS
stdc_leading_ones_ui.cpp
HDRS
stdc_leading_ones_ui.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_ones_ul
SRCS
stdc_leading_ones_ul.cpp
HDRS
stdc_leading_ones_ul.h
DEPENDS
libc.src.__support.CPP.bit
)

add_entrypoint_object(
stdc_leading_ones_ull
SRCS
stdc_leading_ones_ull.cpp
HDRS
stdc_leading_ones_ull.h
DEPENDS
libc.src.__support.CPP.bit
)
set(prefixes
leading_zeros
leading_ones
trailing_zeros
trailing_ones
)
set(suffixes c s i l ll)
foreach(prefix IN LISTS prefixes)
foreach(suffix IN LISTS suffixes)
add_entrypoint_object(
stdc_${prefix}_u${suffix}
SRCS
stdc_${prefix}_u${suffix}.cpp
HDRS
stdc_${prefix}_u${suffix}.h
DEPENDS
libc.src.__support.CPP.bit
)
endforeach()
endforeach()
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_uc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_ones_uc ---------------------------===//
//
// 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 "src/stdbit/stdc_trailing_ones_uc.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_ones_uc, (unsigned char value)) {
return static_cast<unsigned>(cpp::countr_one(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_uc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_ones_uc --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UC_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UC_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_ones_uc(unsigned char value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UC_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ui.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_ones_ui ---------------------------===//
//
// 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 "src/stdbit/stdc_trailing_ones_ui.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_ones_ui, (unsigned value)) {
return static_cast<unsigned>(cpp::countr_one(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ui.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_ones_ui --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UI_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UI_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_ones_ui(unsigned value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UI_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ul.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_ones_ul ---------------------------===//
//
// 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 "src/stdbit/stdc_trailing_ones_ul.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_ones_ul, (unsigned long value)) {
return static_cast<unsigned>(cpp::countr_one(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ul.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_ones_ul --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UL_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UL_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_ones_ul(unsigned long value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_UL_H
21 changes: 21 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation of stdc_trailing_ones_ull --------------------------===//
//
// 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 "src/stdbit/stdc_trailing_ones_ull.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_ones_ull,
(unsigned long long value)) {
return static_cast<unsigned>(cpp::countr_one(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_ull.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_ones_ull --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_ULL_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_ULL_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_ones_ull(unsigned long long value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_ULL_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_us.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_ones_us ---------------------------===//
//
// 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 "src/stdbit/stdc_trailing_ones_us.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_ones_us, (unsigned short value)) {
return static_cast<unsigned>(cpp::countr_one(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_ones_us.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_ones_us --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_US_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_US_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_ones_us(unsigned short value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ONES_US_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_uc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_zeros_uc --------------------------===//
//
// 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 "src/stdbit/stdc_trailing_zeros_uc.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_zeros_uc, (unsigned char value)) {
return static_cast<unsigned>(cpp::countr_zero(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_uc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_zeros_uc --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UC_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UC_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_zeros_uc(unsigned char value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UC_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ui.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_zeros_ui --------------------------===//
//
// 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 "src/stdbit/stdc_trailing_zeros_ui.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_zeros_ui, (unsigned value)) {
return static_cast<unsigned>(cpp::countr_zero(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ui.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_zeros_ui --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UI_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UI_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_zeros_ui(unsigned value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UI_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ul.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_zeros_ul --------------------------===//
//
// 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 "src/stdbit/stdc_trailing_zeros_ul.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_zeros_ul, (unsigned long value)) {
return static_cast<unsigned>(cpp::countr_zero(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ul.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_zeros_ul --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UL_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UL_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_zeros_ul(unsigned long value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_UL_H
21 changes: 21 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation of stdc_trailing_zeros_ull -------------------------===//
//
// 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 "src/stdbit/stdc_trailing_zeros_ull.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_zeros_ull,
(unsigned long long value)) {
return static_cast<unsigned>(cpp::countr_zero(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_ull.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_zeros_ull -------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_ULL_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_ULL_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_zeros_ull(unsigned long long value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_ULL_H
20 changes: 20 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_us.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of stdc_trailing_zeros_us --------------------------===//
//
// 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 "src/stdbit/stdc_trailing_zeros_us.h"

#include "src/__support/CPP/bit.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(unsigned, stdc_trailing_zeros_us, (unsigned short value)) {
return static_cast<unsigned>(cpp::countr_zero(value));
}

} // namespace LIBC_NAMESPACE
18 changes: 18 additions & 0 deletions libc/src/stdbit/stdc_trailing_zeros_us.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===-- Implementation header for stdc_trailing_zeros_us --------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_US_H
#define LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_US_H

namespace LIBC_NAMESPACE {

unsigned stdc_trailing_zeros_us(unsigned short value);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_STDBIT_STDC_TRAILING_ZEROS_US_H
2 changes: 2 additions & 0 deletions libc/src/unistd/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ add_entrypoint_object(
libc.include.unistd
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.macros.sanitizer
libc.src.errno.errno
)

Expand All @@ -309,6 +310,7 @@ add_entrypoint_object(
libc.include.unistd
libc.include.sys_syscall
libc.src.__support.OSUtil.osutil
libc.src.__support.macros.sanitizer
libc.src.errno.errno
)

Expand Down
5 changes: 4 additions & 1 deletion libc/src/unistd/linux/pread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"

#include "src/__support/macros/sanitizer.h" // for MSAN_UNPOISON
#include "src/errno/libc_errno.h"
#include <stdint.h> // For uint64_t.
#include <sys/syscall.h> // For syscall numbers.
Expand All @@ -28,6 +28,9 @@ LLVM_LIBC_FUNCTION(ssize_t, pread,
ssize_t ret = LIBC_NAMESPACE::syscall_impl<ssize_t>(SYS_pread64, fd, buf,
count, offset);
#endif
// The cast is important since there is a check that dereferences the pointer
// which fails on void*.
MSAN_UNPOISON(reinterpret_cast<char *>(buf), count);
if (ret < 0) {
libc_errno = static_cast<int>(-ret);
return -1;
Expand Down
26 changes: 26 additions & 0 deletions libc/test/include/stdbit_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ unsigned stdc_leading_ones_us(unsigned short) noexcept { return 0xBBU; }
unsigned stdc_leading_ones_ui(unsigned) noexcept { return 0xBCU; }
unsigned stdc_leading_ones_ul(unsigned long) noexcept { return 0xBDU; }
unsigned stdc_leading_ones_ull(unsigned long long) noexcept { return 0xBFU; }
unsigned stdc_trailing_zeros_uc(unsigned char) noexcept { return 0xCAU; }
unsigned stdc_trailing_zeros_us(unsigned short) noexcept { return 0xCBU; }
unsigned stdc_trailing_zeros_ui(unsigned) noexcept { return 0xCCU; }
unsigned stdc_trailing_zeros_ul(unsigned long) noexcept { return 0xCDU; }
unsigned stdc_trailing_zeros_ull(unsigned long long) noexcept { return 0xCFU; }
unsigned stdc_trailing_ones_uc(unsigned char) noexcept { return 0xDAU; }
unsigned stdc_trailing_ones_us(unsigned short) noexcept { return 0xDBU; }
unsigned stdc_trailing_ones_ui(unsigned) noexcept { return 0xDCU; }
unsigned stdc_trailing_ones_ul(unsigned long) noexcept { return 0xDDU; }
unsigned stdc_trailing_ones_ull(unsigned long long) noexcept { return 0xDFU; }
}

#include "include/llvm-libc-macros/stdbit-macros.h"
Expand All @@ -52,3 +62,19 @@ TEST(LlvmLibcStdbitTest, TypeGenericMacroLeadingOnes) {
EXPECT_EQ(stdc_leading_ones(0UL), 0xBDU);
EXPECT_EQ(stdc_leading_ones(0ULL), 0xBFU);
}

TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingZeros) {
EXPECT_EQ(stdc_trailing_zeros(static_cast<unsigned char>(0U)), 0xCAU);
EXPECT_EQ(stdc_trailing_zeros(static_cast<unsigned short>(0U)), 0xCBU);
EXPECT_EQ(stdc_trailing_zeros(0U), 0xCCU);
EXPECT_EQ(stdc_trailing_zeros(0UL), 0xCDU);
EXPECT_EQ(stdc_trailing_zeros(0ULL), 0xCFU);
}

TEST(LlvmLibcStdbitTest, TypeGenericMacroTrailingOnes) {
EXPECT_EQ(stdc_trailing_ones(static_cast<unsigned char>(0U)), 0xDAU);
EXPECT_EQ(stdc_trailing_ones(static_cast<unsigned short>(0U)), 0xDBU);
EXPECT_EQ(stdc_trailing_ones(0U), 0xDCU);
EXPECT_EQ(stdc_trailing_ones(0UL), 0xDDU);
EXPECT_EQ(stdc_trailing_ones(0ULL), 0xDFU);
}
131 changes: 21 additions & 110 deletions libc/test/src/stdbit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,112 +1,23 @@
add_custom_target(libc-stdbit-tests)

add_libc_test(
stdc_leading_zeros_uc_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_zeros_uc_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_zeros_uc
)

add_libc_test(
stdc_leading_zeros_us_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_zeros_us_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_zeros_us
)

add_libc_test(
stdc_leading_zeros_ui_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_zeros_ui_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_zeros_ui
)

add_libc_test(
stdc_leading_zeros_ul_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_zeros_ul_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_zeros_ul
)

add_libc_test(
stdc_leading_zeros_ull_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_zeros_ull_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_zeros_ull
)

add_libc_test(
stdc_leading_ones_uc_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_ones_uc_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_ones_uc
)

add_libc_test(
stdc_leading_ones_us_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_ones_us_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_ones_us
)

add_libc_test(
stdc_leading_ones_ui_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_ones_ui_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_ones_ui
)

add_libc_test(
stdc_leading_ones_ul_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_ones_ul_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_ones_ul
)

add_libc_test(
stdc_leading_ones_ull_test
SUITE
libc-stdbit-tests
SRCS
stdc_leading_ones_ull_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_leading_ones_ull
)

set(prefixes
leading_zeros
leading_ones
trailing_zeros
trailing_ones
)
set(suffixes c s i l ll)
foreach(prefix IN LISTS prefixes)
foreach(suffix IN LISTS suffixes)
add_libc_test(
stdc_${prefix}_u${suffix}_test
SUITE
libc-stdbit-tests
SRCS
stdc_${prefix}_u${suffix}_test.cpp
DEPENDS
libc.src.__support.CPP.limits
libc.src.stdbit.stdc_${prefix}_u${suffix}
)
endforeach()
endforeach()
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_ones_uc_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_ones_uc -------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_ones_uc.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingOnesUcTest, ALL) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_uc(UCHAR_MAX),
static_cast<unsigned>(UCHAR_WIDTH));
}

TEST(LlvmLibcStdcTrailingOnesUcTest, ZeroHot) {
for (unsigned i = 0U; i != UCHAR_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_uc(~(1U << i)), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_ones_ui_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_ones_ui -------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_ones_ui.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingOnesUiTest, ALL) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ui(UINT_MAX),
static_cast<unsigned>(UINT_WIDTH));
}

TEST(LlvmLibcStdcTrailingOnesUiTest, ZeroHot) {
for (unsigned i = 0U; i != UINT_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ui(~(1U << i)), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_ones_ul_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_ones_ul -------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_ones_ul.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingOnesUlTest, ALL) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ul(ULONG_MAX),
static_cast<unsigned>(ULONG_WIDTH));
}

TEST(LlvmLibcStdcTrailingOnesUlTest, ZeroHot) {
for (unsigned i = 0U; i != ULONG_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ul(~(1UL << i)), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_ones_ull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_ones_ull ------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_ones_ull.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingOnesUllTest, ALL) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ull(ULLONG_MAX),
static_cast<unsigned>(ULLONG_WIDTH));
}

TEST(LlvmLibcStdcTrailingOnesUllTest, ZeroHot) {
for (unsigned i = 0U; i != ULLONG_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_ull(~(1ULL << i)), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_ones_us_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_ones_us -------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_ones_us.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingOnesUsTest, ALL) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_us(USHRT_MAX),
static_cast<unsigned>(USHRT_WIDTH));
}

TEST(LlvmLibcStdcTrailingOnesUsTest, ZeroHot) {
for (unsigned i = 0U; i != USHRT_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_ones_us(~(1U << i)), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_zeros_uc_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_zeros_uc ------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_zeros_uc.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingZerosUcTest, Zero) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_uc(0U),
static_cast<unsigned>(UCHAR_WIDTH));
}

TEST(LlvmLibcStdcTrailingZerosUcTest, OneHot) {
for (unsigned i = 0U; i != UCHAR_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_uc(1U << i), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_zeros_ui_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_zeros_ui ------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_zeros_ui.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingZerosUiTest, Zero) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ui(0U),
static_cast<unsigned>(UINT_WIDTH));
}

TEST(LlvmLibcStdcTrailingZerosUiTest, OneHot) {
for (unsigned i = 0U; i != UINT_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ui(1U << i), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_zeros_ul_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_zeros_ul ------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_zeros_ul.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingZerosUlTest, Zero) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ul(0U),
static_cast<unsigned>(ULONG_WIDTH));
}

TEST(LlvmLibcStdcTrailingZerosUlTest, OneHot) {
for (unsigned i = 0U; i != ULONG_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ul(1UL << i), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_zeros_ull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_zeros_ull -----------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_zeros_ull.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingZerosUllTest, Zero) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ull(0U),
static_cast<unsigned>(ULLONG_WIDTH));
}

TEST(LlvmLibcStdcTrailingZerosUllTest, OneHot) {
for (unsigned i = 0U; i != ULLONG_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_ull(1ULL << i), i);
}
21 changes: 21 additions & 0 deletions libc/test/src/stdbit/stdc_trailing_zeros_us_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Unittests for stdc_trailing_zeros_us ------------------------------===//
//
// 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 "src/__support/CPP/limits.h"
#include "src/stdbit/stdc_trailing_zeros_us.h"
#include "test/UnitTest/Test.h"

TEST(LlvmLibcStdcTrailingZerosUsTest, Zero) {
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_us(0U),
static_cast<unsigned>(USHRT_WIDTH));
}

TEST(LlvmLibcStdcTrailingZerosUsTest, OneHot) {
for (unsigned i = 0U; i != USHRT_WIDTH; ++i)
EXPECT_EQ(LIBC_NAMESPACE::stdc_trailing_zeros_us(1U << i), i);
}
1 change: 1 addition & 0 deletions libc/test/src/stdio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ add_fp_unittest(
DEPENDS
libc.src.stdio.sprintf
libc.src.__support.FPUtil.fp_bits
libc.include.inttypes
COMPILE_OPTIONS
${sprintf_test_copts}
)
Expand Down
20 changes: 20 additions & 0 deletions libc/test/src/stdio/sprintf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "src/__support/FPUtil/FPBits.h"
#include "test/UnitTest/RoundingModeUtils.h"
#include "test/UnitTest/Test.h"
#include <inttypes.h>

// TODO: Add a comment here explaining the printf format string.

Expand All @@ -33,6 +34,25 @@ using LIBC_NAMESPACE::fputil::testing::RoundingMode;
EXPECT_EQ(actual_written, static_cast<int>(sizeof(expected_str) - 1)); \
EXPECT_STREQ(actual_str, expected_str);

#define macro_test(FMT, X, expected) \
do { \
for (char &c : buff) { \
c = 0; \
} \
LIBC_NAMESPACE::sprintf(buff, "%" FMT, X); \
ASSERT_STREQ(buff, expected); \
} while (0)

TEST(LlvmLibcSPrintfTest, Macros) {
char buff[128];
macro_test(PRIu8, 1, "1");
macro_test(PRIX16, 0xAA, "AA");
macro_test(PRId32, -123, "-123");
macro_test(PRIX32, 0xFFFFFF85, "FFFFFF85");
macro_test(PRIo8, 0xFF, "377");
macro_test(PRIo64, 0123, "123");
}

TEST(LlvmLibcSPrintfTest, SimpleNoConv) {
char buff[64];
int written;
Expand Down
6 changes: 6 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,12 @@
// clang-format on

# ifndef _LIBCPP_HARDENING_MODE

# ifndef _LIBCPP_HARDENING_MODE_DEFAULT
# error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \
`__config_site` header, please make sure your installation of libc++ is not broken.
# endif

# define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT
# endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class small_iter_allocator {
public:
using value_type = T;
using pointer = small_pointer<T>;
using size_type = std::int16_t;
using size_type = std::uint16_t;
using difference_type = std::int16_t;

small_iter_allocator() TEST_NOEXCEPT {}
Expand All @@ -37,49 +37,77 @@ class small_iter_allocator {
friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; }
};

template <class T>
class final_small_iter_allocator final {
public:
using value_type = T;
using pointer = small_pointer<T>;
using size_type = std::uint16_t;
using difference_type = std::int16_t;

final_small_iter_allocator() TEST_NOEXCEPT {}

template <class U>
final_small_iter_allocator(final_small_iter_allocator<U>) TEST_NOEXCEPT {}

T* allocate(std::size_t n);
void deallocate(T* p, std::size_t);

friend bool operator==(final_small_iter_allocator, final_small_iter_allocator) { return true; }
friend bool operator!=(final_small_iter_allocator, final_small_iter_allocator) { return false; }
};

#if __SIZE_WIDTH__ == 64

static_assert(sizeof(std::deque<int>) == 48, "");
static_assert(sizeof(std::deque<int, min_allocator<int> >) == 48, "");
static_assert(sizeof(std::deque<int, test_allocator<int> >) == 80, "");
static_assert(sizeof(std::deque<int, small_iter_allocator<int> >) == 12, "");
static_assert(sizeof(std::deque<int, final_small_iter_allocator<int> >) == 16, "");

static_assert(sizeof(std::deque<char>) == 48, "");
static_assert(sizeof(std::deque<char, min_allocator<char> >) == 48, "");
static_assert(sizeof(std::deque<char, test_allocator<char> >) == 80, "");
static_assert(sizeof(std::deque<char, small_iter_allocator<char> >) == 12, "");
static_assert(sizeof(std::deque<char, final_small_iter_allocator<char> >) == 16, "");

static_assert(TEST_ALIGNOF(std::deque<int>) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<int, min_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<int, test_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<int, small_iter_allocator<int> >) == 2, "");
static_assert(TEST_ALIGNOF(std::deque<int, final_small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::deque<char>) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<char, min_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<char, test_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::deque<char, small_iter_allocator<char> >) == 2, "");
static_assert(TEST_ALIGNOF(std::deque<char, final_small_iter_allocator<char> >) == 2, "");

#elif __SIZE_WIDTH__ == 32

static_assert(sizeof(std::deque<int>) == 24, "");
static_assert(sizeof(std::deque<int, min_allocator<int> >) == 24, "");
static_assert(sizeof(std::deque<int, test_allocator<int> >) == 48, "");
static_assert(sizeof(std::deque<int, small_iter_allocator<int> >) == 12, "");
static_assert(sizeof(std::deque<int, final_small_iter_allocator<int> >) == 16, "");

static_assert(sizeof(std::deque<char>) == 24, "");
static_assert(sizeof(std::deque<char, min_allocator<char> >) == 24, "");
static_assert(sizeof(std::deque<char, test_allocator<char> >) == 48, "");
static_assert(sizeof(std::deque<char, small_iter_allocator<char> >) == 12, "");
static_assert(sizeof(std::deque<char, final_small_iter_allocator<char> >) == 16, "");

static_assert(TEST_ALIGNOF(std::deque<int>) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<int, min_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<int, test_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<int, small_iter_allocator<int> >) == 2, "");
static_assert(TEST_ALIGNOF(std::deque<int, final_small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::deque<char>) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<char, min_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<char, test_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::deque<char, small_iter_allocator<char> >) == 2, "");
static_assert(TEST_ALIGNOF(std::deque<char, final_small_iter_allocator<char> >) == 2, "");

#else
# error std::size_t has an unexpected size
Expand Down
86 changes: 86 additions & 0 deletions libcxx/test/libcxx/containers/sequences/list/abi.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//===----------------------------------------------------------------------===//
//
// 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 <list>

#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"

template <class T>
class small_pointer {
std::uint16_t offset;
};

template <class T>
class small_iter_allocator {
public:
using value_type = T;
using pointer = small_pointer<T>;
using size_type = std::int16_t;
using difference_type = std::int16_t;

small_iter_allocator() TEST_NOEXCEPT {}

template <class U>
small_iter_allocator(small_iter_allocator<U>) TEST_NOEXCEPT {}

T* allocate(std::size_t n);
void deallocate(T* p, std::size_t);

friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; }
friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; }
};

#if __SIZE_WIDTH__ == 64

static_assert(sizeof(std::list<int>) == 24, "");
static_assert(sizeof(std::list<int, min_allocator<int> >) == 24, "");
static_assert(sizeof(std::list<int, test_allocator<int> >) == 40, "");
static_assert(sizeof(std::list<int, small_iter_allocator<int> >) == 6, "");

static_assert(sizeof(std::list<char>) == 24, "");
static_assert(sizeof(std::list<char, min_allocator<char> >) == 24, "");
static_assert(sizeof(std::list<char, test_allocator<char> >) == 40, "");
static_assert(sizeof(std::list<char, small_iter_allocator<char> >) == 6, "");

static_assert(TEST_ALIGNOF(std::list<int>) == 8, "");
static_assert(TEST_ALIGNOF(std::list<int, min_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::list<int, test_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::list<int, small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::list<char>) == 8, "");
static_assert(TEST_ALIGNOF(std::list<char, min_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::list<char, test_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::list<char, small_iter_allocator<char> >) == 2, "");

#elif __SIZE_WIDTH__ == 32

static_assert(sizeof(std::list<int>) == 12, "");
static_assert(sizeof(std::list<int, min_allocator<int> >) == 12, "");
static_assert(sizeof(std::list<int, test_allocator<int> >) == 24, "");
static_assert(sizeof(std::list<int, small_iter_allocator<int> >) == 6, "");

static_assert(sizeof(std::list<char>) == 12, "");
static_assert(sizeof(std::list<char, min_allocator<char> >) == 12, "");
static_assert(sizeof(std::list<char, test_allocator<char> >) == 24, "");
static_assert(sizeof(std::list<char, small_iter_allocator<char> >) == 6, "");

static_assert(TEST_ALIGNOF(std::list<int>) == 4, "");
static_assert(TEST_ALIGNOF(std::list<int, min_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::list<int, test_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::list<int, small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::list<char>) == 4, "");
static_assert(TEST_ALIGNOF(std::list<char, min_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::list<char, test_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::list<char, small_iter_allocator<char> >) == 2, "");

#else
# error std::size_t has an unexpected size
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===----------------------------------------------------------------------===//
//
// 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 <vector>

#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"

template <class T>
class small_pointer {
std::uint16_t offset;
};

template <class T>
class small_iter_allocator {
public:
using value_type = T;
using pointer = small_pointer<T>;
using size_type = std::int16_t;
using difference_type = std::int16_t;

small_iter_allocator() TEST_NOEXCEPT {}

template <class U>
small_iter_allocator(small_iter_allocator<U>) TEST_NOEXCEPT {}

T* allocate(std::size_t n);
void deallocate(T* p, std::size_t);

friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; }
friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; }
};

#if __SIZE_WIDTH__ == 64

static_assert(sizeof(std::vector<bool>) == 24, "");
static_assert(sizeof(std::vector<bool, min_allocator<bool> >) == 24, "");
static_assert(sizeof(std::vector<bool, test_allocator<bool> >) == 40, "");
static_assert(sizeof(std::vector<bool, small_iter_allocator<bool> >) == 6, "");

static_assert(TEST_ALIGNOF(std::vector<bool>) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<bool, min_allocator<bool> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<bool, test_allocator<bool> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<bool, small_iter_allocator<bool> >) == 2, "");

#elif __SIZE_WIDTH__ == 32

static_assert(sizeof(std::vector<bool>) == 12, "");
static_assert(sizeof(std::vector<bool, min_allocator<bool> >) == 12, "");
static_assert(sizeof(std::vector<bool, test_allocator<bool> >) == 24, "");
static_assert(sizeof(std::vector<bool, small_iter_allocator<bool> >) == 6, "");

static_assert(TEST_ALIGNOF(std::vector<bool>) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<bool, min_allocator<bool> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<bool, test_allocator<bool> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<bool, small_iter_allocator<bool> >) == 2, "");

#else
# error std::size_t has an unexpected size
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//===----------------------------------------------------------------------===//
//
// 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 <vector>

#include "min_allocator.h"
#include "test_allocator.h"
#include "test_macros.h"

template <class T>
class small_pointer {
std::uint16_t offset;
};

template <class T>
class small_iter_allocator {
public:
using value_type = T;
using pointer = small_pointer<T>;
using size_type = std::int16_t;
using difference_type = std::int16_t;

small_iter_allocator() TEST_NOEXCEPT {}

template <class U>
small_iter_allocator(small_iter_allocator<U>) TEST_NOEXCEPT {}

T* allocate(std::size_t n);
void deallocate(T* p, std::size_t);

friend bool operator==(small_iter_allocator, small_iter_allocator) { return true; }
friend bool operator!=(small_iter_allocator, small_iter_allocator) { return false; }
};

#if __SIZE_WIDTH__ == 64

static_assert(sizeof(std::vector<int>) == 24, "");
static_assert(sizeof(std::vector<int, min_allocator<int> >) == 24, "");
static_assert(sizeof(std::vector<int, test_allocator<int> >) == 40, "");
static_assert(sizeof(std::vector<int, small_iter_allocator<int> >) == 6, "");

static_assert(sizeof(std::vector<char>) == 24, "");
static_assert(sizeof(std::vector<char, min_allocator<char> >) == 24, "");
static_assert(sizeof(std::vector<char, test_allocator<char> >) == 40, "");
static_assert(sizeof(std::vector<char, small_iter_allocator<char> >) == 6, "");

static_assert(TEST_ALIGNOF(std::vector<int>) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<int, min_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<int, test_allocator<int> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<int, small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::vector<char>) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<char, min_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<char, test_allocator<char> >) == 8, "");
static_assert(TEST_ALIGNOF(std::vector<char, small_iter_allocator<char> >) == 2, "");

#elif __SIZE_WIDTH__ == 32

static_assert(sizeof(std::vector<int>) == 12, "");
static_assert(sizeof(std::vector<int, min_allocator<int> >) == 12, "");
static_assert(sizeof(std::vector<int, test_allocator<int> >) == 24, "");
static_assert(sizeof(std::vector<int, small_iter_allocator<int> >) == 6, "");

static_assert(sizeof(std::vector<char>) == 12, "");
static_assert(sizeof(std::vector<char, min_allocator<char> >) == 12, "");
static_assert(sizeof(std::vector<char, test_allocator<char> >) == 24, "");
static_assert(sizeof(std::vector<char, small_iter_allocator<char> >) == 6, "");

static_assert(TEST_ALIGNOF(std::vector<int>) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<int, min_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<int, test_allocator<int> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<int, small_iter_allocator<int> >) == 2, "");

static_assert(TEST_ALIGNOF(std::vector<char>) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<char, min_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<char, test_allocator<char> >) == 4, "");
static_assert(TEST_ALIGNOF(std::vector<char, small_iter_allocator<char> >) == 2, "");

#else
# error std::size_t has an unexpected size
#endif
1 change: 1 addition & 0 deletions lldb/bindings/headers.swig
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "lldb/API/SBScriptObject.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStatisticsOptions.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
Expand Down
8 changes: 8 additions & 0 deletions lldb/bindings/interface/SBStatisticsOptionsDocstrings.i
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
%feature("docstring",
"A container for options to use when dumping statistics."
) lldb::SBStatisticsOptions;

%feature("docstring", "Sets whether the statistics should only dump a summary."
) lldb::SBStatisticsOptions::SetSummaryOnly;
%feature("docstring", "Gets whether the statistics only dump a summary."
) lldb::SBStatisticsOptions::GetSummaryOnly;
2 changes: 2 additions & 0 deletions lldb/bindings/interfaces.swig
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
%include "./interface/SBReproducerDocstrings.i"
%include "./interface/SBSectionDocstrings.i"
%include "./interface/SBSourceManagerDocstrings.i"
%include "./interface/SBStatisticsOptionsDocstrings.i"
%include "./interface/SBStreamDocstrings.i"
%include "./interface/SBStringListDocstrings.i"
%include "./interface/SBStructuredDataDocstrings.i"
Expand Down Expand Up @@ -131,6 +132,7 @@
%include "lldb/API/SBScriptObject.h"
%include "lldb/API/SBSection.h"
%include "lldb/API/SBSourceManager.h"
%include "lldb/API/SBStatisticsOptions.h"
%include "lldb/API/SBStream.h"
%include "lldb/API/SBStringList.h"
%include "lldb/API/SBStructuredData.h"
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/API/LLDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include "lldb/API/SBReproducer.h"
#include "lldb/API/SBSection.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStatisticsOptions.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/API/SBDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class LLDB_API SBReproducer;
class LLDB_API SBScriptObject;
class LLDB_API SBSection;
class LLDB_API SBSourceManager;
class LLDB_API SBStatisticsOptions;
class LLDB_API SBStream;
class LLDB_API SBStringList;
class LLDB_API SBStructuredData;
Expand Down
36 changes: 36 additions & 0 deletions lldb/include/lldb/API/SBStatisticsOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- SBStatisticsOptions.h -----------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_API_SBSTATISTICSOPTIONS_H
#define LLDB_API_SBSTATISTICSOPTIONS_H

#include "lldb/API/SBDefines.h"

namespace lldb {

/// This class handles the verbosity when dumping statistics
class LLDB_API SBStatisticsOptions {
public:
SBStatisticsOptions();
SBStatisticsOptions(const lldb::SBStatisticsOptions &rhs);
~SBStatisticsOptions();

const SBStatisticsOptions &operator=(const lldb::SBStatisticsOptions &rhs);

void SetSummaryOnly(bool b);
bool GetSummaryOnly();

protected:
friend class SBTarget;
const lldb_private::StatisticsOptions &ref() const;

private:
std::unique_ptr<lldb_private::StatisticsOptions> m_opaque_up;
};
} // namespace lldb
#endif // LLDB_API_SBSTATISTICSOPTIONS_H
10 changes: 10 additions & 0 deletions lldb/include/lldb/API/SBTarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFileSpecList.h"
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBStatisticsOptions.h"
#include "lldb/API/SBSymbolContextList.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBValue.h"
Expand Down Expand Up @@ -90,6 +91,15 @@ class LLDB_API SBTarget {
/// A SBStructuredData with the statistics collected.
lldb::SBStructuredData GetStatistics();

/// Returns a dump of the collected statistics.
///
/// \param[in] options
/// An objects object that contains all options for the statistics dumping.
///
/// \return
/// A SBStructuredData with the statistics collected.
lldb::SBStructuredData GetStatistics(SBStatisticsOptions options);

/// Return the platform object associated with the target.
///
/// After return, the platform object should be checked for
Expand Down
Loading