[clang][SPARC] Pass 16-aligned structs with the correct alignment in … · llvm/llvm-project@9ee4ac8 (original) (raw)

`@@ -8,6 +8,7 @@

`

8

8

``

9

9

`#include "ABIInfoImpl.h"

`

10

10

`#include "TargetInfo.h"

`

``

11

`+

#include

`

11

12

``

12

13

`using namespace clang;

`

13

14

`using namespace clang::CodeGen;

`

`@@ -109,7 +110,8 @@ class SparcV9ABIInfo : public ABIInfo {

`

109

110

`SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}

`

110

111

``

111

112

`private:

`

112

``

`-

ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;

`

``

113

`+

ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit,

`

``

114

`+

unsigned &RegOffset) const;

`

113

115

`void computeInfo(CGFunctionInfo &FI) const override;

`

114

116

` RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,

`

115

117

` AggValueSlot Slot) const override;

`

`@@ -222,127 +224,114 @@ class SparcV9ABIInfo : public ABIInfo {

`

222

224

`};

`

223

225

`} // end anonymous namespace

`

224

226

``

225

``

`-

ABIArgInfo

`

226

``

`-

SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {

`

``

227

`+

ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,

`

``

228

`+

unsigned &RegOffset) const {

`

227

229

`if (Ty->isVoidType())

`

228

230

`return ABIArgInfo::getIgnore();

`

229

231

``

230

``

`-

uint64_t Size = getContext().getTypeSize(Ty);

`

``

232

`+

auto &Context = getContext();

`

``

233

`+

auto &VMContext = getVMContext();

`

``

234

+

``

235

`+

uint64_t Size = Context.getTypeSize(Ty);

`

``

236

`+

unsigned Alignment = Context.getTypeAlign(Ty);

`

``

237

`+

bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0);

`

231

238

``

232

239

`// Anything too big to fit in registers is passed with an explicit indirect

`

233

240

`// pointer / sret pointer.

`

234

``

`-

if (Size > SizeLimit)

`

``

241

`+

if (Size > SizeLimit) {

`

``

242

`+

RegOffset += 1;

`

235

243

`return getNaturalAlignIndirect(

`

236

244

` Ty, /AddrSpace=/getDataLayout().getAllocaAddrSpace(),

`

237

245

`/ByVal=/false);

`

``

246

`+

}

`

238

247

``

239

248

`// Treat an enum type as its underlying type.

`

240

249

`if (const EnumType *EnumTy = Ty->getAs())

`

241

250

` Ty = EnumTy->getDecl()->getIntegerType();

`

242

251

``

243

252

`// Integer types smaller than a register are extended.

`

244

``

`-

if (Size < 64 && Ty->isIntegerType())

`

``

253

`+

if (Size < 64 && Ty->isIntegerType()) {

`

``

254

`+

RegOffset += 1;

`

245

255

`return ABIArgInfo::getExtend(Ty);

`

``

256

`+

}

`

246

257

``

247

258

`if (const auto *EIT = Ty->getAs())

`

248

``

`-

if (EIT->getNumBits() < 64)

`

``

259

`+

if (EIT->getNumBits() < 64) {

`

``

260

`+

RegOffset += 1;

`

249

261

`return ABIArgInfo::getExtend(Ty);

`

``

262

`+

}

`

250

263

``

251

264

`// Other non-aggregates go in registers.

`

252

``

`-

if (!isAggregateTypeForABI(Ty))

`

``

265

`+

if (!isAggregateTypeForABI(Ty)) {

`

``

266

`+

RegOffset += Size / 64;

`

253

267

`return ABIArgInfo::getDirect();

`

``

268

`+

}

`

254

269

``

255

270

`// If a C++ object has either a non-trivial copy constructor or a non-trivial

`

256

271

`// destructor, it is passed with an explicit indirect pointer / sret pointer.

`

257

``

`-

if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))

`

``

272

`+

if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {

`

``

273

`+

RegOffset += 1;

`

258

274

`return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),

`

259

275

` RAA == CGCXXABI::RAA_DirectInMemory);

`

``

276

`+

}

`

260

277

``

261

278

`// This is a small aggregate type that should be passed in registers.

`

262

279

`// Build a coercion type from the LLVM struct type.

`

263

280

` llvm::StructType *StrTy = dyn_castllvm::StructType(CGT.ConvertType(Ty));

`

264

``

`-

if (!StrTy)

`

``

281

`+

if (!StrTy) {

`

``

282

`+

RegOffset += Size / 64;

`

265

283

`return ABIArgInfo::getDirect();

`

``

284

`+

}

`

266

285

``

267

``

`-

CoerceBuilder CB(getVMContext(), getDataLayout());

`

``

286

`+

CoerceBuilder CB(VMContext, getDataLayout());

`

268

287

` CB.addStruct(0, StrTy);

`

269

288

`// All structs, even empty ones, should take up a register argument slot,

`

270

289

`// so pin the minimum struct size to one bit.

`

271

290

` CB.pad(llvm::alignTo(

`

272

291

`std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),

`

273

292

`64));

`

``

293

`+

RegOffset += CB.Size / 64;

`

``

294

+

``

295

`+

// If we're dealing with overaligned structs we may need to add a padding in

`

``

296

`+

// the front, to preserve the correct register-memory mapping.

`

``

297

`+

//

`

``

298

`+

// See SCD 2.4.1, pages 3P-11 and 3P-12.

`

``

299

`+

llvm::Type *Padding =

`

``

300

`+

NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr;

`

``

301

`+

RegOffset += NeedPadding ? 1 : 0;

`

274

302

``

275

303

`// Try to use the original type for coercion.

`

276

304

` llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();

`

277

305

``

278

``

`-

if (CB.InReg)

`

279

``

`-

return ABIArgInfo::getDirectInReg(CoerceTy);

`

280

``

`-

else

`

281

``

`-

return ABIArgInfo::getDirect(CoerceTy);

`

``

306

`+

ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);

`

``

307

`+

AAI.setInReg(CB.InReg);

`

``

308

`+

return AAI;

`

282

309

`}

`

283

310

``

284

311

`RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,

`

285

312

` QualType Ty, AggValueSlot Slot) const {

`

286

``

`-

ABIArgInfo AI = classifyType(Ty, 16 * 8);

`

287

``

`-

llvm::Type *ArgTy = CGT.ConvertType(Ty);

`

288

``

`-

if (AI.canHaveCoerceToType() && !AI.getCoerceToType())

`

289

``

`-

AI.setCoerceToType(ArgTy);

`

290

``

-

291

313

` CharUnits SlotSize = CharUnits::fromQuantity(8);

`

``

314

`+

auto TInfo = getContext().getTypeInfoInChars(Ty);

`

292

315

``

293

``

`-

CGBuilderTy &Builder = CGF.Builder;

`

294

``

`-

Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"),

`

295

``

`-

getVAListElementType(CGF), SlotSize);

`

296

``

`-

llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;

`

297

``

-

298

``

`-

auto TypeInfo = getContext().getTypeInfoInChars(Ty);

`

299

``

-

300

``

`-

Address ArgAddr = Address::invalid();

`

301

``

`-

CharUnits Stride;

`

302

``

`-

switch (AI.getKind()) {

`

303

``

`-

case ABIArgInfo::Expand:

`

304

``

`-

case ABIArgInfo::CoerceAndExpand:

`

305

``

`-

case ABIArgInfo::InAlloca:

`

306

``

`-

llvm_unreachable("Unsupported ABI kind for va_arg");

`

307

``

-

308

``

`-

case ABIArgInfo::Extend: {

`

309

``

`-

Stride = SlotSize;

`

310

``

`-

CharUnits Offset = SlotSize - TypeInfo.Width;

`

311

``

`-

ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");

`

312

``

`-

break;

`

313

``

`-

}

`

314

``

-

315

``

`-

case ABIArgInfo::Direct: {

`

316

``

`-

auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());

`

317

``

`-

Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);

`

318

``

`-

ArgAddr = Addr;

`

319

``

`-

break;

`

320

``

`-

}

`

321

``

-

322

``

`-

case ABIArgInfo::Indirect:

`

323

``

`-

case ABIArgInfo::IndirectAliased:

`

324

``

`-

Stride = SlotSize;

`

325

``

`-

ArgAddr = Addr.withElementType(ArgPtrTy);

`

326

``

`-

ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,

`

327

``

`-

TypeInfo.Align);

`

328

``

`-

break;

`

``

316

`+

// Zero-sized types have a width of one byte for parameter passing purposes.

`

``

317

`+

TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));

`

329

318

``

330

``

`-

case ABIArgInfo::Ignore:

`

331

``

`-

return Slot.asRValue();

`

332

``

`-

}

`

333

``

-

334

``

`-

// Update VAList.

`

335

``

`-

Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, "ap.next");

`

336

``

`-

Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);

`

337

``

-

338

``

`-

return CGF.EmitLoadOfAnyValue(

`

339

``

`-

CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot);

`

``

319

`+

// Arguments bigger than 2*SlotSize bytes are passed indirectly.

`

``

320

`+

return emitVoidPtrVAArg(CGF, VAListAddr, Ty,

`

``

321

`+

/IsIndirect=/TInfo.Width > 2 * SlotSize, TInfo,

`

``

322

`+

SlotSize,

`

``

323

`+

/AllowHigherAlign=/true, Slot);

`

340

324

`}

`

341

325

``

342

326

`void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {

`

343

``

`-

FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);

`

``

327

`+

unsigned RetOffset = 0;

`

``

328

`+

ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset);

`

``

329

`+

FI.getReturnInfo() = RetType;

`

``

330

+

``

331

`+

// Indirect returns will have its pointer passed as an argument.

`

``

332

`+

unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0;

`

344

333

`for (auto &I : FI.arguments())

`

345

``

`-

I.info = classifyType(I.type, 16 * 8);

`

``

334

`+

I.info = classifyType(I.type, 16 * 8, ArgOffset);

`

346

335

`}

`

347

336

``

348

337

`namespace {

`