423 lines · cpp
1//===- Sparc.cpp ----------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10#include "TargetInfo.h"11#include <algorithm>12 13using namespace clang;14using namespace clang::CodeGen;15 16//===----------------------------------------------------------------------===//17// SPARC v8 ABI Implementation.18// Based on the SPARC Compliance Definition version 2.4.1.19//20// Ensures that complex values are passed in registers.21//22namespace {23class SparcV8ABIInfo : public DefaultABIInfo {24public:25 SparcV8ABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}26 27private:28 ABIArgInfo classifyReturnType(QualType RetTy) const;29 ABIArgInfo classifyArgumentType(QualType Ty) const;30 void computeInfo(CGFunctionInfo &FI) const override;31};32} // end anonymous namespace33 34ABIArgInfo SparcV8ABIInfo::classifyReturnType(QualType Ty) const {35 const auto *CT = Ty->getAs<ComplexType>();36 const auto *BT = Ty->getAs<BuiltinType>();37 if (CT)38 BT = CT->getElementType()->getAs<BuiltinType>();39 bool IsLongDouble = BT && BT->getKind() == BuiltinType::LongDouble;40 41 // long double _Complex is special in that it should be marked as inreg.42 if (CT)43 return IsLongDouble ? ABIArgInfo::getDirectInReg()44 : ABIArgInfo::getDirect();45 46 if (IsLongDouble)47 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),48 /*ByVal=*/false);49 50 return DefaultABIInfo::classifyReturnType(Ty);51}52 53ABIArgInfo SparcV8ABIInfo::classifyArgumentType(QualType Ty) const {54 if (const auto *BT = Ty->getAs<BuiltinType>();55 BT && BT->getKind() == BuiltinType::LongDouble)56 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());57 58 return DefaultABIInfo::classifyArgumentType(Ty);59}60 61void SparcV8ABIInfo::computeInfo(CGFunctionInfo &FI) const {62 FI.getReturnInfo() = classifyReturnType(FI.getReturnType());63 for (auto &Arg : FI.arguments())64 Arg.info = classifyArgumentType(Arg.type);65}66 67namespace {68class SparcV8TargetCodeGenInfo : public TargetCodeGenInfo {69public:70 SparcV8TargetCodeGenInfo(CodeGenTypes &CGT)71 : TargetCodeGenInfo(std::make_unique<SparcV8ABIInfo>(CGT)) {}72 73 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,74 llvm::Value *Address) const override {75 int Offset;76 if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))77 Offset = 12;78 else79 Offset = 8;80 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,81 llvm::ConstantInt::get(CGF.Int32Ty, Offset));82 }83 84 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,85 llvm::Value *Address) const override {86 int Offset;87 if (isAggregateTypeForABI(CGF.CurFnInfo->getReturnType()))88 Offset = -12;89 else90 Offset = -8;91 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,92 llvm::ConstantInt::get(CGF.Int32Ty, Offset));93 }94};95} // end anonymous namespace96 97//===----------------------------------------------------------------------===//98// SPARC v9 ABI Implementation.99// Based on the SPARC Compliance Definition version 2.4.1.100//101// Function arguments a mapped to a nominal "parameter array" and promoted to102// registers depending on their type. Each argument occupies 8 or 16 bytes in103// the array, structs larger than 16 bytes are passed indirectly.104//105// One case requires special care:106//107// struct mixed {108// int i;109// float f;110// };111//112// When a struct mixed is passed by value, it only occupies 8 bytes in the113// parameter array, but the int is passed in an integer register, and the float114// is passed in a floating point register. This is represented as two arguments115// with the LLVM IR inreg attribute:116//117// declare void f(i32 inreg %i, float inreg %f)118//119// The code generator will only allocate 4 bytes from the parameter array for120// the inreg arguments. All other arguments are allocated a multiple of 8121// bytes.122//123namespace {124class SparcV9ABIInfo : public ABIInfo {125public:126 SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}127 128private:129 ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit,130 unsigned &RegOffset) const;131 void computeInfo(CGFunctionInfo &FI) const override;132 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,133 AggValueSlot Slot) const override;134 135 // Coercion type builder for structs passed in registers. The coercion type136 // serves two purposes:137 //138 // 1. Pad structs to a multiple of 64 bits, so they are passed 'left-aligned'139 // in registers.140 // 2. Expose aligned floating point elements as first-level elements, so the141 // code generator knows to pass them in floating point registers.142 //143 // We also compute the InReg flag which indicates that the struct contains144 // aligned 32-bit floats.145 //146 struct CoerceBuilder {147 llvm::LLVMContext &Context;148 const llvm::DataLayout &DL;149 SmallVector<llvm::Type*, 8> Elems;150 uint64_t Size;151 bool InReg;152 153 CoerceBuilder(llvm::LLVMContext &c, const llvm::DataLayout &dl)154 : Context(c), DL(dl), Size(0), InReg(false) {}155 156 // Pad Elems with integers until Size is ToSize.157 void pad(uint64_t ToSize) {158 assert(ToSize >= Size && "Cannot remove elements");159 if (ToSize == Size)160 return;161 162 // Finish the current 64-bit word.163 uint64_t Aligned = llvm::alignTo(Size, 64);164 if (Aligned > Size && Aligned <= ToSize) {165 Elems.push_back(llvm::IntegerType::get(Context, Aligned - Size));166 Size = Aligned;167 }168 169 // Add whole 64-bit words.170 while (Size + 64 <= ToSize) {171 Elems.push_back(llvm::Type::getInt64Ty(Context));172 Size += 64;173 }174 175 // Final in-word padding.176 if (Size < ToSize) {177 Elems.push_back(llvm::IntegerType::get(Context, ToSize - Size));178 Size = ToSize;179 }180 }181 182 // Add a floating point element at Offset.183 void addFloat(uint64_t Offset, llvm::Type *Ty, unsigned Bits) {184 // Unaligned floats are treated as integers.185 if (Offset % Bits)186 return;187 // The InReg flag is only required if there are any floats < 64 bits.188 if (Bits < 64)189 InReg = true;190 pad(Offset);191 Elems.push_back(Ty);192 Size = Offset + Bits;193 }194 195 // Add a struct type to the coercion type, starting at Offset (in bits).196 void addStruct(uint64_t Offset, llvm::StructType *StrTy) {197 const llvm::StructLayout *Layout = DL.getStructLayout(StrTy);198 for (unsigned i = 0, e = StrTy->getNumElements(); i != e; ++i) {199 llvm::Type *ElemTy = StrTy->getElementType(i);200 uint64_t ElemOffset = Offset + Layout->getElementOffsetInBits(i);201 switch (ElemTy->getTypeID()) {202 case llvm::Type::StructTyID:203 addStruct(ElemOffset, cast<llvm::StructType>(ElemTy));204 break;205 case llvm::Type::FloatTyID:206 addFloat(ElemOffset, ElemTy, 32);207 break;208 case llvm::Type::DoubleTyID:209 addFloat(ElemOffset, ElemTy, 64);210 break;211 case llvm::Type::FP128TyID:212 addFloat(ElemOffset, ElemTy, 128);213 break;214 case llvm::Type::PointerTyID:215 if (ElemOffset % 64 == 0) {216 pad(ElemOffset);217 Elems.push_back(ElemTy);218 Size += 64;219 }220 break;221 default:222 break;223 }224 }225 }226 227 // Check if Ty is a usable substitute for the coercion type.228 bool isUsableType(llvm::StructType *Ty) const {229 return llvm::ArrayRef(Elems) == Ty->elements();230 }231 232 // Get the coercion type as a literal struct type.233 llvm::Type *getType() const {234 if (Elems.size() == 1)235 return Elems.front();236 else237 return llvm::StructType::get(Context, Elems);238 }239 };240};241} // end anonymous namespace242 243ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,244 unsigned &RegOffset) const {245 if (Ty->isVoidType())246 return ABIArgInfo::getIgnore();247 248 auto &Context = getContext();249 auto &VMContext = getVMContext();250 251 uint64_t Size = Context.getTypeSize(Ty);252 unsigned Alignment = Context.getTypeAlign(Ty);253 bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0);254 255 // Anything too big to fit in registers is passed with an explicit indirect256 // pointer / sret pointer.257 if (Size > SizeLimit) {258 RegOffset += 1;259 return getNaturalAlignIndirect(260 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),261 /*ByVal=*/false);262 }263 264 // Treat an enum type as its underlying type.265 if (const auto *ED = Ty->getAsEnumDecl())266 Ty = ED->getIntegerType();267 268 // Integer types smaller than a register are extended.269 if (Size < 64 && Ty->isIntegerType()) {270 RegOffset += 1;271 return ABIArgInfo::getExtend(Ty);272 }273 274 if (const auto *EIT = Ty->getAs<BitIntType>())275 if (EIT->getNumBits() < 64) {276 RegOffset += 1;277 return ABIArgInfo::getExtend(Ty);278 }279 280 // Other non-aggregates go in registers.281 if (!isAggregateTypeForABI(Ty)) {282 RegOffset += Size / 64;283 return ABIArgInfo::getDirect();284 }285 286 // If a C++ object has either a non-trivial copy constructor or a non-trivial287 // destructor, it is passed with an explicit indirect pointer / sret pointer.288 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {289 RegOffset += 1;290 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),291 RAA == CGCXXABI::RAA_DirectInMemory);292 }293 294 // This is a small aggregate type that should be passed in registers.295 // Build a coercion type from the LLVM struct type.296 llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));297 if (!StrTy) {298 RegOffset += Size / 64;299 return ABIArgInfo::getDirect();300 }301 302 CoerceBuilder CB(VMContext, getDataLayout());303 CB.addStruct(0, StrTy);304 // All structs, even empty ones, should take up a register argument slot,305 // so pin the minimum struct size to one bit.306 CB.pad(llvm::alignTo(307 std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),308 64));309 RegOffset += CB.Size / 64;310 311 // If we're dealing with overaligned structs we may need to add a padding in312 // the front, to preserve the correct register-memory mapping.313 //314 // See SCD 2.4.1, pages 3P-11 and 3P-12.315 llvm::Type *Padding =316 NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr;317 RegOffset += NeedPadding ? 1 : 0;318 319 // Try to use the original type for coercion.320 llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();321 322 ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);323 AAI.setInReg(CB.InReg);324 return AAI;325}326 327RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,328 QualType Ty, AggValueSlot Slot) const {329 CharUnits SlotSize = CharUnits::fromQuantity(8);330 auto TInfo = getContext().getTypeInfoInChars(Ty);331 332 // Zero-sized types have a width of one byte for parameter passing purposes.333 TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));334 335 // Arguments bigger than 2*SlotSize bytes are passed indirectly.336 return emitVoidPtrVAArg(CGF, VAListAddr, Ty,337 /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,338 SlotSize,339 /*AllowHigherAlign=*/true, Slot);340}341 342void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {343 unsigned RetOffset = 0;344 ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset);345 FI.getReturnInfo() = RetType;346 347 // Indirect returns will have its pointer passed as an argument.348 unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0;349 for (auto &I : FI.arguments())350 I.info = classifyType(I.type, 16 * 8, ArgOffset);351}352 353namespace {354class SparcV9TargetCodeGenInfo : public TargetCodeGenInfo {355public:356 SparcV9TargetCodeGenInfo(CodeGenTypes &CGT)357 : TargetCodeGenInfo(std::make_unique<SparcV9ABIInfo>(CGT)) {}358 359 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {360 return 14;361 }362 363 bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,364 llvm::Value *Address) const override;365 366 llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF,367 llvm::Value *Address) const override {368 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,369 llvm::ConstantInt::get(CGF.Int32Ty, 8));370 }371 372 llvm::Value *encodeReturnAddress(CodeGen::CodeGenFunction &CGF,373 llvm::Value *Address) const override {374 return CGF.Builder.CreateGEP(CGF.Int8Ty, Address,375 llvm::ConstantInt::get(CGF.Int32Ty, -8));376 }377};378} // end anonymous namespace379 380bool381SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,382 llvm::Value *Address) const {383 // This is calculated from the LLVM and GCC tables and verified384 // against gcc output. AFAIK all ABIs use the same encoding.385 386 CodeGen::CGBuilderTy &Builder = CGF.Builder;387 388 llvm::IntegerType *i8 = CGF.Int8Ty;389 llvm::Value *Four8 = llvm::ConstantInt::get(i8, 4);390 llvm::Value *Eight8 = llvm::ConstantInt::get(i8, 8);391 392 // 0-31: the 8-byte general-purpose registers393 AssignToArrayRange(Builder, Address, Eight8, 0, 31);394 395 // 32-63: f0-31, the 4-byte floating-point registers396 AssignToArrayRange(Builder, Address, Four8, 32, 63);397 398 // Y = 64399 // PSR = 65400 // WIM = 66401 // TBR = 67402 // PC = 68403 // NPC = 69404 // FSR = 70405 // CSR = 71406 AssignToArrayRange(Builder, Address, Eight8, 64, 71);407 408 // 72-87: d0-15, the 8-byte floating-point registers409 AssignToArrayRange(Builder, Address, Eight8, 72, 87);410 411 return false;412}413 414std::unique_ptr<TargetCodeGenInfo>415CodeGen::createSparcV8TargetCodeGenInfo(CodeGenModule &CGM) {416 return std::make_unique<SparcV8TargetCodeGenInfo>(CGM.getTypes());417}418 419std::unique_ptr<TargetCodeGenInfo>420CodeGen::createSparcV9TargetCodeGenInfo(CodeGenModule &CGM) {421 return std::make_unique<SparcV9TargetCodeGenInfo>(CGM.getTypes());422}423