1 //===- Hexagon.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ABIInfoImpl.h" 10 #include "TargetInfo.h" 11 12 using namespace clang; 13 using namespace clang::CodeGen; 14 15 //===----------------------------------------------------------------------===// 16 // Hexagon ABI Implementation 17 //===----------------------------------------------------------------------===// 18 19 namespace { 20 21 class HexagonABIInfo : public DefaultABIInfo { 22 public: 23 HexagonABIInfo(CodeGenTypes &CGT) : DefaultABIInfo(CGT) {} 24 25 private: 26 ABIArgInfo classifyReturnType(QualType RetTy) const; 27 ABIArgInfo classifyArgumentType(QualType RetTy) const; 28 ABIArgInfo classifyArgumentType(QualType RetTy, unsigned *RegsLeft) const; 29 30 void computeInfo(CGFunctionInfo &FI) const override; 31 32 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 33 AggValueSlot Slot) const override; 34 Address EmitVAArgFromMemory(CodeGenFunction &CFG, Address VAListAddr, 35 QualType Ty) const; 36 Address EmitVAArgForHexagon(CodeGenFunction &CFG, Address VAListAddr, 37 QualType Ty) const; 38 Address EmitVAArgForHexagonLinux(CodeGenFunction &CFG, Address VAListAddr, 39 QualType Ty) const; 40 }; 41 42 class HexagonTargetCodeGenInfo : public TargetCodeGenInfo { 43 public: 44 HexagonTargetCodeGenInfo(CodeGenTypes &CGT) 45 : TargetCodeGenInfo(std::make_unique<HexagonABIInfo>(CGT)) {} 46 47 int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override { 48 return 29; 49 } 50 51 void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, 52 CodeGen::CodeGenModule &GCM) const override { 53 if (GV->isDeclaration()) 54 return; 55 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D); 56 if (!FD) 57 return; 58 } 59 }; 60 61 } // namespace 62 63 void HexagonABIInfo::computeInfo(CGFunctionInfo &FI) const { 64 unsigned RegsLeft = 6; 65 if (!getCXXABI().classifyReturnType(FI)) 66 FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 67 for (auto &I : FI.arguments()) 68 I.info = classifyArgumentType(I.type, &RegsLeft); 69 } 70 71 static bool HexagonAdjustRegsLeft(uint64_t Size, unsigned *RegsLeft) { 72 assert(Size <= 64 && "Not expecting to pass arguments larger than 64 bits" 73 " through registers"); 74 75 if (*RegsLeft == 0) 76 return false; 77 78 if (Size <= 32) { 79 (*RegsLeft)--; 80 return true; 81 } 82 83 if (2 <= (*RegsLeft & (~1U))) { 84 *RegsLeft = (*RegsLeft & (~1U)) - 2; 85 return true; 86 } 87 88 // Next available register was r5 but candidate was greater than 32-bits so it 89 // has to go on the stack. However we still consume r5 90 if (*RegsLeft == 1) 91 *RegsLeft = 0; 92 93 return false; 94 } 95 96 ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty, 97 unsigned *RegsLeft) const { 98 if (!isAggregateTypeForABI(Ty)) { 99 // Treat an enum type as its underlying type. 100 if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 101 Ty = EnumTy->getDecl()->getIntegerType(); 102 103 uint64_t Size = getContext().getTypeSize(Ty); 104 if (Size <= 64) 105 HexagonAdjustRegsLeft(Size, RegsLeft); 106 107 if (Size > 64 && Ty->isBitIntType()) 108 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), 109 /*ByVal=*/true); 110 111 return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) 112 : ABIArgInfo::getDirect(); 113 } 114 115 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) 116 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), 117 RAA == CGCXXABI::RAA_DirectInMemory); 118 119 // Ignore empty records. 120 if (isEmptyRecord(getContext(), Ty, true)) 121 return ABIArgInfo::getIgnore(); 122 123 uint64_t Size = getContext().getTypeSize(Ty); 124 unsigned Align = getContext().getTypeAlign(Ty); 125 126 if (Size > 64) 127 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), 128 /*ByVal=*/true); 129 130 if (HexagonAdjustRegsLeft(Size, RegsLeft)) 131 Align = Size <= 32 ? 32 : 64; 132 if (Size <= Align) { 133 // Pass in the smallest viable integer type. 134 Size = llvm::bit_ceil(Size); 135 return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size)); 136 } 137 return DefaultABIInfo::classifyArgumentType(Ty); 138 } 139 140 ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { 141 if (RetTy->isVoidType()) 142 return ABIArgInfo::getIgnore(); 143 144 const TargetInfo &T = CGT.getTarget(); 145 uint64_t Size = getContext().getTypeSize(RetTy); 146 147 if (RetTy->getAs<VectorType>()) { 148 // HVX vectors are returned in vector registers or register pairs. 149 if (T.hasFeature("hvx")) { 150 assert(T.hasFeature("hvx-length64b") || T.hasFeature("hvx-length128b")); 151 uint64_t VecSize = T.hasFeature("hvx-length64b") ? 64*8 : 128*8; 152 if (Size == VecSize || Size == 2*VecSize) 153 return ABIArgInfo::getDirectInReg(); 154 } 155 // Large vector types should be returned via memory. 156 if (Size > 64) 157 return getNaturalAlignIndirect(RetTy, 158 getDataLayout().getAllocaAddrSpace()); 159 } 160 161 if (!isAggregateTypeForABI(RetTy)) { 162 // Treat an enum type as its underlying type. 163 if (const EnumType *EnumTy = RetTy->getAs<EnumType>()) 164 RetTy = EnumTy->getDecl()->getIntegerType(); 165 166 if (Size > 64 && RetTy->isBitIntType()) 167 return getNaturalAlignIndirect( 168 RetTy, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); 169 170 return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) 171 : ABIArgInfo::getDirect(); 172 } 173 174 if (isEmptyRecord(getContext(), RetTy, true)) 175 return ABIArgInfo::getIgnore(); 176 177 // Aggregates <= 8 bytes are returned in registers, other aggregates 178 // are returned indirectly. 179 if (Size <= 64) { 180 // Return in the smallest viable integer type. 181 Size = llvm::bit_ceil(Size); 182 return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size)); 183 } 184 return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace(), 185 /*ByVal=*/true); 186 } 187 188 Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF, 189 Address VAListAddr, 190 QualType Ty) const { 191 // Load the overflow area pointer. 192 Address __overflow_area_pointer_p = 193 CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p"); 194 llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad( 195 __overflow_area_pointer_p, "__overflow_area_pointer"); 196 197 uint64_t Align = CGF.getContext().getTypeAlign(Ty) / 8; 198 if (Align > 4) { 199 // Alignment should be a power of 2. 200 assert((Align & (Align - 1)) == 0 && "Alignment is not power of 2!"); 201 202 // overflow_arg_area = (overflow_arg_area + align - 1) & -align; 203 llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int64Ty, Align - 1); 204 205 // Add offset to the current pointer to access the argument. 206 __overflow_area_pointer = 207 CGF.Builder.CreateGEP(CGF.Int8Ty, __overflow_area_pointer, Offset); 208 llvm::Value *AsInt = 209 CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty); 210 211 // Create a mask which should be "AND"ed 212 // with (overflow_arg_area + align - 1) 213 llvm::Value *Mask = llvm::ConstantInt::get(CGF.Int32Ty, -(int)Align); 214 __overflow_area_pointer = CGF.Builder.CreateIntToPtr( 215 CGF.Builder.CreateAnd(AsInt, Mask), __overflow_area_pointer->getType(), 216 "__overflow_area_pointer.align"); 217 } 218 219 // Get the type of the argument from memory and bitcast 220 // overflow area pointer to the argument type. 221 llvm::Type *PTy = CGF.ConvertTypeForMem(Ty); 222 Address AddrTyped = 223 Address(__overflow_area_pointer, PTy, CharUnits::fromQuantity(Align)); 224 225 // Round up to the minimum stack alignment for varargs which is 4 bytes. 226 uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4); 227 228 __overflow_area_pointer = CGF.Builder.CreateGEP( 229 CGF.Int8Ty, __overflow_area_pointer, 230 llvm::ConstantInt::get(CGF.Int32Ty, Offset), 231 "__overflow_area_pointer.next"); 232 CGF.Builder.CreateStore(__overflow_area_pointer, __overflow_area_pointer_p); 233 234 return AddrTyped; 235 } 236 237 Address HexagonABIInfo::EmitVAArgForHexagon(CodeGenFunction &CGF, 238 Address VAListAddr, 239 QualType Ty) const { 240 // FIXME: Need to handle alignment 241 llvm::Type *BP = CGF.Int8PtrTy; 242 CGBuilderTy &Builder = CGF.Builder; 243 Address VAListAddrAsBPP = VAListAddr.withElementType(BP); 244 llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); 245 // Handle address alignment for type alignment > 32 bits 246 uint64_t TyAlign = CGF.getContext().getTypeAlign(Ty) / 8; 247 if (TyAlign > 4) { 248 assert((TyAlign & (TyAlign - 1)) == 0 && "Alignment is not power of 2!"); 249 llvm::Value *AddrAsInt = Builder.CreatePtrToInt(Addr, CGF.Int32Ty); 250 AddrAsInt = Builder.CreateAdd(AddrAsInt, Builder.getInt32(TyAlign - 1)); 251 AddrAsInt = Builder.CreateAnd(AddrAsInt, Builder.getInt32(~(TyAlign - 1))); 252 Addr = Builder.CreateIntToPtr(AddrAsInt, BP); 253 } 254 Address AddrTyped = 255 Address(Addr, CGF.ConvertType(Ty), CharUnits::fromQuantity(TyAlign)); 256 257 uint64_t Offset = llvm::alignTo(CGF.getContext().getTypeSize(Ty) / 8, 4); 258 llvm::Value *NextAddr = Builder.CreateGEP( 259 CGF.Int8Ty, Addr, llvm::ConstantInt::get(CGF.Int32Ty, Offset), "ap.next"); 260 Builder.CreateStore(NextAddr, VAListAddrAsBPP); 261 262 return AddrTyped; 263 } 264 265 Address HexagonABIInfo::EmitVAArgForHexagonLinux(CodeGenFunction &CGF, 266 Address VAListAddr, 267 QualType Ty) const { 268 int ArgSize = CGF.getContext().getTypeSize(Ty) / 8; 269 270 if (ArgSize > 8) 271 return EmitVAArgFromMemory(CGF, VAListAddr, Ty); 272 273 // Here we have check if the argument is in register area or 274 // in overflow area. 275 // If the saved register area pointer + argsize rounded up to alignment > 276 // saved register area end pointer, argument is in overflow area. 277 unsigned RegsLeft = 6; 278 Ty = CGF.getContext().getCanonicalType(Ty); 279 (void)classifyArgumentType(Ty, &RegsLeft); 280 281 llvm::BasicBlock *MaybeRegBlock = CGF.createBasicBlock("vaarg.maybe_reg"); 282 llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg"); 283 llvm::BasicBlock *OnStackBlock = CGF.createBasicBlock("vaarg.on_stack"); 284 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end"); 285 286 // Get rounded size of the argument.GCC does not allow vararg of 287 // size < 4 bytes. We follow the same logic here. 288 ArgSize = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8; 289 int ArgAlign = (CGF.getContext().getTypeSize(Ty) <= 32) ? 4 : 8; 290 291 // Argument may be in saved register area 292 CGF.EmitBlock(MaybeRegBlock); 293 294 // Load the current saved register area pointer. 295 Address __current_saved_reg_area_pointer_p = CGF.Builder.CreateStructGEP( 296 VAListAddr, 0, "__current_saved_reg_area_pointer_p"); 297 llvm::Value *__current_saved_reg_area_pointer = CGF.Builder.CreateLoad( 298 __current_saved_reg_area_pointer_p, "__current_saved_reg_area_pointer"); 299 300 // Load the saved register area end pointer. 301 Address __saved_reg_area_end_pointer_p = CGF.Builder.CreateStructGEP( 302 VAListAddr, 1, "__saved_reg_area_end_pointer_p"); 303 llvm::Value *__saved_reg_area_end_pointer = CGF.Builder.CreateLoad( 304 __saved_reg_area_end_pointer_p, "__saved_reg_area_end_pointer"); 305 306 // If the size of argument is > 4 bytes, check if the stack 307 // location is aligned to 8 bytes 308 if (ArgAlign > 4) { 309 310 llvm::Value *__current_saved_reg_area_pointer_int = 311 CGF.Builder.CreatePtrToInt(__current_saved_reg_area_pointer, 312 CGF.Int32Ty); 313 314 __current_saved_reg_area_pointer_int = CGF.Builder.CreateAdd( 315 __current_saved_reg_area_pointer_int, 316 llvm::ConstantInt::get(CGF.Int32Ty, (ArgAlign - 1)), 317 "align_current_saved_reg_area_pointer"); 318 319 __current_saved_reg_area_pointer_int = 320 CGF.Builder.CreateAnd(__current_saved_reg_area_pointer_int, 321 llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign), 322 "align_current_saved_reg_area_pointer"); 323 324 __current_saved_reg_area_pointer = 325 CGF.Builder.CreateIntToPtr(__current_saved_reg_area_pointer_int, 326 __current_saved_reg_area_pointer->getType(), 327 "align_current_saved_reg_area_pointer"); 328 } 329 330 llvm::Value *__new_saved_reg_area_pointer = 331 CGF.Builder.CreateGEP(CGF.Int8Ty, __current_saved_reg_area_pointer, 332 llvm::ConstantInt::get(CGF.Int32Ty, ArgSize), 333 "__new_saved_reg_area_pointer"); 334 335 llvm::Value *UsingStack = nullptr; 336 UsingStack = CGF.Builder.CreateICmpSGT(__new_saved_reg_area_pointer, 337 __saved_reg_area_end_pointer); 338 339 CGF.Builder.CreateCondBr(UsingStack, OnStackBlock, InRegBlock); 340 341 // Argument in saved register area 342 // Implement the block where argument is in register saved area 343 CGF.EmitBlock(InRegBlock); 344 345 CGF.Builder.CreateStore(__new_saved_reg_area_pointer, 346 __current_saved_reg_area_pointer_p); 347 348 CGF.EmitBranch(ContBlock); 349 350 // Argument in overflow area 351 // Implement the block where the argument is in overflow area. 352 CGF.EmitBlock(OnStackBlock); 353 354 // Load the overflow area pointer 355 Address __overflow_area_pointer_p = 356 CGF.Builder.CreateStructGEP(VAListAddr, 2, "__overflow_area_pointer_p"); 357 llvm::Value *__overflow_area_pointer = CGF.Builder.CreateLoad( 358 __overflow_area_pointer_p, "__overflow_area_pointer"); 359 360 // Align the overflow area pointer according to the alignment of the argument 361 if (ArgAlign > 4) { 362 llvm::Value *__overflow_area_pointer_int = 363 CGF.Builder.CreatePtrToInt(__overflow_area_pointer, CGF.Int32Ty); 364 365 __overflow_area_pointer_int = 366 CGF.Builder.CreateAdd(__overflow_area_pointer_int, 367 llvm::ConstantInt::get(CGF.Int32Ty, ArgAlign - 1), 368 "align_overflow_area_pointer"); 369 370 __overflow_area_pointer_int = 371 CGF.Builder.CreateAnd(__overflow_area_pointer_int, 372 llvm::ConstantInt::get(CGF.Int32Ty, -ArgAlign), 373 "align_overflow_area_pointer"); 374 375 __overflow_area_pointer = CGF.Builder.CreateIntToPtr( 376 __overflow_area_pointer_int, __overflow_area_pointer->getType(), 377 "align_overflow_area_pointer"); 378 } 379 380 // Get the pointer for next argument in overflow area and store it 381 // to overflow area pointer. 382 llvm::Value *__new_overflow_area_pointer = CGF.Builder.CreateGEP( 383 CGF.Int8Ty, __overflow_area_pointer, 384 llvm::ConstantInt::get(CGF.Int32Ty, ArgSize), 385 "__overflow_area_pointer.next"); 386 387 CGF.Builder.CreateStore(__new_overflow_area_pointer, 388 __overflow_area_pointer_p); 389 390 CGF.Builder.CreateStore(__new_overflow_area_pointer, 391 __current_saved_reg_area_pointer_p); 392 393 CGF.EmitBranch(ContBlock); 394 // Get the correct pointer to load the variable argument 395 // Implement the ContBlock 396 CGF.EmitBlock(ContBlock); 397 398 llvm::Type *MemTy = CGF.ConvertTypeForMem(Ty); 399 llvm::PHINode *ArgAddr = CGF.Builder.CreatePHI( 400 llvm::PointerType::getUnqual(MemTy->getContext()), 2, "vaarg.addr"); 401 ArgAddr->addIncoming(__current_saved_reg_area_pointer, InRegBlock); 402 ArgAddr->addIncoming(__overflow_area_pointer, OnStackBlock); 403 404 return Address(ArgAddr, MemTy, CharUnits::fromQuantity(ArgAlign)); 405 } 406 407 RValue HexagonABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 408 QualType Ty, AggValueSlot Slot) const { 409 410 if (getTarget().getTriple().isMusl()) 411 return CGF.EmitLoadOfAnyValue( 412 CGF.MakeAddrLValue(EmitVAArgForHexagonLinux(CGF, VAListAddr, Ty), Ty), 413 Slot); 414 415 return CGF.EmitLoadOfAnyValue( 416 CGF.MakeAddrLValue(EmitVAArgForHexagon(CGF, VAListAddr, Ty), Ty), Slot); 417 } 418 419 std::unique_ptr<TargetCodeGenInfo> 420 CodeGen::createHexagonTargetCodeGenInfo(CodeGenModule &CGM) { 421 return std::make_unique<HexagonTargetCodeGenInfo>(CGM.getTypes()); 422 } 423