45 changes: 23 additions & 22 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1431,8 +1431,8 @@ struct EmboxCommonConversion : public fir::FIROpConversion<OP> {
fir::unwrapPassByRefType(memref.getType()))))
TODO(xbox.getLoc(),
"fir.embox codegen dynamic size component in derived type");
indices.append(operands.begin() + xbox.subcomponentOffset(),
operands.begin() + xbox.subcomponentOffset() +
indices.append(operands.begin() + xbox.getSubcomponentOperandIndex(),
operands.begin() + xbox.getSubcomponentOperandIndex() +
xbox.getSubcomponent().size());
}

Expand Down Expand Up @@ -1487,7 +1487,7 @@ struct EmboxOpConversion : public EmboxCommonConversion<fir::EmboxOp> {
mlir::Value sourceBox;
mlir::Type sourceBoxType;
if (embox.getSourceBox()) {
sourceBox = operands[embox.getSourceBoxOffset()];
sourceBox = operands[embox.getSourceBoxOperandIndex()];
sourceBoxType = embox.getSourceBox().getType();
}
assert(!embox.getShape() && "There should be no dims on this embox op");
Expand Down Expand Up @@ -1519,7 +1519,7 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
mlir::Value sourceBox;
mlir::Type sourceBoxType;
if (xbox.getSourceBox()) {
sourceBox = operands[xbox.getSourceBoxOffset()];
sourceBox = operands[xbox.getSourceBoxOperandIndex()];
sourceBoxType = xbox.getSourceBox().getType();
}
auto [boxTy, dest, resultEleSize] = consDescriptorPrefix(
Expand All @@ -1529,11 +1529,11 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
// Generate the triples in the dims field of the descriptor
auto i64Ty = mlir::IntegerType::get(xbox.getContext(), 64);
assert(!xbox.getShape().empty() && "must have a shape");
unsigned shapeOffset = xbox.shapeOffset();
unsigned shapeOffset = xbox.getShapeOperandIndex();
bool hasShift = !xbox.getShift().empty();
unsigned shiftOffset = xbox.shiftOffset();
unsigned shiftOffset = xbox.getShiftOperandIndex();
bool hasSlice = !xbox.getSlice().empty();
unsigned sliceOffset = xbox.sliceOffset();
unsigned sliceOffset = xbox.getSliceOperandIndex();
mlir::Location loc = xbox.getLoc();
mlir::Value zero = genConstantIndex(loc, i64Ty, rewriter, 0);
mlir::Value one = genConstantIndex(loc, i64Ty, rewriter, 1);
Expand Down Expand Up @@ -1682,7 +1682,7 @@ struct XEmboxOpConversion : public EmboxCommonConversion<fir::cg::XEmboxOp> {
if (hasSubcomp)
getSubcomponentIndices(xbox, xbox.getMemref(), operands, fieldIndices);
if (hasSubstr)
substringOffset = operands[xbox.substrOffset()];
substringOffset = operands[xbox.getSubstrOperandIndex()];
mlir::Type llvmBaseType =
convertType(fir::unwrapRefType(xbox.getMemref().getType()));
base = genBoxOffsetGep(rewriter, loc, base, llvmBaseType, ptrOffset,
Expand Down Expand Up @@ -1843,7 +1843,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
if (!rebox.getSubcomponent().empty())
getSubcomponentIndices(rebox, rebox.getBox(), operands, fieldIndices);
if (!rebox.getSubstr().empty())
substringOffset = operands[rebox.substrOffset()];
substringOffset = operands[rebox.getSubstrOperandIndex()];
base = genBoxOffsetGep(rewriter, loc, base, llvmBaseObjectType, zero,
/*cstInteriorIndices=*/std::nullopt, fieldIndices,
substringOffset);
Expand All @@ -1862,8 +1862,8 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
llvm::SmallVector<mlir::Value> slicedStrides;
mlir::Value one = genConstantIndex(loc, idxTy, rewriter, 1);
const bool sliceHasOrigins = !rebox.getShift().empty();
unsigned sliceOps = rebox.sliceOffset();
unsigned shiftOps = rebox.shiftOffset();
unsigned sliceOps = rebox.getSliceOperandIndex();
unsigned shiftOps = rebox.getShiftOperandIndex();
auto strideOps = inputStrides.begin();
const unsigned inputRank = inputStrides.size();
for (unsigned i = 0; i < inputRank;
Expand Down Expand Up @@ -1912,9 +1912,10 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
mlir::Value base, mlir::ValueRange inputExtents,
mlir::ValueRange inputStrides, mlir::ValueRange operands,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::ValueRange reboxShifts{operands.begin() + rebox.shiftOffset(),
operands.begin() + rebox.shiftOffset() +
rebox.getShift().size()};
mlir::ValueRange reboxShifts{
operands.begin() + rebox.getShiftOperandIndex(),
operands.begin() + rebox.getShiftOperandIndex() +
rebox.getShift().size()};
if (rebox.getShape().empty()) {
// Only setting new lower bounds.
return finalizeRebox(rebox, destBoxTy, dest, base, reboxShifts,
Expand All @@ -1934,7 +1935,7 @@ struct XReboxOpConversion : public EmboxCommonConversion<fir::cg::XReboxOp> {
? genConstantIndex(loc, idxTy, rewriter, 1)
: inputStrides[0];
for (unsigned i = 0; i < rebox.getShape().size(); ++i) {
mlir::Value rawExtent = operands[rebox.shapeOffset() + i];
mlir::Value rawExtent = operands[rebox.getShapeOperandIndex() + i];
mlir::Value extent = integerCast(loc, rewriter, idxTy, rawExtent);
newExtents.emplace_back(extent);
newStrides.emplace_back(stride);
Expand Down Expand Up @@ -2137,10 +2138,10 @@ struct XArrayCoorOpConversion
assert(coor.getShift().empty() || coor.getShift().size() == rank);
assert(coor.getSlice().empty() || coor.getSlice().size() == 3 * rank);
mlir::Type idxTy = lowerTy().indexType();
unsigned indexOffset = coor.indicesOffset();
unsigned shapeOffset = coor.shapeOffset();
unsigned shiftOffset = coor.shiftOffset();
unsigned sliceOffset = coor.sliceOffset();
unsigned indexOffset = coor.getIndicesOperandIndex();
unsigned shapeOffset = coor.getShapeOperandIndex();
unsigned shiftOffset = coor.getShiftOperandIndex();
unsigned sliceOffset = coor.getSliceOperandIndex();
auto sliceOps = coor.getSlice().begin();
mlir::Value one = genConstantIndex(loc, idxTy, rewriter, 1);
mlir::Value prevExt = one;
Expand Down Expand Up @@ -2238,7 +2239,7 @@ struct XArrayCoorOpConversion
}
llvm::SmallVector<mlir::Value> indices = convertSubcomponentIndices(
loc, elementType,
operands.slice(coor.subcomponentOffset(),
operands.slice(coor.getSubcomponentOperandIndex(),
coor.getSubcomponent().size()));
args.append(indices.begin(), indices.end());
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(coor, llvmPtrTy,
Expand All @@ -2262,7 +2263,7 @@ struct XArrayCoorOpConversion
if (fir::characterWithDynamicLen(eleTy)) {
assert(coor.getLenParams().size() == 1);
auto length = integerCast(loc, rewriter, idxTy,
operands[coor.lenParamsOffset()]);
operands[coor.getLenParamsOperandIndex()]);
offset = rewriter.create<mlir::LLVM::MulOp>(loc, idxTy, offset,
length, nsw);
} else {
Expand All @@ -2275,7 +2276,7 @@ struct XArrayCoorOpConversion
args.push_back(offset);
llvm::SmallVector<mlir::Value> indices = convertSubcomponentIndices(
loc, gepObjectType,
operands.slice(coor.subcomponentOffset(),
operands.slice(coor.getSubcomponentOperandIndex(),
coor.getSubcomponent().size()));
args.append(indices.begin(), indices.end());
}
Expand Down
181 changes: 106 additions & 75 deletions flang/lib/Optimizer/Transforms/AddDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ class AddDebugInfoPass : public fir::impl::AddDebugInfoBase<AddDebugInfoPass> {
void handleGlobalOp(fir::GlobalOp glocalOp, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DIScopeAttr scope,
mlir::SymbolTable *symbolTable);
void handleFuncOp(mlir::func::FuncOp funcOp, mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DICompileUnitAttr cuAttr,
mlir::SymbolTable *symbolTable);
};

static uint32_t getLineFromLoc(mlir::Location loc) {
Expand Down Expand Up @@ -207,11 +210,112 @@ void AddDebugInfoPass::handleGlobalOp(fir::GlobalOp globalOp,
globalOp->setLoc(builder.getFusedLoc({globalOp->getLoc()}, gvAttr));
}

void AddDebugInfoPass::handleFuncOp(mlir::func::FuncOp funcOp,
mlir::LLVM::DIFileAttr fileAttr,
mlir::LLVM::DICompileUnitAttr cuAttr,
mlir::SymbolTable *symbolTable) {
mlir::Location l = funcOp->getLoc();
// If fused location has already been created then nothing to do
// Otherwise, create a fused location.
if (debugInfoIsAlreadySet(l))
return;

mlir::ModuleOp module = getOperation();
mlir::MLIRContext *context = &getContext();
mlir::OpBuilder builder(context);
llvm::StringRef fileName(fileAttr.getName());
llvm::StringRef filePath(fileAttr.getDirectory());
unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
? llvm::dwarf::getCallingConvention("DW_CC_program")
: llvm::dwarf::getCallingConvention("DW_CC_normal");

if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) {
fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
}

mlir::StringAttr fullName = mlir::StringAttr::get(context, funcOp.getName());
mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName());
mlir::StringAttr funcName =
(attr) ? mlir::cast<mlir::StringAttr>(attr)
: mlir::StringAttr::get(context, funcOp.getName());

auto result = fir::NameUniquer::deconstruct(funcName);
funcName = mlir::StringAttr::get(context, result.second.name);

llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
fir::DebugTypeGenerator typeGen(module);
for (auto resTy : funcOp.getResultTypes()) {
auto tyAttr = typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
types.push_back(tyAttr);
}
for (auto inTy : funcOp.getArgumentTypes()) {
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
cuAttr, funcOp.getLoc());
types.push_back(tyAttr);
}

mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
mlir::LLVM::DIFileAttr funcFileAttr =
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);

// Only definitions need a distinct identifier and a compilation unit.
mlir::DistinctAttr id;
mlir::LLVM::DIScopeAttr Scope = fileAttr;
mlir::LLVM::DICompileUnitAttr compilationUnit;
mlir::LLVM::DISubprogramFlags subprogramFlags =
mlir::LLVM::DISubprogramFlags{};
if (isOptimized)
subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
if (!funcOp.isExternal()) {
id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
compilationUnit = cuAttr;
subprogramFlags =
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
}
unsigned line = getLineFromLoc(l);
if (fir::isInternalProcedure(funcOp)) {
// For contained functions, the scope is the parent subroutine.
mlir::SymbolRefAttr sym = mlir::cast<mlir::SymbolRefAttr>(
funcOp->getAttr(fir::getHostSymbolAttrName()));
if (sym) {
if (auto func =
symbolTable->lookup<mlir::func::FuncOp>(sym.getLeafReference())) {
// Make sure that parent is processed.
handleFuncOp(func, fileAttr, cuAttr, symbolTable);
if (auto fusedLoc =
mlir::dyn_cast_if_present<mlir::FusedLoc>(func.getLoc())) {
if (auto spAttr =
mlir::dyn_cast_if_present<mlir::LLVM::DISubprogramAttr>(
fusedLoc.getMetadata()))
Scope = spAttr;
}
}
}
} else if (!result.second.modules.empty()) {
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
line - 1, false);
}

auto spAttr = mlir::LLVM::DISubprogramAttr::get(
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
line, line, subprogramFlags, subTypeAttr);
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));

// Don't process variables if user asked for line tables only.
if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly)
return;

funcOp.walk([&](fir::cg::XDeclareOp declOp) {
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, symbolTable);
});
}

void AddDebugInfoPass::runOnOperation() {
mlir::ModuleOp module = getOperation();
mlir::MLIRContext *context = &getContext();
mlir::SymbolTable symbolTable(module);
mlir::OpBuilder builder(context);
llvm::StringRef fileName;
std::string filePath;
// We need 2 type of file paths here.
Expand Down Expand Up @@ -248,80 +352,7 @@ void AddDebugInfoPass::runOnOperation() {
isOptimized, debugLevel);

module.walk([&](mlir::func::FuncOp funcOp) {
mlir::Location l = funcOp->getLoc();
// If fused location has already been created then nothing to do
// Otherwise, create a fused location.
if (debugInfoIsAlreadySet(l))
return;

unsigned int CC = (funcOp.getName() == fir::NameUniquer::doProgramEntry())
? llvm::dwarf::getCallingConvention("DW_CC_program")
: llvm::dwarf::getCallingConvention("DW_CC_normal");

if (auto funcLoc = mlir::dyn_cast<mlir::FileLineColLoc>(l)) {
fileName = llvm::sys::path::filename(funcLoc.getFilename().getValue());
filePath = llvm::sys::path::parent_path(funcLoc.getFilename().getValue());
}

mlir::StringAttr fullName =
mlir::StringAttr::get(context, funcOp.getName());
mlir::Attribute attr = funcOp->getAttr(fir::getInternalFuncNameAttrName());
mlir::StringAttr funcName =
(attr) ? mlir::cast<mlir::StringAttr>(attr)
: mlir::StringAttr::get(context, funcOp.getName());

auto result = fir::NameUniquer::deconstruct(funcName);
funcName = mlir::StringAttr::get(context, result.second.name);

llvm::SmallVector<mlir::LLVM::DITypeAttr> types;
fir::DebugTypeGenerator typeGen(module);
for (auto resTy : funcOp.getResultTypes()) {
auto tyAttr =
typeGen.convertType(resTy, fileAttr, cuAttr, funcOp.getLoc());
types.push_back(tyAttr);
}
for (auto inTy : funcOp.getArgumentTypes()) {
auto tyAttr = typeGen.convertType(fir::unwrapRefType(inTy), fileAttr,
cuAttr, funcOp.getLoc());
types.push_back(tyAttr);
}

mlir::LLVM::DISubroutineTypeAttr subTypeAttr =
mlir::LLVM::DISubroutineTypeAttr::get(context, CC, types);
mlir::LLVM::DIFileAttr funcFileAttr =
mlir::LLVM::DIFileAttr::get(context, fileName, filePath);

// Only definitions need a distinct identifier and a compilation unit.
mlir::DistinctAttr id;
mlir::LLVM::DIScopeAttr Scope = fileAttr;
mlir::LLVM::DICompileUnitAttr compilationUnit;
mlir::LLVM::DISubprogramFlags subprogramFlags =
mlir::LLVM::DISubprogramFlags{};
if (isOptimized)
subprogramFlags = mlir::LLVM::DISubprogramFlags::Optimized;
if (!funcOp.isExternal()) {
id = mlir::DistinctAttr::create(mlir::UnitAttr::get(context));
compilationUnit = cuAttr;
subprogramFlags =
subprogramFlags | mlir::LLVM::DISubprogramFlags::Definition;
}
unsigned line = getLineFromLoc(l);
if (!result.second.modules.empty())
Scope = getOrCreateModuleAttr(result.second.modules[0], fileAttr, cuAttr,
line - 1, false);

auto spAttr = mlir::LLVM::DISubprogramAttr::get(
context, id, compilationUnit, Scope, funcName, fullName, funcFileAttr,
line, line, subprogramFlags, subTypeAttr);
funcOp->setLoc(builder.getFusedLoc({funcOp->getLoc()}, spAttr));

// Don't process variables if user asked for line tables only.
if (debugLevel == mlir::LLVM::DIEmissionKind::LineTablesOnly)
return;

funcOp.walk([&](fir::cg::XDeclareOp declOp) {
handleDeclareOp(declOp, fileAttr, spAttr, typeGen, &symbolTable);
});
handleFuncOp(funcOp, fileAttr, cuAttr, &symbolTable);
});
// Process any global which was not processed through DeclareOp.
if (debugLevel == mlir::LLVM::DIEmissionKind::Full) {
Expand Down
47 changes: 47 additions & 0 deletions flang/test/Lower/OpenMP/private-derived-type.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s | FileCheck %s
! RUN: bbc -emit-hlfir -fopenmp -o - %s | FileCheck %s

subroutine s4
type y3
integer,allocatable::x
end type y3
type(y3)::v
!$omp parallel
!$omp do private(v)
do i=1,10
v%x=1
end do
!$omp end do
!$omp end parallel
end subroutine s4


! CHECK-LABEL: func.func @_QPs4() {
! Example of how the lowering for regular derived type variables:
! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}> {bindc_name = "v", uniq_name = "_QFs4Ev"}
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFs4Ev"} : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>)
! CHECK: %[[VAL_10:.*]] = fir.embox %[[VAL_9]]#1 : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_11:.*]] = fir.address_of
! CHECK: %[[VAL_12:.*]] = arith.constant 4 : i32
! CHECK: %[[VAL_13:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_11]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
! CHECK: %[[VAL_15:.*]] = fir.call @_FortranAInitialize(%[[VAL_13]], %[[VAL_14]], %[[VAL_12]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: omp.parallel {
! CHECK: %[[VAL_23:.*]] = fir.alloca !fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}> {bindc_name = "v", pinned, uniq_name = "_QFs4Ev"}
! CHECK: %[[VAL_24:.*]]:2 = hlfir.declare %[[VAL_23]] {uniq_name = "_QFs4Ev"} : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>, !fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>)
! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_24]]#1 : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_26:.*]] = fir.address_of
! CHECK: %[[VAL_27:.*]] = arith.constant 4 : i32
! CHECK: %[[VAL_28:.*]] = fir.convert %[[VAL_25]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_26]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8>
! Check we do call FortranAInitialize on the derived type
! CHECK: %[[VAL_30:.*]] = fir.call @_FortranAInitialize(%[[VAL_28]], %[[VAL_29]], %[[VAL_27]]) fastmath<contract> : (!fir.box<none>, !fir.ref<i8>, i32) -> none
! CHECK: omp.wsloop {
! CHECK: omp.terminator
! CHECK: }
! CHECK: %[[VAL_39:.*]] = fir.embox %[[VAL_9]]#1 : (!fir.ref<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>
! CHECK: %[[VAL_40:.*]] = fir.convert %[[VAL_39]] : (!fir.box<!fir.type<_QFs4Ty3{x:!fir.box<!fir.heap<i32>>}>>) -> !fir.box<none>
! Check the derived type is destroyed
! CHECK: %[[VAL_41:.*]] = fir.call @_FortranADestroy(%[[VAL_40]]) fastmath<contract> : (!fir.box<none>) -> none
! CHECK: return
! CHECK: }
26 changes: 26 additions & 0 deletions flang/test/Transforms/debug-96314.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s -o - | FileCheck %s

module attributes {dlti.dl_spec = #dlti.dl_spec<>} {
func.func @_QMhelperPmod_sub(%arg0: !fir.ref<i32> {fir.bindc_name = "a"} ) {
return
} loc(#loc1)
func.func private @_QMhelperFmod_subPchild1(%arg0: !fir.ref<i32> {fir.bindc_name = "b"} ) attributes {fir.host_symbol = @_QMhelperPmod_sub, llvm.linkage = #llvm.linkage<internal>} {
return
} loc(#loc2)
func.func @global_sub_(%arg0: !fir.ref<i32> {fir.bindc_name = "n"} ) attributes {fir.internal_name = "_QPglobal_sub"} {
return
} loc(#loc3)
func.func private @_QFglobal_subPchild2(%arg0: !fir.ref<i32> {fir.bindc_name = "c"}) attributes {fir.host_symbol = @global_sub_, llvm.linkage = #llvm.linkage<internal>} {
return
} loc(#loc4)
}

#loc1 = loc("test.f90":5:1)
#loc2 = loc("test.f90":15:1)
#loc3 = loc("test.f90":25:1)
#loc4 = loc("test.f90":35:1)

// CHECK-DAG: #[[SP1:.*]] = #llvm.di_subprogram<{{.*}}name = "mod_sub"{{.*}}>
// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP1]], name = "child1"{{.*}}>
// CHECK-DAG: #[[SP2:.*]] = #llvm.di_subprogram<{{.*}}linkageName = "global_sub_"{{.*}}>
// CHECK-DAG: #llvm.di_subprogram<{{.*}}scope = #[[SP2]], name = "child2"{{.*}}>
124 changes: 62 additions & 62 deletions libc/docs/date_and_time.rst

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Implementation Status

- `linux-aarch32 <https://github.com/llvm/llvm-project/tree/main/libc/config/linux/arm/entrypoints.txt>`_

- `linux-riscv64 <https://github.com/llvm/llvm-project/tree/main/libc/config/linux/riscv64/entrypoints.txt>`_
- `linux-riscv and linux-riscv32 <https://github.com/llvm/llvm-project/tree/main/libc/config/linux/riscv/entrypoints.txt>`_

* To check math functions enabled for Windows:

Expand Down
181 changes: 53 additions & 128 deletions libc/src/__support/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,10 @@ class Block {
return reinterpret_cast<const cpp::byte *>(this) + BLOCK_OVERHEAD;
}

/// Marks the block as free and merges it with any free neighbors.
///
/// This method is static in order to consume and replace the given block
/// pointer. If neither member is free, the returned pointer will point to the
/// original block. Otherwise, it will point to the new, larger block created
/// by merging adjacent free blocks together.
static void free(Block *&block);
// @returns The region of memory the block manages, including the header.
ByteSpan region() {
return {reinterpret_cast<cpp::byte *>(this), outer_size()};
}

/// Attempts to split this block.
///
Expand All @@ -176,75 +173,34 @@ class Block {
/// This method may fail if the remaining space is too small to hold a new
/// block. If this method fails for any reason, the original block is
/// unmodified.
///
/// This method is static in order to consume and replace the given block
/// pointer with a pointer to the new, smaller block.
static optional<Block *> split(Block *&block, size_t new_inner_size);
optional<Block *> split(size_t new_inner_size);

/// Merges this block with the one that comes after it.
///
/// This method is static in order to consume and replace the given block
/// pointer with a pointer to the new, larger block.
static bool merge_next(Block *&block);
bool merge_next();

/// Fetches the block immediately after this one.
///
/// For performance, this always returns a block pointer, even if the returned
/// pointer is invalid. The pointer is valid if and only if `last()` is false.
///
/// Typically, after calling `Init` callers may save a pointer past the end of
/// the list using `next()`. This makes it easy to subsequently iterate over
/// the list:
/// @code{.cpp}
/// auto result = Block<>::init(byte_span);
/// Block<>* begin = *result;
/// Block<>* end = begin->next();
/// ...
/// for (auto* block = begin; block != end; block = block->next()) {
/// // Do something which each block.
/// }
/// @endcode
/// @returns The block immediately after this one, or a null pointer if this
/// is the last block.
Block *next() const;

/// @copydoc `next`.
static Block *next_block(const Block *block) {
return block == nullptr ? nullptr : block->next();
}

/// @returns The block immediately before this one, or a null pointer if this
/// is the first block.
Block *prev() const;

/// @copydoc `prev`.
static Block *prev_block(const Block *block) {
return block == nullptr ? nullptr : block->prev();
}

/// Indicates whether the block is in use.
///
/// @returns `true` if the block is in use or `false` if not.
bool used() const { return next_ & USED_MASK; }

/// Indicates whether this block is the last block or not (i.e. whether
/// `next()` points to a valid block or not). This is needed because
/// `next()` points to the end of this block, whether there is a valid
/// block there or not.
///
/// @returns `true` is this is the last block or `false` if not.
bool last() const { return next_ & LAST_MASK; }

/// Marks this block as in use.
void mark_used() { next_ |= USED_MASK; }

/// Marks this block as free.
void mark_free() { next_ &= ~USED_MASK; }

/// Marks this block as the last one in the chain.
/// Marks this block as the last one in the chain. Makes next() return
/// nullptr.
constexpr void mark_last() { next_ |= LAST_MASK; }

/// Clears the last bit from this block.
void clear_last() { next_ &= ~LAST_MASK; }

/// @brief Checks if a block is valid.
///
/// @returns `true` if and only if the following conditions are met:
Expand Down Expand Up @@ -314,10 +270,8 @@ class Block {
static BlockInfo allocate(Block *block, size_t alignment, size_t size);

private:
/// Consumes the block and returns as a span of bytes.
static ByteSpan as_bytes(Block *&&block);

/// Consumes the span of bytes and uses it to construct and return a block.
/// Construct a block to represent a span of bytes. Overwrites only enough
/// memory for the block header; the rest of the span is left alone.
static Block *as_block(size_t prev_outer_size, ByteSpan bytes);

/// Returns a `BlockStatus` that is either VALID or indicates the reason why
Expand All @@ -329,7 +283,7 @@ class Block {

/// Like `split`, but assumes the caller has already checked to parameters to
/// ensure the split will succeed.
static Block *split_impl(Block *&block, size_t new_inner_size);
Block *split_impl(size_t new_inner_size);

/// Offset from this block to the previous block. 0 if this is the first
/// block.
Expand Down Expand Up @@ -389,20 +343,6 @@ Block<OffsetType, kAlign>::init(ByteSpan region) {
return block;
}

template <typename OffsetType, size_t kAlign>
void Block<OffsetType, kAlign>::free(Block *&block) {
if (block == nullptr)
return;

block->mark_free();
Block *prev = block->prev();

if (merge_next(prev))
block = prev;

merge_next(block);
}

template <typename OffsetType, size_t kAlign>
bool Block<OffsetType, kAlign>::can_allocate(size_t alignment,
size_t size) const {
Expand Down Expand Up @@ -436,7 +376,7 @@ Block<OffsetType, kAlign>::allocate(Block *block, size_t alignment,

Block *original = info.block;
optional<Block *> maybe_aligned_block =
Block::split(original, adjustment - BLOCK_OVERHEAD);
original->split(adjustment - BLOCK_OVERHEAD);
LIBC_ASSERT(maybe_aligned_block.has_value() &&
"This split should always result in a new block. The check in "
"`can_allocate` ensures that we have enough space here to make "
Expand All @@ -445,7 +385,7 @@ Block<OffsetType, kAlign>::allocate(Block *block, size_t alignment,
if (Block *prev = original->prev()) {
// If there is a block before this, we can merge the current one with the
// newly created one.
merge_next(prev);
prev->merge_next();
} else {
// Otherwise, this was the very first block in the chain. Now we can make
// it the new first block.
Expand All @@ -459,84 +399,76 @@ Block<OffsetType, kAlign>::allocate(Block *block, size_t alignment,
}

// Now get a block for the requested size.
if (optional<Block *> next = Block::split(info.block, size))
if (optional<Block *> next = info.block->split(size))
info.next = *next;

return info;
}

template <typename OffsetType, size_t kAlign>
optional<Block<OffsetType, kAlign> *>
Block<OffsetType, kAlign>::split(Block *&block, size_t new_inner_size) {
if (block == nullptr)
Block<OffsetType, kAlign>::split(size_t new_inner_size) {
if (used())
return {};

if (block->used())
return {};

size_t old_inner_size = block->inner_size();
size_t old_inner_size = inner_size();
new_inner_size = align_up(new_inner_size, ALIGNMENT);
if (old_inner_size < new_inner_size)
return {};

if (old_inner_size - new_inner_size < BLOCK_OVERHEAD)
return {};

return split_impl(block, new_inner_size);
return split_impl(new_inner_size);
}

template <typename OffsetType, size_t kAlign>
Block<OffsetType, kAlign> *
Block<OffsetType, kAlign>::split_impl(Block *&block, size_t new_inner_size) {
size_t prev_outer_size = block->prev_;
Block<OffsetType, kAlign>::split_impl(size_t new_inner_size) {
size_t outer_size1 = new_inner_size + BLOCK_OVERHEAD;
bool is_last = block->last();
ByteSpan bytes = as_bytes(cpp::move(block));
Block *block1 = as_block(prev_outer_size, bytes.subspan(0, outer_size1));
Block *block2 = as_block(outer_size1, bytes.subspan(outer_size1));

if (is_last)
block2->mark_last();
else
block2->next()->prev_ = block2->next_;

block = cpp::move(block1);
return block2;
bool has_next = next();
ByteSpan new_region = region().subspan(outer_size1);
LIBC_ASSERT(!used() && "used blocks cannot be split");
// The low order bits of outer_size1 should both be zero, and is the correct
// value for the flags is false.
next_ = outer_size1;
LIBC_ASSERT(!used() && next() && "incorrect first split flags");
Block *new_block = as_block(outer_size1, new_region);

if (has_next) {
// The two flags are both false, so next_ is a plain size.
LIBC_ASSERT(!new_block->used() && next() && "flags disrupt use of size");
new_block->next()->prev_ = new_block->next_;
} else {
new_block->mark_last();
}
return new_block;
}

template <typename OffsetType, size_t kAlign>
bool Block<OffsetType, kAlign>::merge_next(Block *&block) {
if (block == nullptr)
return false;

if (block->last())
return false;

Block *next = block->next();
if (block->used() || next->used())
bool Block<OffsetType, kAlign>::merge_next() {
if (used() || !next() || next()->used())
return false;

size_t prev_outer_size = block->prev_;
bool is_last = next->last();
ByteSpan prev_bytes = as_bytes(cpp::move(block));
ByteSpan next_bytes = as_bytes(cpp::move(next));
size_t outer_size = prev_bytes.size() + next_bytes.size();
cpp::byte *merged = ::new (prev_bytes.data()) cpp::byte[outer_size];
block = as_block(prev_outer_size, ByteSpan(merged, outer_size));
// Extend the size and copy the last() flag from the next block to this one.
next_ &= SIZE_MASK;
next_ += next()->next_;

if (is_last)
block->mark_last();
else
block->next()->prev_ = block->next_;
if (next()) {
// The two flags are both false, so next_ is a plain size.
LIBC_ASSERT(!used() && next() && "flags disrupt use of size");
next()->prev_ = next_;
}

return true;
}

template <typename OffsetType, size_t kAlign>
Block<OffsetType, kAlign> *Block<OffsetType, kAlign>::next() const {
uintptr_t addr =
last() ? 0 : reinterpret_cast<uintptr_t>(this) + outer_size();
return reinterpret_cast<Block *>(addr);
if (next_ & LAST_MASK)
return nullptr;
return reinterpret_cast<Block *>(reinterpret_cast<uintptr_t>(this) +
outer_size());
}

template <typename OffsetType, size_t kAlign>
Expand All @@ -555,13 +487,6 @@ constexpr Block<OffsetType, kAlign>::Block(size_t prev_outer_size,
next_ = outer_size;
}

template <typename OffsetType, size_t kAlign>
ByteSpan Block<OffsetType, kAlign>::as_bytes(Block *&&block) {
size_t block_size = block->outer_size();
cpp::byte *bytes = new (cpp::move(block)) cpp::byte[block_size];
return {bytes, block_size};
}

template <typename OffsetType, size_t kAlign>
Block<OffsetType, kAlign> *
Block<OffsetType, kAlign>::as_block(size_t prev_outer_size, ByteSpan bytes) {
Expand All @@ -573,7 +498,7 @@ internal::BlockStatus Block<OffsetType, kAlign>::check_status() const {
if (reinterpret_cast<uintptr_t>(this) % ALIGNMENT != 0)
return internal::BlockStatus::MISALIGNED;

if (!last() && (this >= next() || this != next()->prev()))
if (next() && (this >= next() || this != next()->prev()))
return internal::BlockStatus::NEXT_MISMATCHED;

if (prev() && (this <= prev() || this != prev()->next()))
Expand Down
6 changes: 3 additions & 3 deletions libc/src/__support/freelist_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,19 @@ template <size_t NUM_BUCKETS> void FreeListHeap<NUM_BUCKETS>::free(void *ptr) {
BlockType *prev = chunk_block->prev();
BlockType *next = nullptr;

if (!chunk_block->last())
if (chunk_block->next())
next = chunk_block->next();

if (prev != nullptr && !prev->used()) {
// Remove from freelist and merge
freelist_.remove_chunk(block_to_span(prev));
chunk_block = chunk_block->prev();
BlockType::merge_next(chunk_block);
chunk_block->merge_next();
}

if (next != nullptr && !next->used()) {
freelist_.remove_chunk(block_to_span(next));
BlockType::merge_next(chunk_block);
chunk_block->merge_next();
}
// Add back to the freelist
freelist_.add_chunk(block_to_span(chunk_block));
Expand Down
193 changes: 26 additions & 167 deletions libc/test/src/__support/block_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ TEST_FOR_EACH_BLOCK_TYPE(CanCreateSingleAlignedBlock) {
EXPECT_EQ(block->prev(), static_cast<BlockType *>(nullptr));
EXPECT_EQ(block->next(), static_cast<BlockType *>(nullptr));
EXPECT_FALSE(block->used());
EXPECT_TRUE(block->last());
}

TEST_FOR_EACH_BLOCK_TYPE(CanCreateUnalignedSingleBlock) {
Expand Down Expand Up @@ -96,18 +95,16 @@ TEST_FOR_EACH_BLOCK_TYPE(CanSplitBlock) {
ASSERT_TRUE(result.has_value());
auto *block1 = *result;

result = BlockType::split(block1, kSplitN);
result = block1->split(kSplitN);
ASSERT_TRUE(result.has_value());

auto *block2 = *result;

EXPECT_EQ(block1->inner_size(), kSplitN);
EXPECT_EQ(block1->outer_size(), kSplitN + BlockType::BLOCK_OVERHEAD);
EXPECT_FALSE(block1->last());

EXPECT_EQ(block2->outer_size(), kN - kSplitN - BlockType::BLOCK_OVERHEAD);
EXPECT_FALSE(block2->used());
EXPECT_TRUE(block2->last());

EXPECT_EQ(block1->next(), block2);
EXPECT_EQ(block2->prev(), block1);
Expand All @@ -128,7 +125,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CanSplitBlockUnaligned) {
split_addr += alignof(BlockType) - (split_addr % alignof(BlockType));
uintptr_t split_len = split_addr - (uintptr_t)&bytes;

result = BlockType::split(block1, kSplitN);
result = block1->split(kSplitN);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

Expand Down Expand Up @@ -161,11 +158,11 @@ TEST_FOR_EACH_BLOCK_TYPE(CanSplitMidBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
result = block1->split(kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block1, kSplit2);
result = block1->split(kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

Expand All @@ -184,7 +181,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotSplitTooSmallBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

result = BlockType::split(block, kSplitN);
result = block->split(kSplitN);
ASSERT_FALSE(result.has_value());
}

Expand All @@ -197,13 +194,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotSplitBlockWithoutHeaderSpace) {
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

result = BlockType::split(block, kSplitN);
ASSERT_FALSE(result.has_value());
}

TEST_FOR_EACH_BLOCK_TYPE(CannotSplitNull) {
BlockType *block = nullptr;
auto result = BlockType::split(block, 1);
result = block->split(kSplitN);
ASSERT_FALSE(result.has_value());
}

Expand All @@ -216,7 +207,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotMakeBlockLargerInSplit) {
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

result = BlockType::split(block, block->inner_size() + 1);
result = block->split(block->inner_size() + 1);
ASSERT_FALSE(result.has_value());
}

Expand All @@ -229,8 +220,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotMakeSecondBlockLargerInSplit) {
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

result = BlockType::split(block, block->inner_size() -
BlockType::BLOCK_OVERHEAD + 1);
result = block->split(block->inner_size() - BlockType::BLOCK_OVERHEAD + 1);
ASSERT_FALSE(result.has_value());
}

Expand All @@ -243,7 +233,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CanMakeZeroSizeFirstBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

result = BlockType::split(block, 0);
result = block->split(0);
ASSERT_TRUE(result.has_value());
EXPECT_EQ(block->inner_size(), static_cast<size_t>(0));
}
Expand All @@ -257,8 +247,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CanMakeZeroSizeSecondBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1,
block1->inner_size() - BlockType::BLOCK_OVERHEAD);
result = block1->split(block1->inner_size() - BlockType::BLOCK_OVERHEAD);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

Expand Down Expand Up @@ -293,7 +282,7 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotSplitUsedBlock) {
BlockType *block = *result;

block->mark_used();
result = BlockType::split(block, kSplitN);
result = block->split(kSplitN);
ASSERT_FALSE(result.has_value());
}

Expand All @@ -309,14 +298,14 @@ TEST_FOR_EACH_BLOCK_TYPE(CanMergeWithNextBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
result = block1->split(kSplit1);
ASSERT_TRUE(result.has_value());

result = BlockType::split(block1, kSplit2);
result = block1->split(kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

EXPECT_TRUE(BlockType::merge_next(block3));
EXPECT_TRUE(block3->merge_next());

EXPECT_EQ(block1->next(), block3);
EXPECT_EQ(block3->prev(), block1);
Expand All @@ -334,16 +323,11 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotMergeWithFirstOrLastBlock) {
BlockType *block1 = *result;

// Do a split, just to check that the checks on next/prev are different...
result = BlockType::split(block1, kSplitN);
result = block1->split(kSplitN);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

EXPECT_FALSE(BlockType::merge_next(block2));
}

TEST_FOR_EACH_BLOCK_TYPE(CannotMergeNull) {
BlockType *block = nullptr;
EXPECT_FALSE(BlockType::merge_next(block));
EXPECT_FALSE(block2->merge_next());
}

TEST_FOR_EACH_BLOCK_TYPE(CannotMergeUsedBlock) {
Expand All @@ -356,131 +340,11 @@ TEST_FOR_EACH_BLOCK_TYPE(CannotMergeUsedBlock) {
BlockType *block = *result;

// Do a split, just to check that the checks on next/prev are different...
result = BlockType::split(block, kSplitN);
ASSERT_TRUE(result.has_value());

block->mark_used();
EXPECT_FALSE(BlockType::merge_next(block));
}

TEST_FOR_EACH_BLOCK_TYPE(CanFreeSingleBlock) {
constexpr size_t kN = 1024;
alignas(BlockType::ALIGNMENT) array<byte, kN> bytes;

auto result = BlockType::init(bytes);
result = block->split(kSplitN);
ASSERT_TRUE(result.has_value());
BlockType *block = *result;

block->mark_used();
BlockType::free(block);
EXPECT_FALSE(block->used());
EXPECT_EQ(block->outer_size(), kN);
}

TEST_FOR_EACH_BLOCK_TYPE(CanFreeBlockWithoutMerging) {
constexpr size_t kN = 1024;
constexpr size_t kSplit1 = 512;
constexpr size_t kSplit2 = 256;

alignas(BlockType::ALIGNMENT) array<byte, kN> bytes;
auto result = BlockType::init(bytes);
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

block1->mark_used();
block2->mark_used();
block3->mark_used();

BlockType::free(block2);
EXPECT_FALSE(block2->used());
EXPECT_NE(block2->prev(), static_cast<BlockType *>(nullptr));
EXPECT_FALSE(block2->last());
}

TEST_FOR_EACH_BLOCK_TYPE(CanFreeBlockAndMergeWithPrev) {
constexpr size_t kN = 1024;
constexpr size_t kSplit1 = 512;
constexpr size_t kSplit2 = 256;

alignas(BlockType::ALIGNMENT) array<byte, kN> bytes;
auto result = BlockType::init(bytes);
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

block2->mark_used();
block3->mark_used();

BlockType::free(block2);
EXPECT_FALSE(block2->used());
EXPECT_EQ(block2->prev(), static_cast<BlockType *>(nullptr));
EXPECT_FALSE(block2->last());
}

TEST_FOR_EACH_BLOCK_TYPE(CanFreeBlockAndMergeWithNext) {
constexpr size_t kN = 1024;
constexpr size_t kSplit1 = 512;
constexpr size_t kSplit2 = 256;

alignas(BlockType::ALIGNMENT) array<byte, kN> bytes;
auto result = BlockType::init(bytes);
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
ASSERT_TRUE(result.has_value());

block1->mark_used();
block2->mark_used();

BlockType::free(block2);
EXPECT_FALSE(block2->used());
EXPECT_NE(block2->prev(), static_cast<BlockType *>(nullptr));
EXPECT_TRUE(block2->last());
}

TEST_FOR_EACH_BLOCK_TYPE(CanFreeUsedBlockAndMergeWithBoth) {
constexpr size_t kN = 1024;
constexpr size_t kSplit1 = 512;
constexpr size_t kSplit2 = 256;

alignas(BlockType::ALIGNMENT) array<byte, kN> bytes;
auto result = BlockType::init(bytes);
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
ASSERT_TRUE(result.has_value());

block2->mark_used();

BlockType::free(block2);
EXPECT_FALSE(block2->used());
EXPECT_EQ(block2->prev(), static_cast<BlockType *>(nullptr));
EXPECT_TRUE(block2->last());
EXPECT_FALSE(block->merge_next());
}

TEST_FOR_EACH_BLOCK_TYPE(CanCheckValidBlock) {
Expand All @@ -493,11 +357,11 @@ TEST_FOR_EACH_BLOCK_TYPE(CanCheckValidBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
result = block1->split(kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
result = block2->split(kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

Expand All @@ -517,15 +381,15 @@ TEST_FOR_EACH_BLOCK_TYPE(CanCheckInvalidBlock) {
ASSERT_TRUE(result.has_value());
BlockType *block1 = *result;

result = BlockType::split(block1, kSplit1);
result = block1->split(kSplit1);
ASSERT_TRUE(result.has_value());
BlockType *block2 = *result;

result = BlockType::split(block2, kSplit2);
result = block2->split(kSplit2);
ASSERT_TRUE(result.has_value());
BlockType *block3 = *result;

result = BlockType::split(block3, kSplit3);
result = block3->split(kSplit3);
ASSERT_TRUE(result.has_value());

// Corrupt a Block header.
Expand Down Expand Up @@ -630,7 +494,6 @@ TEST_FOR_EACH_BLOCK_TYPE(AllocateAlreadyAligned) {
// Check the next block.
EXPECT_NE(next, static_cast<BlockType *>(nullptr));
EXPECT_EQ(aligned_block->next(), next);
EXPECT_EQ(next->next(), static_cast<BlockType *>(nullptr));
EXPECT_EQ(reinterpret_cast<byte *>(next) + next->outer_size(),
bytes.data() + bytes.size());
}
Expand Down Expand Up @@ -674,7 +537,6 @@ TEST_FOR_EACH_BLOCK_TYPE(AllocateNeedsAlignment) {
// Check the next block.
EXPECT_NE(next, static_cast<BlockType *>(nullptr));
EXPECT_EQ(aligned_block->next(), next);
EXPECT_EQ(next->next(), static_cast<BlockType *>(nullptr));
EXPECT_EQ(reinterpret_cast<byte *>(next) + next->outer_size(), &*bytes.end());
}

Expand All @@ -687,7 +549,7 @@ TEST_FOR_EACH_BLOCK_TYPE(PreviousBlockMergedIfNotFirst) {
BlockType *block = *result;

// Split the block roughly halfway and work on the second half.
auto result2 = BlockType::split(block, kN / 2);
auto result2 = block->split(kN / 2);
ASSERT_TRUE(result2.has_value());
BlockType *newblock = *result2;
ASSERT_EQ(newblock->prev(), block);
Expand Down Expand Up @@ -744,20 +606,17 @@ TEST_FOR_EACH_BLOCK_TYPE(CanRemergeBlockAllocations) {

// Check we have the appropriate blocks.
ASSERT_NE(prev, static_cast<BlockType *>(nullptr));
ASSERT_FALSE(prev->last());
ASSERT_EQ(aligned_block->prev(), prev);
EXPECT_NE(next, static_cast<BlockType *>(nullptr));
EXPECT_NE(next, static_cast<BlockType *>(nullptr));
EXPECT_EQ(aligned_block->next(), next);
EXPECT_EQ(next->next(), static_cast<BlockType *>(nullptr));
ASSERT_TRUE(next->last());

// Now check for successful merges.
EXPECT_TRUE(BlockType::merge_next(prev));
EXPECT_TRUE(prev->merge_next());
EXPECT_EQ(prev->next(), next);
EXPECT_TRUE(BlockType::merge_next(prev));
EXPECT_TRUE(prev->merge_next());
EXPECT_EQ(prev->next(), static_cast<BlockType *>(nullptr));
EXPECT_TRUE(prev->last());

// We should have the original buffer.
EXPECT_EQ(reinterpret_cast<byte *>(prev), &*bytes.begin());
Expand Down
7 changes: 0 additions & 7 deletions libcxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,6 @@ option(LIBCXX_GENERATE_COVERAGE "Enable generating code coverage." OFF)
set(LIBCXX_COVERAGE_LIBRARY "" CACHE STRING
"The Profile-rt library used to build with code coverage")

set(LIBCXX_CONFIGURE_IDE_DEFAULT OFF)
if (XCODE OR MSVC_IDE)
set(LIBCXX_CONFIGURE_IDE_DEFAULT ON)
endif()
option(LIBCXX_CONFIGURE_IDE "Configure libcxx for use within an IDE"
${LIBCXX_CONFIGURE_IDE_DEFAULT})

set(LIBCXX_HERMETIC_STATIC_LIBRARY_DEFAULT OFF)
if (WIN32)
set(LIBCXX_HERMETIC_STATIC_LIBRARY_DEFAULT ON)
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_syncbuf`` ``201803L``
---------------------------------------------------------- -----------------
``__cpp_lib_three_way_comparison`` ``201711L``
``__cpp_lib_three_way_comparison`` ``201907L``
---------------------------------------------------------- -----------------
``__cpp_lib_to_address`` ``201711L``
---------------------------------------------------------- -----------------
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/19.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Implemented Papers
------------------

- P1132R8 - ``out_ptr`` - a scalable output pointer abstraction
- P1614R2 - The Mothership has Landed
- P2637R3 - Member ``visit``
- P2652R2 - Disallow User Specialization of ``allocator_traits``
- P2819R2 - Add ``tuple`` protocol to ``complex``
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/Status/Cxx20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Paper Status
.. [#note-P0883.1] P0883: shared_ptr and floating-point changes weren't applied as they themselves aren't implemented yet.
.. [#note-P0883.2] P0883: ``ATOMIC_FLAG_INIT`` was marked deprecated in version 14.0, but was undeprecated with the implementation of LWG3659 in version 15.0.
.. [#note-P0660] P0660: The paper is implemented but the features are experimental and can be enabled via ``-fexperimental-library``.
.. [#note-P1614] P1614: ``std::strong_order(long double, long double)`` is partly implemented.
.. [#note-P0355] P0355: The implementation status is:
* ``Calendars`` mostly done in Clang 7
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/Cxx20Papers.csv
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
"`P1522R1 <https://wg21.link/P1522R1>`__","LWG","Iterator Difference Type and Integer Overflow","Cologne","|Complete|","15.0","|ranges|"
"`P1523R1 <https://wg21.link/P1523R1>`__","LWG","Views and Size Types","Cologne","|Complete|","15.0","|ranges|"
"`P1612R1 <https://wg21.link/P1612R1>`__","LWG","Relocate Endian's Specification","Cologne","|Complete|","10.0"
"`P1614R2 <https://wg21.link/P1614R2>`__","LWG","The Mothership has Landed","Cologne","|In Progress|",""
"`P1614R2 <https://wg21.link/P1614R2>`__","LWG","The Mothership has Landed","Cologne","|Complete| [#note-P1614]_","19.0"
"`P1638R1 <https://wg21.link/P1638R1>`__","LWG","basic_istream_view::iterator should not be copyable","Cologne","|Complete|","16.0","|ranges|"
"`P1643R1 <https://wg21.link/P1643R1>`__","LWG","Add wait/notify to atomic_ref","Cologne","|Complete|","19.0"
"`P1644R0 <https://wg21.link/P1644R0>`__","LWG","Add wait/notify to atomic<shared_ptr>","Cologne","",""
Expand Down
2 changes: 1 addition & 1 deletion libcxx/docs/Status/SpaceshipPapers.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"Number","Name","Status","First released version"
`P1614R2 <https://wg21.link/P1614R2>`_,The Mothership has Landed,|In Progress|,
`P1614R2 <https://wg21.link/P1614R2>`_,The Mothership has Landed,|Complete|,19.0
`P2404R3 <https://wg21.link/P2404R3>`_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types",,
`LWG3330 <https://wg21.link/LWG3330>`_,Include ``<compare>`` from most library headers,"|Complete|","13.0"
`LWG3347 <https://wg21.link/LWG3347>`_,"``std::pair<T, U>`` now requires ``T`` and ``U`` to be *less-than-comparable*",|Nothing To Do|,
Expand Down
4 changes: 4 additions & 0 deletions libcxx/include/locale
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ template <class charT> class messages_byname;
# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
# endif

# if defined(__APPLE__) || defined(__FreeBSD__)
# include <xlocale.h>
# endif

# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
# endif
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ __cpp_lib_string_view 202403L <string> <string
__cpp_lib_submdspan 202306L <mdspan>
__cpp_lib_syncbuf 201803L <syncstream>
__cpp_lib_text_encoding 202306L <text_encoding>
__cpp_lib_three_way_comparison 201711L <compare>
__cpp_lib_three_way_comparison 201907L <compare>
__cpp_lib_to_address 201711L <memory>
__cpp_lib_to_array 201907L <array>
__cpp_lib_to_chars 202306L <charconv>
Expand Down Expand Up @@ -446,7 +446,7 @@ __cpp_lib_void_t 201411L <type_traits>
# if !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)
# define __cpp_lib_syncbuf 201803L
# endif
# define __cpp_lib_three_way_comparison 201711L
# define __cpp_lib_three_way_comparison 201907L
# define __cpp_lib_to_address 201711L
# define __cpp_lib_to_array 201907L
# define __cpp_lib_type_identity 201806L
Expand Down
14 changes: 0 additions & 14 deletions libcxx/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,20 +143,6 @@ if (LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS)
)
endif()

# Add all the headers to the project for IDEs.
if (LIBCXX_CONFIGURE_IDE)
file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*)
if(WIN32)
file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/__support/win32/*.h)
list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS})
endif()
# Force them all into the headers dir on MSVC, otherwise they end up at
# project scope because they don't have extensions.
if (MSVC_IDE)
source_group("Header Files" FILES ${LIBCXX_HEADERS})
endif()
endif()

if(NOT LIBCXX_INSTALL_LIBRARY)
set(exclude_from_all EXCLUDE_FROM_ALL)
endif()
Expand Down
50 changes: 12 additions & 38 deletions libcxx/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,21 @@ endif()

serialize_lit_params_list(SERIALIZED_LIT_PARAMS LIBCXX_TEST_PARAMS)

if (LIBCXX_INCLUDE_TESTS)
include(AddLLVM) # for configure_lit_site_cfg and add_lit_testsuite
include(AddLLVM) # for configure_lit_site_cfg and add_lit_testsuite

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/configs/cmake-bridge.cfg.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake-bridge.cfg"
@ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/configs/cmake-bridge.cfg.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake-bridge.cfg"
@ONLY)

configure_lit_site_cfg(
"${LIBCXX_TEST_CONFIG}"
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
MAIN_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py")
configure_lit_site_cfg(
"${LIBCXX_TEST_CONFIG}"
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
MAIN_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py")

add_lit_testsuite(check-cxx
"Running libcxx tests"
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS cxx-test-depends)

endif()
add_lit_testsuite(check-cxx
"Running libcxx tests"
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS cxx-test-depends)

if (LIBCXX_GENERATE_COVERAGE)
include(CodeCoverage)
Expand All @@ -64,26 +61,3 @@ if (LIBCXX_GENERATE_COVERAGE)
set(extract_dirs "${LIBCXX_SOURCE_DIR}/include;${LIBCXX_SOURCE_DIR}/src")
setup_lcov_test_target_coverage("cxx" "${output_dir}" "${capture_dirs}" "${extract_dirs}")
endif()

if (LIBCXX_CONFIGURE_IDE)
# Create dummy targets for each of the tests in the test suite, this allows
# IDE's such as CLion to correctly highlight the tests because it knows
# roughly what include paths/compile flags/macro definitions are needed.
include_directories(support)
file(GLOB_RECURSE LIBCXX_TESTS ${CMAKE_CURRENT_SOURCE_DIR}/*.pass.cpp)
file(GLOB LIBCXX_TEST_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/support/*)
file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*)
add_executable(libcxx_test_objects EXCLUDE_FROM_ALL
${LIBCXX_TESTS} ${LIBCXX_TEST_HEADERS} ${LIBCXX_HEADERS})
add_dependencies(libcxx_test_objects cxx)

split_list(LIBCXX_COMPILE_FLAGS)
split_list(LIBCXX_LINK_FLAGS)

set_target_properties(libcxx_test_objects
PROPERTIES
COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}"
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
EXCLUDE_FROM_ALL ON
)
endif()
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static void large_file() {
// the data at the end of the source file.
std::string out_data(additional_size, 'z');
{
std::FILE* dest_file = std::fopen(dest.string().c_str(), "rb");
std::FILE* dest_file = std::fopen(dest.string().c_str(), "r");
assert(dest_file != nullptr);
assert(std::fseek(dest_file, sendfile_size_limit, SEEK_SET) == 0);
assert(std::fread(&out_data[0], sizeof(out_data[0]), additional_size, dest_file) == additional_size);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// Test the feature test macros defined by <compare>

/* Constant Value
__cpp_lib_three_way_comparison 201711L [C++20]
__cpp_lib_three_way_comparison 201907L [C++20]
*/

#include <compare>
Expand Down Expand Up @@ -45,26 +45,26 @@
# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++20"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++20"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++20"
# endif

#elif TEST_STD_VER == 23

# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++23"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++23"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++23"
# endif

#elif TEST_STD_VER > 23

# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++26"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++26"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++26"
# endif

#endif // TEST_STD_VER > 23
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
__cpp_lib_submdspan 202306L [C++26]
__cpp_lib_syncbuf 201803L [C++20]
__cpp_lib_text_encoding 202306L [C++26]
__cpp_lib_three_way_comparison 201711L [C++20]
__cpp_lib_three_way_comparison 201907L [C++20]
__cpp_lib_to_address 201711L [C++20]
__cpp_lib_to_array 201907L [C++20]
__cpp_lib_to_chars 201611L [C++17]
Expand Down Expand Up @@ -4438,8 +4438,8 @@
# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++20"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++20"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++20"
# endif

# ifndef __cpp_lib_to_address
Expand Down Expand Up @@ -6037,8 +6037,8 @@
# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++23"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++23"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++23"
# endif

# ifndef __cpp_lib_to_address
Expand Down Expand Up @@ -7960,8 +7960,8 @@
# ifndef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should be defined in c++26"
# endif
# if __cpp_lib_three_way_comparison != 201711L
# error "__cpp_lib_three_way_comparison should have the value 201711L in c++26"
# if __cpp_lib_three_way_comparison != 201907L
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++26"
# endif

# ifndef __cpp_lib_to_address
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@

// UNSUPPORTED: c++03, c++11, c++14

// picolibc doesn't define TIME_UTC.
// XFAIL: LIBCXX-PICOLIBC-FIXME

// ::timespec_get is provided by the C library, but it's marked as
// unavailable until macOS 10.15
// XFAIL: target={{.+}}-apple-macosx10.{{13|14}}
Expand Down
9 changes: 2 additions & 7 deletions libcxx/utils/ci/build-picolibc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,8 @@ picolibc_source_dir="${build_dir}/picolibc-source"
picolibc_build_dir="${build_dir}/picolibc-build"
mkdir -p "${picolibc_source_dir}"
mkdir -p "${picolibc_build_dir}"
# Download the version of picolibc that was the latest at the time this script was written.
# Following changes are required and were introduced after version 1.8.5:
# - updated semihost arguments handling,
# - added missing macros in stdio.h
# - external linkage for isblank
# Version following 1.8.5, was not released by the time of writing.
picolibc_commit="04a90c56d7aac61880f205ec29b3dce6a9de0342"
# Download a known good version of picolibc.
picolibc_commit="48fbc2009c6473293d03d5ec6f190565c6223a5c"
curl -L "https://github.com/picolibc/picolibc/archive/${picolibc_commit}.zip" --output "${picolibc_source_dir}/picolibc.zip"
unzip -q "${picolibc_source_dir}/picolibc.zip" -d "${picolibc_source_dir}"
mv "${picolibc_source_dir}/picolibc-${picolibc_commit}"/* "${picolibc_source_dir}"
Expand Down
3 changes: 1 addition & 2 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,8 +1302,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_three_way_comparison",
"values": {"c++20": 201711},
# {"c++20": 201907} # P1614R2 The Mothership has Landed (see P1902R1 Missing feature-test macros 2017-2019)
"values": {"c++20": 201907},
"headers": ["compare"],
},
{
Expand Down
4 changes: 2 additions & 2 deletions lld/MachO/BPSectionOrderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ getRelocHash(const Reloc &reloc,
sectionIdx = sectionIdxIt->getSecond();
std::string kind;
if (isec)
kind = ("Section " + Twine(isec->kind())).str();
kind = ("Section " + Twine((uint8_t)isec->kind())).str();
if (auto *sym = reloc.referent.dyn_cast<Symbol *>()) {
kind += (" Symbol " + Twine(sym->kind())).str();
kind += (" Symbol " + Twine((uint8_t)sym->kind())).str();
if (auto *d = dyn_cast<Defined>(sym)) {
if (isa_and_nonnull<CStringInputSection>(isec))
return getRelocHash(kind, 0, isec->getOffset(d->value), reloc.addend);
Expand Down
20 changes: 20 additions & 0 deletions lldb/include/lldb/Core/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLDB_CORE_PLUGINMANAGER_H

#include "lldb/Core/Architecture.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/FileSpec.h"
Expand Down Expand Up @@ -487,6 +488,25 @@ class PluginManager {

static LanguageSet GetAllTypeSystemSupportedLanguagesForExpressions();

// Scripted Interface
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages);

static bool UnregisterPlugin(ScriptedInterfaceCreateInstance create_callback);

static uint32_t GetNumScriptedInterfaces();

static llvm::StringRef GetScriptedInterfaceNameAtIndex(uint32_t idx);

static llvm::StringRef GetScriptedInterfaceDescriptionAtIndex(uint32_t idx);

static lldb::ScriptLanguage GetScriptedInterfaceLanguageAtIndex(uint32_t idx);

static ScriptedInterfaceUsages
GetScriptedInterfaceUsagesAtIndex(uint32_t idx);

// REPL
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
REPLCreateInstance create_callback,
Expand Down
7 changes: 7 additions & 0 deletions lldb/include/lldb/Interpreter/Interfaces/ScriptedInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H
#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDINTERFACE_H

#include "ScriptedInterfaceUsages.h"

#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
Expand Down Expand Up @@ -68,6 +70,11 @@ class ScriptedInterface {
return true;
}

static bool CreateInstance(lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages) {
return false;
}

protected:
StructuredData::GenericSP m_object_instance_sp;
};
Expand Down
43 changes: 43 additions & 0 deletions lldb/include/lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===-- ScriptedInterfaceUsages.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_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H
#define LLDB_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H

#include "lldb/lldb-types.h"

#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"

namespace lldb_private {
class ScriptedInterfaceUsages {
public:
ScriptedInterfaceUsages() = default;
ScriptedInterfaceUsages(const std::vector<llvm::StringRef> ci_usages,
const std::vector<llvm::StringRef> sbapi_usages)
: m_command_interpreter_usages(ci_usages), m_sbapi_usages(sbapi_usages) {}

const std::vector<llvm::StringRef> &GetCommandInterpreterUsages() const {
return m_command_interpreter_usages;
}

const std::vector<llvm::StringRef> &GetSBAPIUsages() const {
return m_sbapi_usages;
}

enum class UsageKind { CommandInterpreter, API };

void Dump(Stream &s, UsageKind kind) const;

private:
std::vector<llvm::StringRef> m_command_interpreter_usages;
std::vector<llvm::StringRef> m_sbapi_usages;
};
} // namespace lldb_private

#endif // LLDB_INTERPRETER_SCRIPTEDINTERFACEUSAGES_H
3 changes: 3 additions & 0 deletions lldb/include/lldb/lldb-private-interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Value;
} // namespace llvm

namespace lldb_private {
class ScriptedInterfaceUsages;
typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
const ArchSpec &arch);
typedef std::unique_ptr<Architecture> (*ArchitectureCreateInstance)(
Expand Down Expand Up @@ -124,6 +125,8 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error,
lldb::LanguageType language,
Debugger *debugger, Target *target,
const char *repl_options);
typedef bool (*ScriptedInterfaceCreateInstance)(lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages);
typedef int (*ComparisonFunction)(const void *, const void *);
typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
/// Trace
Expand Down
126 changes: 124 additions & 2 deletions lldb/source/Commands/CommandObjectScripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@

#include "CommandObjectScripting.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Args.h"
Expand Down Expand Up @@ -127,9 +129,126 @@ class CommandObjectScriptingRun : public CommandObjectRaw {
CommandOptions m_options;
};

#pragma mark CommandObjectMultiwordScripting
#define LLDB_OPTIONS_scripting_template_list
#include "CommandOptions.inc"

class CommandObjectScriptingTemplateList : public CommandObjectParsed {
public:
CommandObjectScriptingTemplateList(CommandInterpreter &interpreter)
: CommandObjectParsed(
interpreter, "scripting template list",
"List all the available scripting extension templates. ",
"scripting template list [--language <scripting-language> --]") {}

~CommandObjectScriptingTemplateList() override = default;

Options *GetOptions() override { return &m_options; }

class CommandOptions : public Options {
public:
CommandOptions() = default;
~CommandOptions() override = default;
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
ExecutionContext *execution_context) override {
Status error;
const int short_option = m_getopt_table[option_idx].val;

// CommandObjectMultiwordScripting
switch (short_option) {
case 'l':
m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
option_arg, GetDefinitions()[option_idx].enum_values,
eScriptLanguageNone, error);
if (!error.Success())
error.SetErrorStringWithFormatv(
"unrecognized value for language '{0}'", option_arg);
break;
default:
llvm_unreachable("Unimplemented option");
}

return error;
}

void OptionParsingStarting(ExecutionContext *execution_context) override {
m_language = lldb::eScriptLanguageDefault;
}

llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::ArrayRef(g_scripting_template_list_options);
}

lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
};

protected:
void DoExecute(Args &command, CommandReturnObject &result) override {
Stream &s = result.GetOutputStream();
s.Printf("Available scripted extension templates:");

auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) {
if (!value.empty()) {
s.IndentMore();
s.Indent();
s << key << ": " << value << '\n';
s.IndentLess();
}
};

size_t num_listed_interface = 0;
size_t num_templates = PluginManager::GetNumScriptedInterfaces();
for (size_t i = 0; i < num_templates; i++) {
llvm::StringRef plugin_name =
PluginManager::GetScriptedInterfaceNameAtIndex(i);
if (plugin_name.empty())
break;

lldb::ScriptLanguage lang =
PluginManager::GetScriptedInterfaceLanguageAtIndex(i);
if (lang != m_options.m_language)
continue;

if (!num_listed_interface)
s.EOL();

num_listed_interface++;

llvm::StringRef desc =
PluginManager::GetScriptedInterfaceDescriptionAtIndex(i);
ScriptedInterfaceUsages usages =
PluginManager::GetScriptedInterfaceUsagesAtIndex(i);

print_field("Name", plugin_name);
print_field("Language", ScriptInterpreter::LanguageToString(lang));
print_field("Description", desc);
usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API);
usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter);

if (i != num_templates - 1)
s.EOL();
}

if (!num_listed_interface)
s << " None\n";
}

private:
CommandOptions m_options;
};

class CommandObjectMultiwordScriptingTemplate : public CommandObjectMultiword {
public:
CommandObjectMultiwordScriptingTemplate(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "scripting template",
"Commands for operating on the scripting templates.",
"scripting template [<subcommand-options>]") {
LoadSubCommand(
"list",
CommandObjectSP(new CommandObjectScriptingTemplateList(interpreter)));
}

~CommandObjectMultiwordScriptingTemplate() override = default;
};

CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
CommandInterpreter &interpreter)
Expand All @@ -139,6 +258,9 @@ CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
"scripting <subcommand> [<subcommand-options>]") {
LoadSubCommand("run",
CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
LoadSubCommand("template",
CommandObjectSP(
new CommandObjectMultiwordScriptingTemplate(interpreter)));
}

CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;
6 changes: 6 additions & 0 deletions lldb/source/Commands/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,12 @@ let Command = "scripting run" in {
" language. If none is specific the default scripting language is used.">;
}

let Command = "scripting template list" in {
def scripting_template_list_language : Option<"language", "l">,
EnumArg<"ScriptLang">, Desc<"Specify the scripting "
" language. If none is specified the default scripting language is used.">;
}

let Command = "source info" in {
def source_info_count : Option<"count", "c">, Arg<"Count">,
Desc<"The number of line entries to display.">;
Expand Down
65 changes: 65 additions & 0 deletions lldb/source/Core/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,70 @@ LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() {
return all;
}

#pragma mark ScriptedInterfaces

struct ScriptedInterfaceInstance
: public PluginInstance<ScriptedInterfaceCreateInstance> {
ScriptedInterfaceInstance(llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language,
ScriptedInterfaceUsages usages)
: PluginInstance<ScriptedInterfaceCreateInstance>(name, description,
create_callback),
language(language), usages(usages) {}

lldb::ScriptLanguage language;
ScriptedInterfaceUsages usages;
};

typedef PluginInstances<ScriptedInterfaceInstance> ScriptedInterfaceInstances;

static ScriptedInterfaceInstances &GetScriptedInterfaceInstances() {
static ScriptedInterfaceInstances g_instances;
return g_instances;
}

bool PluginManager::RegisterPlugin(
llvm::StringRef name, llvm::StringRef description,
ScriptedInterfaceCreateInstance create_callback,
lldb::ScriptLanguage language, ScriptedInterfaceUsages usages) {
return GetScriptedInterfaceInstances().RegisterPlugin(
name, description, create_callback, language, usages);
}

bool PluginManager::UnregisterPlugin(
ScriptedInterfaceCreateInstance create_callback) {
return GetScriptedInterfaceInstances().UnregisterPlugin(create_callback);
}

uint32_t PluginManager::GetNumScriptedInterfaces() {
return GetScriptedInterfaceInstances().GetInstances().size();
}

llvm::StringRef PluginManager::GetScriptedInterfaceNameAtIndex(uint32_t index) {
return GetScriptedInterfaceInstances().GetNameAtIndex(index);
}

llvm::StringRef
PluginManager::GetScriptedInterfaceDescriptionAtIndex(uint32_t index) {
return GetScriptedInterfaceInstances().GetDescriptionAtIndex(index);
}

lldb::ScriptLanguage
PluginManager::GetScriptedInterfaceLanguageAtIndex(uint32_t idx) {
const auto &instances = GetScriptedInterfaceInstances().GetInstances();
return idx < instances.size() ? instances[idx].language
: ScriptLanguage::eScriptLanguageNone;
}

ScriptedInterfaceUsages
PluginManager::GetScriptedInterfaceUsagesAtIndex(uint32_t idx) {
const auto &instances = GetScriptedInterfaceInstances().GetInstances();
if (idx >= instances.size())
return {};
return instances[idx].usages;
}

#pragma mark REPL

struct REPLInstance : public PluginInstance<REPLCreateInstance> {
Expand Down Expand Up @@ -1565,6 +1629,7 @@ void PluginManager::DebuggerInitialize(Debugger &debugger) {
GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
GetTracePluginInstances().PerformDebuggerCallback(debugger);
GetScriptedInterfaceInstances().PerformDebuggerCallback(debugger);
}

// This is the preferred new way to register plugin specific settings. e.g.
Expand Down
8 changes: 3 additions & 5 deletions lldb/source/Host/linux/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,9 @@ enum class ProcessState {
Zombie,
};

constexpr int task_comm_len = 16;

struct StatFields {
::pid_t pid = LLDB_INVALID_PROCESS_ID;
char comm[task_comm_len];
// comm
char state;
::pid_t ppid = LLDB_INVALID_PROCESS_ID;
::pid_t pgrp = LLDB_INVALID_PROCESS_ID;
Expand Down Expand Up @@ -100,8 +98,8 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
StatFields stat_fields;
if (sscanf(
Rest.data(),
"%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld",
&stat_fields.pid, stat_fields.comm, &stat_fields.state,
"%d %*s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld",
&stat_fields.pid, /* comm, */ &stat_fields.state,
&stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session,
&stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags,
&stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt,
Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ lldb_tablegen(InterpreterPropertiesEnum.inc -gen-lldb-property-enum-defs
SOURCE InterpreterProperties.td
TARGET LLDBInterpreterPropertiesEnumGen)

add_subdirectory(Interfaces)

add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
CommandAlias.cpp
CommandHistory.cpp
Expand Down Expand Up @@ -54,6 +56,7 @@ add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
ScriptInterpreter.cpp

LINK_LIBS
lldbInterpreterInterfaces
lldbCommands
lldbCore
lldbDataFormatters
Expand All @@ -66,6 +69,7 @@ add_lldb_library(lldbInterpreter NO_PLUGIN_DEPENDENCIES
)

add_dependencies(lldbInterpreter
lldbInterpreterInterfaces
LLDBInterpreterPropertiesGen
LLDBInterpreterPropertiesEnumGen)

10 changes: 10 additions & 0 deletions lldb/source/Interpreter/Interfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_lldb_library(lldbInterpreterInterfaces NO_PLUGIN_DEPENDENCIES
ScriptedInterfaceUsages.cpp

LINK_LIBS
lldbUtility

LINK_COMPONENTS
Support
)

37 changes: 37 additions & 0 deletions lldb/source/Interpreter/Interfaces/ScriptedInterfaceUsages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===-- ScriptedInterfaceUsages.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"

using namespace lldb;
using namespace lldb_private;

void ScriptedInterfaceUsages::Dump(Stream &s, UsageKind kind) const {
s.IndentMore();
s.Indent();
llvm::StringRef usage_kind =
(kind == UsageKind::CommandInterpreter) ? "Command Interpreter" : "API";
s << usage_kind << " Usages:";
const std::vector<llvm::StringRef> &usages =
(kind == UsageKind::CommandInterpreter) ? GetCommandInterpreterUsages()
: GetSBAPIUsages();
if (usages.empty())
s << " None\n";
else if (usages.size() == 1)
s << " " << usages.front() << '\n';
else {
s << '\n';
for (llvm::StringRef usage : usages) {
s.IndentMore();
s.Indent();
s << usage << '\n';
s.IndentLess();
}
}
s.IndentLess();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@ if (LLDB_ENABLE_LIBEDIT)
endif()

add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
OperatingSystemPythonInterface.cpp
ScriptedPythonInterface.cpp
ScriptedProcessPythonInterface.cpp
ScriptedThreadPythonInterface.cpp
ScriptedThreadPlanPythonInterface.cpp
ScriptedPlatformPythonInterface.cpp

LINK_LIBS
lldbCore
Expand All @@ -38,3 +34,9 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces
LINK_COMPONENTS
Support
)

add_subdirectory(OperatingSystemPythonInterface)
add_subdirectory(ScriptedPlatformPythonInterface)
add_subdirectory(ScriptedProcessPythonInterface)
add_subdirectory(ScriptedThreadPlanPythonInterface)

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_lldb_library(lldbPluginScriptInterpreterPythonOperatingSystemPythonInterface PLUGIN

OperatingSystemPythonInterface.cpp

LINK_LIBS
lldbCore
lldbHost
lldbInterpreter
lldbTarget
lldbPluginScriptInterpreterPython
${Python3_LIBRARIES}
${LLDB_LIBEDIT_LIBS}

LINK_COMPONENTS
Support
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,30 @@
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"

#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../lldb-python.h"
#include "../../lldb-python.h"
//clang-format on

#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"
#include "../../SWIGPythonBridge.h"
#include "../../ScriptInterpreterPythonImpl.h"
#include "OperatingSystemPythonInterface.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
using Locker = ScriptInterpreterPythonImpl::Locker;

LLDB_PLUGIN_DEFINE_ADV(OperatingSystemPythonInterface, ScriptInterpreterPythonOperatingSystemPythonInterface)

OperatingSystemPythonInterface::OperatingSystemPythonInterface(
ScriptInterpreterPythonImpl &interpreter)
: OperatingSystemInterface(), ScriptedThreadPythonInterface(interpreter) {}
Expand Down Expand Up @@ -79,4 +84,18 @@ OperatingSystemPythonInterface::GetRegisterContextForTID(lldb::tid_t tid) {
return obj->GetAsString()->GetValue().str();
}

void OperatingSystemPythonInterface::Initialize() {
const std::vector<llvm::StringRef> ci_usages = {
"settings set target.process.python-os-plugin-path <script-path>",
"settings set process.experimental.os-plugin-reports-all-threads [0/1]"};
const std::vector<llvm::StringRef> api_usages = {};
PluginManager::RegisterPlugin(
GetPluginNameStatic(), llvm::StringRef("Mock thread state"),
CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
}

void OperatingSystemPythonInterface::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,28 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_OPERATINGSYSTEMPYTHONINTERFACE_H

#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../../lldb-python.h"
//clang-format on
#endif

#include "lldb/Host/Config.h"
#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"

#if LLDB_ENABLE_PYTHON

#include "ScriptedThreadPythonInterface.h"
#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
#include "../ScriptedThreadPythonInterface.h"

#include <optional>

namespace lldb_private {
class OperatingSystemPythonInterface
: virtual public OperatingSystemInterface,
virtual public ScriptedThreadPythonInterface {
virtual public ScriptedThreadPythonInterface,
public PluginInterface {
public:
OperatingSystemPythonInterface(ScriptInterpreterPythonImpl &interpreter);

Expand All @@ -41,6 +51,16 @@ class OperatingSystemPythonInterface
StructuredData::DictionarySP GetRegisterInfo() override;

std::optional<std::string> GetRegisterContextForTID(lldb::tid_t tid) override;

static void Initialize();

static void Terminate();

static llvm::StringRef GetPluginNameStatic() {
return "OperatingSystemPythonInterface";
}

llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
};
} // namespace lldb_private

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_lldb_library(lldbPluginScriptInterpreterPythonScriptedPlatformPythonInterface PLUGIN

ScriptedPlatformPythonInterface.cpp

LINK_LIBS
lldbCore
lldbHost
lldbInterpreter
lldbTarget
lldbPluginScriptInterpreterPython
${Python3_LIBRARIES}
${LLDB_LIBEDIT_LIBS}

LINK_COMPONENTS
Support
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,35 @@
//
//===----------------------------------------------------------------------===//

#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../../lldb-python.h"
//clang-format on

#endif

#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"

#if LLDB_ENABLE_PYTHON

// LLDB Python header must be included first
#include "../lldb-python.h"

#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"
#include "../../SWIGPythonBridge.h"
#include "../../ScriptInterpreterPythonImpl.h"
#include "ScriptedPlatformPythonInterface.h"

#include "lldb/Target/ExecutionContext.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
using Locker = ScriptInterpreterPythonImpl::Locker;

LLDB_PLUGIN_DEFINE_ADV(ScriptedPlatformPythonInterface, ScriptInterpreterPythonScriptedPlatformPythonInterface)

ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface(
ScriptInterpreterPythonImpl &interpreter)
: ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {}
Expand Down Expand Up @@ -93,4 +101,14 @@ Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) {
return GetStatusFromMethod("kill_process", pid);
}

void ScriptedPlatformPythonInterface::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), "Mock platform and interact with its processes.",
CreateInstance, eScriptLanguagePython, {});
}

void ScriptedPlatformPythonInterface::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}

#endif // LLDB_ENABLE_PYTHON
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPLATFORMPYTHONINTERFACE_H

#include "lldb/Host/Config.h"
#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"

#if LLDB_ENABLE_PYTHON

#include "ScriptedPythonInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
#include "../ScriptedPythonInterface.h"

namespace lldb_private {
class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface,
public ScriptedPythonInterface {
public ScriptedPythonInterface,
public PluginInterface {
public:
ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter);

Expand All @@ -43,6 +44,16 @@ class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface,
Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override;

Status KillProcess(lldb::pid_t pid) override;

static void Initialize();

static void Terminate();

static llvm::StringRef GetPluginNameStatic() {
return "ScriptedPlatformPythonInterface";
}

llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
};
} // namespace lldb_private

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_lldb_library(lldbPluginScriptInterpreterPythonScriptedProcessPythonInterface PLUGIN

ScriptedProcessPythonInterface.cpp

LINK_LIBS
lldbCore
lldbHost
lldbInterpreter
lldbTarget
lldbPluginScriptInterpreterPython
${Python3_LIBRARIES}
${LLDB_LIBEDIT_LIBS}

LINK_COMPONENTS
Support
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,37 @@
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"
#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../lldb-python.h"
#include "../../lldb-python.h"
//clang-format on
#endif

#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"

#if LLDB_ENABLE_PYTHON

#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"
#include "../../SWIGPythonBridge.h"
#include "../../ScriptInterpreterPythonImpl.h"
#include "../ScriptedThreadPythonInterface.h"
#include "ScriptedProcessPythonInterface.h"
#include "ScriptedThreadPythonInterface.h"

#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;
using Locker = ScriptInterpreterPythonImpl::Locker;

LLDB_PLUGIN_DEFINE_ADV(ScriptedProcessPythonInterface, ScriptInterpreterPythonScriptedProcessPythonInterface)

ScriptedProcessPythonInterface::ScriptedProcessPythonInterface(
ScriptInterpreterPythonImpl &interpreter)
: ScriptedProcessInterface(), ScriptedPythonInterface(interpreter) {}
Expand Down Expand Up @@ -208,4 +216,24 @@ StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() {
return dict;
}

void ScriptedProcessPythonInterface::Initialize() {
const std::vector<llvm::StringRef> ci_usages = {
"process attach -C <script-name> [-k key -v value ...]",
"process launch -C <script-name> [-k key -v value ...]"};
const std::vector<llvm::StringRef> api_usages = {
"SBAttachInfo.SetScriptedProcessClassName",
"SBAttachInfo.SetScriptedProcessDictionary",
"SBTarget.Attach",
"SBLaunchInfo.SetScriptedProcessClassName",
"SBLaunchInfo.SetScriptedProcessDictionary",
"SBTarget.Launch"};
PluginManager::RegisterPlugin(
GetPluginNameStatic(), llvm::StringRef("Mock process state"),
CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
}

void ScriptedProcessPythonInterface::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPROCESSPYTHONINTERFACE_H

#include "lldb/Host/Config.h"
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"

#if LLDB_ENABLE_PYTHON

#include "ScriptedPythonInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
#include "../ScriptedPythonInterface.h"

#include <optional>

namespace lldb_private {
class ScriptedProcessPythonInterface : public ScriptedProcessInterface,
public ScriptedPythonInterface {
public ScriptedPythonInterface,
public PluginInterface {
public:
ScriptedProcessPythonInterface(ScriptInterpreterPythonImpl &interpreter);

Expand Down Expand Up @@ -67,6 +69,16 @@ class ScriptedProcessPythonInterface : public ScriptedProcessInterface,

StructuredData::DictionarySP GetMetadata() override;

static void Initialize();

static void Terminate();

static llvm::StringRef GetPluginNameStatic() {
return "ScriptedProcessPythonInterface";
}

llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }

private:
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
add_lldb_library(lldbPluginScriptInterpreterPythonScriptedThreadPlanPythonInterface PLUGIN

ScriptedThreadPlanPythonInterface.cpp

LINK_LIBS
lldbCore
lldbHost
lldbInterpreter
lldbTarget
lldbPluginScriptInterpreterPython
${Python3_LIBRARIES}
${LLDB_LIBEDIT_LIBS}

LINK_COMPONENTS
Support
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,28 @@
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/PluginManager.h"
#include "lldb/Host/Config.h"
#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"

#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../lldb-python.h"
#include "../../lldb-python.h"
//clang-format on

#include "../SWIGPythonBridge.h"
#include "../ScriptInterpreterPythonImpl.h"
#include "../../SWIGPythonBridge.h"
#include "../../ScriptInterpreterPythonImpl.h"
#include "ScriptedThreadPlanPythonInterface.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::python;

LLDB_PLUGIN_DEFINE_ADV(ScriptedThreadPlanPythonInterface, ScriptInterpreterPythonScriptedThreadPlanPythonInterface)

ScriptedThreadPlanPythonInterface::ScriptedThreadPlanPythonInterface(
ScriptInterpreterPythonImpl &interpreter)
: ScriptedThreadPlanInterface(), ScriptedPythonInterface(interpreter) {}
Expand Down Expand Up @@ -102,4 +107,19 @@ ScriptedThreadPlanPythonInterface::GetStopDescription(lldb::StreamSP &stream) {
return llvm::Error::success();
}

void ScriptedThreadPlanPythonInterface::Initialize() {
const std::vector<llvm::StringRef> ci_usages = {
"thread step-scripted -C <script-name> [-k key -v value ...]"};
const std::vector<llvm::StringRef> api_usages = {
"SBThread.StepUsingScriptedThreadPlan"};
PluginManager::RegisterPlugin(
GetPluginNameStatic(),
llvm::StringRef("Alter thread stepping logic and stop reason"),
CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
}

void ScriptedThreadPlanPythonInterface::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDTHREADPLANPYTHONINTERFACE_H

#if LLDB_ENABLE_PYTHON

// clang-format off
// LLDB Python header must be included first
#include "../../lldb-python.h"
//clang-format on

#endif

#include "lldb/Host/Config.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"

#if LLDB_ENABLE_PYTHON

#include "ScriptedPythonInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadPlanInterface.h"
#include "../ScriptedPythonInterface.h"

#include <optional>

namespace lldb_private {
class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface,
public ScriptedPythonInterface {
public ScriptedPythonInterface,
public PluginInterface {
public:
ScriptedThreadPlanPythonInterface(ScriptInterpreterPythonImpl &interpreter);

Expand All @@ -41,6 +52,16 @@ class ScriptedThreadPlanPythonInterface : public ScriptedThreadPlanInterface,
lldb::StateType GetRunState() override;

llvm::Error GetStopDescription(lldb::StreamSP &stream) override;

static void Initialize();

static void Terminate();

static llvm::StringRef GetPluginNameStatic() {
return "ScriptedThreadPlanPythonInterface";
}

llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
};
} // namespace lldb_private

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
// LLDB Python header must be included first
#include "lldb-python.h"

#include "Interfaces/OperatingSystemPythonInterface.h"
#include "Interfaces/ScriptedPlatformPythonInterface.h"
#include "Interfaces/ScriptedProcessPythonInterface.h"
#include "Interfaces/ScriptedThreadPlanPythonInterface.h"
#include "Interfaces/OperatingSystemPythonInterface/OperatingSystemPythonInterface.h"
#include "Interfaces/ScriptedPlatformPythonInterface/ScriptedPlatformPythonInterface.h"
#include "Interfaces/ScriptedProcessPythonInterface/ScriptedProcessPythonInterface.h"
#include "Interfaces/ScriptedThreadPlanPythonInterface/ScriptedThreadPlanPythonInterface.h"
#include "Interfaces/ScriptedThreadPythonInterface.h"
#include "PythonDataObjects.h"
#include "PythonReadline.h"
Expand Down
2 changes: 1 addition & 1 deletion lldb/test/API/assert_messages_test/TestAssertMessages.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def assert_expect_fails_with(self, cmd, expect_args, expected_msg):
else:
self.fail("Initial expect should have raised AssertionError!")

@expectedFailureAll(remote=True)
@expectedFailureAll(oslist=no_match(["linux"]), remote=True)
def test_createTestTarget(self):
try:
self.createTestTarget("doesnt_exist")
Expand Down
4 changes: 0 additions & 4 deletions llvm/bindings/ocaml/llvm/llvm.mli
Original file line number Diff line number Diff line change
Expand Up @@ -760,10 +760,6 @@ val void_type : llcontext -> lltype
[llvm::Type::LabelTy]. *)
val label_type : llcontext -> lltype

(** [x86_mmx_type c] returns the x86 64-bit MMX register type in the
context [c]. See [llvm::Type::X86_MMXTy]. *)
val x86_mmx_type : llcontext -> lltype

(** [type_by_name m name] returns the specified type from the current module
if it exists.
See the method [llvm::Module::getTypeByName] *)
Expand Down
5 changes: 0 additions & 5 deletions llvm/bindings/ocaml/llvm/llvm_ocaml.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,11 +686,6 @@ value llvm_label_type(value Context) {
return to_val(LLVMLabelTypeInContext(Context_val(Context)));
}

/* llcontext -> lltype */
value llvm_x86_mmx_type(value Context) {
return to_val(LLVMX86MMXTypeInContext(Context_val(Context)));
}

/* llmodule -> string -> lltype option */
value llvm_type_by_name(value M, value Name) {
return ptr_to_option(LLVMGetTypeByName(Module_val(M), String_val(Name)));
Expand Down
1 change: 0 additions & 1 deletion llvm/cmake/modules/LLVMExternalProjectUtils.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ function(llvm_ExternalProject_Add name source_dir)
${sysroot_arg}
-DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
-DLLVM_CONFIG_PATH=${llvm_config_path}
-DLLVM_CMAKE_DIR=${LLVM_CMAKE_DIR}
-DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
-DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
-DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
Expand Down
2 changes: 1 addition & 1 deletion llvm/docs/BitCodeFormat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ TYPE_CODE_X86_MMX Record

``[X86_MMX]``

The ``X86_MMX`` record (code 17) adds an ``x86_mmx`` type to the type table.
The ``X86_MMX`` record (code 17) is deprecated, and imported as a <1 x i64> vector.

TYPE_CODE_STRUCT_ANON Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
20 changes: 1 addition & 19 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3945,24 +3945,6 @@ or constants of this type.
x86_amx


X86_mmx Type
""""""""""""

:Overview:

The x86_mmx type represents a value held in an MMX register on an x86
machine. The operations allowed on it are quite limited: parameters and
return values, load and store, and bitcast. User-specified MMX
instructions are represented as intrinsic or asm calls with arguments
and/or results of this type. There are no arrays, vectors or constants
of this type.

:Syntax:

::

x86_mmx


.. _t_pointer:

Expand Down Expand Up @@ -4396,7 +4378,7 @@ represented by ``0xH`` followed by 4 hexadecimal digits. The bfloat 16-bit
format is represented by ``0xR`` followed by 4 hexadecimal digits. All
hexadecimal formats are big-endian (sign bit at the left).

There are no constants of type x86_mmx and x86_amx.
There are no constants of type x86_amx.

.. _complexconstants:

Expand Down
15 changes: 15 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ Update on required toolchains to build LLVM
Changes to the LLVM IR
----------------------

* The ``x86_mmx`` IR type has been removed. It will be translated to
the standard vector type ``<1 x i64>`` in bitcode upgrade.

Changes to LLVM infrastructure
------------------------------

Expand Down Expand Up @@ -120,6 +123,12 @@ Changes to the X86 Backend
encoding. To use optimised NOP filling in a code section, leave off the
"fillval" argument, i.e. `.balign N`, `.p2align N` or `.align N` respectively.

* Due to the removal of the ``x86_mmx`` IR type, functions with
``x86_mmx`` arguments or return values will use a different,
incompatible, calling convention ABI. Such functions are not
generally seen in the wild (Clang never generates them!), so this is
not expected to result in real-world compatibility problems.

Changes to the OCaml bindings
-----------------------------

Expand All @@ -129,6 +138,12 @@ Changes to the Python bindings
Changes to the C API
--------------------

* The following symbols are deleted due to the removal of the ``x86_mmx`` IR type:

* ``LLVMX86_MMXTypeKind``
* ``LLVMX86MMXTypeInContext``
* ``LLVMX86MMXType``

Changes to the CodeGen infrastructure
-------------------------------------

Expand Down
48 changes: 21 additions & 27 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,27 +146,27 @@ typedef enum {
} LLVMOpcode;

typedef enum {
LLVMVoidTypeKind, /**< type with no size */
LLVMHalfTypeKind, /**< 16 bit floating point type */
LLVMFloatTypeKind, /**< 32 bit floating point type */
LLVMDoubleTypeKind, /**< 64 bit floating point type */
LLVMX86_FP80TypeKind, /**< 80 bit floating point type (X87) */
LLVMFP128TypeKind, /**< 128 bit floating point type (112-bit mantissa)*/
LLVMPPC_FP128TypeKind, /**< 128 bit floating point type (two 64-bits) */
LLVMLabelTypeKind, /**< Labels */
LLVMIntegerTypeKind, /**< Arbitrary bit width integers */
LLVMFunctionTypeKind, /**< Functions */
LLVMStructTypeKind, /**< Structures */
LLVMArrayTypeKind, /**< Arrays */
LLVMPointerTypeKind, /**< Pointers */
LLVMVectorTypeKind, /**< Fixed width SIMD vector type */
LLVMMetadataTypeKind, /**< Metadata */
LLVMX86_MMXTypeKind, /**< X86 MMX */
LLVMTokenTypeKind, /**< Tokens */
LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */
LLVMBFloatTypeKind, /**< 16 bit brain floating point type */
LLVMX86_AMXTypeKind, /**< X86 AMX */
LLVMTargetExtTypeKind, /**< Target extension type */
LLVMVoidTypeKind = 0, /**< type with no size */
LLVMHalfTypeKind = 1, /**< 16 bit floating point type */
LLVMFloatTypeKind = 2, /**< 32 bit floating point type */
LLVMDoubleTypeKind = 3, /**< 64 bit floating point type */
LLVMX86_FP80TypeKind = 4, /**< 80 bit floating point type (X87) */
LLVMFP128TypeKind = 5, /**< 128 bit floating point type (112-bit mantissa)*/
LLVMPPC_FP128TypeKind = 6, /**< 128 bit floating point type (two 64-bits) */
LLVMLabelTypeKind = 7, /**< Labels */
LLVMIntegerTypeKind = 8, /**< Arbitrary bit width integers */
LLVMFunctionTypeKind = 9, /**< Functions */
LLVMStructTypeKind = 10, /**< Structures */
LLVMArrayTypeKind = 11, /**< Arrays */
LLVMPointerTypeKind = 12, /**< Pointers */
LLVMVectorTypeKind = 13, /**< Fixed width SIMD vector type */
LLVMMetadataTypeKind = 14, /**< Metadata */
/* 15 previously used by LLVMX86_MMXTypeKind */
LLVMTokenTypeKind = 16, /**< Tokens */
LLVMScalableVectorTypeKind = 17, /**< Scalable SIMD vector type */
LLVMBFloatTypeKind = 18, /**< 16 bit brain floating point type */
LLVMX86_AMXTypeKind = 19, /**< X86 AMX */
LLVMTargetExtTypeKind = 20, /**< Target extension type */
} LLVMTypeKind;

typedef enum {
Expand Down Expand Up @@ -1716,11 +1716,6 @@ LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C);
*/
LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C);

/**
* Create a X86 MMX type in a context.
*/
LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C);

/**
* Create a X86 AMX type in a context.
*/
Expand All @@ -1742,7 +1737,6 @@ LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C);
*/
LLVMTypeRef LLVMVoidType(void);
LLVMTypeRef LLVMLabelType(void);
LLVMTypeRef LLVMX86MMXType(void);
LLVMTypeRef LLVMX86AMXType(void);

/**
Expand Down
4 changes: 2 additions & 2 deletions llvm/include/llvm/ADT/DenseMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ class DenseMapBase : public DebugEpochBase {
}

bool erase(const KeyT &Val) {
BucketT *TheBucket;
if (!LookupBucketFor(Val, TheBucket))
BucketT *TheBucket = doFind(Val);
if (!TheBucket)
return false; // not in map.

TheBucket->getSecond().~ValueT();
Expand Down
Loading