Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,6 @@ struct MissingFeatures {
// specs. We should make it always present.
static bool makeTripleAlwaysPresent() { return false; }

// This Itanium bit is currently being skipped in cir.
static bool itaniumRecordLayoutBuilderFinishLayout() { return false; }

static bool mustProgress() { return false; }
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,31 @@ mlir::Value emitAddressAtOffset(LowerFunction &LF, mlir::Value addr,
return addr;
}

/// Creates a coerced value from \param Src having a type of \param Ty which is
/// a non primitive type
mlir::Value createCoercedNonPrimitive(mlir::Value Src, mlir::Type Ty,
LowerFunction &LF) {
if (auto load = mlir::dyn_cast<LoadOp>(Src.getDefiningOp())) {
auto &bld = LF.getRewriter();
auto addr = load.getAddr();

auto oldAlloca = mlir::dyn_cast<AllocaOp>(addr.getDefiningOp());
auto alloca = bld.create<AllocaOp>(
Src.getLoc(), bld.getType<PointerType>(Ty), Ty,
/*name=*/llvm::StringRef(""), oldAlloca.getAlignmentAttr());

auto tySize = LF.LM.getDataLayout().getTypeStoreSize(Ty);
createMemCpy(LF, alloca, addr, tySize.getFixedValue());

auto newLoad = bld.create<LoadOp>(Src.getLoc(), alloca.getResult());
bld.replaceAllOpUsesWith(load, newLoad);

return newLoad;
}

cir_cconv_unreachable("NYI");
}

/// After the calling convention is lowered, an ABI-agnostic type might have to
/// be loaded back to its ABI-aware couterpart so it may be returned. If they
/// differ, we have to do a coerced load. A coerced load, which means to load a
Expand All @@ -351,7 +376,8 @@ mlir::Value castReturnValue(mlir::Value Src, mlir::Type Ty, LowerFunction &LF) {

auto intTy = mlir::dyn_cast<IntType>(Ty);
if (intTy && !intTy.isPrimitive())
cir_cconv_unreachable("non-primitive types NYI");
return createCoercedNonPrimitive(Src, Ty, LF);

llvm::TypeSize DstSize = LF.LM.getDataLayout().getTypeAllocSize(Ty);

// FIXME(cir): Do we need the EnterStructPointerForCoercedAccess routine here?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ class ItaniumRecordLayoutBuilder {
/// Initialize record layout for the given record decl.
void initializeLayout(const Type Ty);

/// Finalize record layout. Adjust record size based on the alignment.
void finishLayout(const StructType D);

uint64_t getDataSizeInBits() const { return DataSize; }

void setDataSize(clang::CharUnits NewSize) {
Expand All @@ -243,8 +246,7 @@ void ItaniumRecordLayoutBuilder::layout(const StructType RT) {
// FIXME(cir): Handle virtual-related layouts.
cir_cconv_assert(!cir::MissingFeatures::getCXXRecordBases());

cir_cconv_assert(
!cir::MissingFeatures::itaniumRecordLayoutBuilderFinishLayout());
finishLayout(RT);
}

void ItaniumRecordLayoutBuilder::initializeLayout(const mlir::Type Ty) {
Expand Down Expand Up @@ -478,6 +480,31 @@ void ItaniumRecordLayoutBuilder::layoutFields(const StructType D) {
}
}

void ItaniumRecordLayoutBuilder::finishLayout(const StructType D) {
// If we have any remaining field tail padding, include that in the overall
// size.
setSize(std::max(getSizeInBits(), (uint64_t)Context.toBits(PaddedFieldSize)));

// Finally, round the size of the record up to the alignment of the
// record itself.
uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
uint64_t UnpackedSizeInBits =
llvm::alignTo(getSizeInBits(), Context.toBits(UnpackedAlignment));

uint64_t RoundedSize = llvm::alignTo(
getSizeInBits(),
Context.toBits(!Context.getTargetInfo().defaultsToAIXPowerAlignment()
? Alignment
: PreferredAlignment));

if (UseExternalLayout) {
cir_cconv_unreachable("NYI");
}

// Set the size to the final size.
setSize(RoundedSize);
}

void ItaniumRecordLayoutBuilder::UpdateAlignment(
clang::CharUnits NewAlignment, clang::CharUnits UnpackedNewAlignment,
clang::CharUnits PreferredNewAlignment) {
Expand Down Expand Up @@ -522,12 +549,12 @@ void ItaniumRecordLayoutBuilder::checkFieldPadding(
// Warn if padding was introduced to the struct/class.
if (!IsUnion && Offset > UnpaddedOffset) {
unsigned PadSize = Offset - UnpaddedOffset;
// bool InBits = true;
bool InBits = true;
if (PadSize % CharBitNum == 0) {
PadSize = PadSize / CharBitNum;
// InBits = false;
InBits = false;
}
cir_cconv_assert(cir::MissingFeatures::bitFieldPaddingDiagnostics());
cir_cconv_assert(!cir::MissingFeatures::bitFieldPaddingDiagnostics());
}
if (isPacked && Offset != UnpackedOffset) {
HasPackedField = true;
Expand Down
31 changes: 30 additions & 1 deletion clang/test/CIR/CallConvLowering/AArch64/aarch64-cc-structs.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,33 @@ void pass_gt_128(GT_128 s) {}
// LLVM: %[[#V2:]] = alloca [2 x i64], i64 1, align 8
// LLVM: store [2 x i64] %[[#ARG]], ptr %[[#V2]], align 8
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[#V1]], ptr %[[#V2]], i64 12, i1 false)
void passS(S s) {}
void passS(S s) {}

typedef struct {
uint8_t a;
uint16_t b;
uint8_t c;
} S_PAD;

// CHECK: cir.func {{.*@ret_s_pad}}() -> !u48i
// CHECK: %[[#V0:]] = cir.alloca !ty_S_PAD, !cir.ptr<!ty_S_PAD>, ["__retval"] {alignment = 2 : i64}
// CHECK: %[[#V1:]] = cir.load %[[#V0]] : !cir.ptr<!ty_S_PAD>, !ty_S_PAD
// CHECK: %[[#V2:]] = cir.alloca !u48i, !cir.ptr<!u48i>, [""] {alignment = 2 : i64}
// CHECK: %[[#V3:]] = cir.cast(bitcast, %[[#V0]] : !cir.ptr<!ty_S_PAD>)
// CHECK: %[[#V4:]] = cir.cast(bitcast, %[[#V2:]] : !cir.ptr<!u48i>), !cir.ptr<!void>
// CHECK: %[[#V5:]] = cir.const #cir.int<6> : !u64i
// CHECK: cir.libc.memcpy %[[#V5]] bytes from %[[#V3]] to %[[#V4]] : !u64i, !cir.ptr<!void>
// CHECK: %[[#V6:]] = cir.load %[[#V2]] : !cir.ptr<!u48i>
// CHECK: cir.return %[[#V6]]

// LLVM: i48 @ret_s_pad()
// LLVM: %[[#V1:]] = alloca %struct.S_PAD, i64 1, align 2
// LLVM: %[[#V2:]] = load %struct.S_PAD, ptr %[[#V1]], align 2
// LLVM: %[[#V3:]] = alloca i48, i64 1, align 2
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[#V3]], ptr %[[#V1]], i64 6, i1 false)
// LLVM: %[[#V4:]] = load i48, ptr %[[#V3]]
// LLVM: ret i48 %[[#V4]]
S_PAD ret_s_pad() {
S_PAD s;
return s;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+EOL