|
@@ -8249,6 +8249,137 @@ SparcV9TargetCodeGenInfo::initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// ARC ABI implementation.
|
|
|
|
+namespace {
|
|
|
|
+
|
|
|
|
+class ARCABIInfo : public DefaultABIInfo {
|
|
|
|
+public:
|
|
|
|
+ using DefaultABIInfo::DefaultABIInfo;
|
|
|
|
+
|
|
|
|
+private:
|
|
|
|
+ Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
|
|
+ QualType Ty) const override;
|
|
|
|
+
|
|
|
|
+ void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const {
|
|
|
|
+ if (!State.FreeRegs)
|
|
|
|
+ return;
|
|
|
|
+ if (Info.isIndirect() && Info.getInReg())
|
|
|
|
+ State.FreeRegs--;
|
|
|
|
+ else if (Info.isDirect() && Info.getInReg()) {
|
|
|
|
+ unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32;
|
|
|
|
+ if (sz < State.FreeRegs)
|
|
|
|
+ State.FreeRegs -= sz;
|
|
|
|
+ else
|
|
|
|
+ State.FreeRegs = 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ void computeInfo(CGFunctionInfo &FI) const override {
|
|
|
|
+ CCState State(FI.getCallingConvention());
|
|
|
|
+ // ARC uses 8 registers to pass arguments.
|
|
|
|
+ State.FreeRegs = 8;
|
|
|
|
+
|
|
|
|
+ if (!getCXXABI().classifyReturnType(FI))
|
|
|
|
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
|
|
|
|
+ updateState(FI.getReturnInfo(), FI.getReturnType(), State);
|
|
|
|
+ for (auto &I : FI.arguments()) {
|
|
|
|
+ I.info = classifyArgumentType(I.type, State.FreeRegs);
|
|
|
|
+ updateState(I.info, I.type, State);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const;
|
|
|
|
+ ABIArgInfo getIndirectByValue(QualType Ty) const;
|
|
|
|
+ ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const;
|
|
|
|
+ ABIArgInfo classifyReturnType(QualType RetTy) const;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+class ARCTargetCodeGenInfo : public TargetCodeGenInfo {
|
|
|
|
+public:
|
|
|
|
+ ARCTargetCodeGenInfo(CodeGenTypes &CGT)
|
|
|
|
+ : TargetCodeGenInfo(new ARCABIInfo(CGT)) {}
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {
|
|
|
|
+ return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) :
|
|
|
|
+ getNaturalAlignIndirect(Ty, false);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {
|
|
|
|
+ // Compute the byval alignment.
|
|
|
|
+ const unsigned MinABIStackAlignInBytes = 4;
|
|
|
|
+ unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;
|
|
|
|
+ return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true,
|
|
|
|
+ TypeAlign > MinABIStackAlignInBytes);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
|
|
|
|
+ QualType Ty) const {
|
|
|
|
+ return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,
|
|
|
|
+ getContext().getTypeInfoInChars(Ty),
|
|
|
|
+ CharUnits::fromQuantity(4), true);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,
|
|
|
|
+ uint8_t FreeRegs) const {
|
|
|
|
+ // Handle the generic C++ ABI.
|
|
|
|
+ const RecordType *RT = Ty->getAs<RecordType>();
|
|
|
|
+ if (RT) {
|
|
|
|
+ CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());
|
|
|
|
+ if (RAA == CGCXXABI::RAA_Indirect)
|
|
|
|
+ return getIndirectByRef(Ty, FreeRegs > 0);
|
|
|
|
+
|
|
|
|
+ if (RAA == CGCXXABI::RAA_DirectInMemory)
|
|
|
|
+ return getIndirectByValue(Ty);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Treat an enum type as its underlying type.
|
|
|
|
+ if (const EnumType *EnumTy = Ty->getAs<EnumType>())
|
|
|
|
+ Ty = EnumTy->getDecl()->getIntegerType();
|
|
|
|
+
|
|
|
|
+ auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;
|
|
|
|
+
|
|
|
|
+ if (isAggregateTypeForABI(Ty)) {
|
|
|
|
+ // Structures with flexible arrays are always indirect.
|
|
|
|
+ if (RT && RT->getDecl()->hasFlexibleArrayMember())
|
|
|
|
+ return getIndirectByValue(Ty);
|
|
|
|
+
|
|
|
|
+ // Ignore empty structs/unions.
|
|
|
|
+ if (isEmptyRecord(getContext(), Ty, true))
|
|
|
|
+ return ABIArgInfo::getIgnore();
|
|
|
|
+
|
|
|
|
+ llvm::LLVMContext &LLVMContext = getVMContext();
|
|
|
|
+
|
|
|
|
+ llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
|
|
|
|
+ SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);
|
|
|
|
+ llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);
|
|
|
|
+
|
|
|
|
+ return FreeRegs >= SizeInRegs ?
|
|
|
|
+ ABIArgInfo::getDirectInReg(Result) :
|
|
|
|
+ ABIArgInfo::getDirect(Result, 0, nullptr, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return Ty->isPromotableIntegerType() ?
|
|
|
|
+ (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) :
|
|
|
|
+ ABIArgInfo::getExtend(Ty)) :
|
|
|
|
+ (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() :
|
|
|
|
+ ABIArgInfo::getDirect());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {
|
|
|
|
+ if (RetTy->isAnyComplexType())
|
|
|
|
+ return ABIArgInfo::getDirectInReg();
|
|
|
|
+
|
|
|
|
+ // Arguments of size > 4 registers are indirect.
|
|
|
|
+ auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;
|
|
|
|
+ if (RetSize > 4)
|
|
|
|
+ return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);
|
|
|
|
+
|
|
|
|
+ return DefaultABIInfo::classifyReturnType(RetTy);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+} // End anonymous namespace.
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//===----------------------------------------------------------------------===//
|
|
// XCore ABI Implementation
|
|
// XCore ABI Implementation
|
|
@@ -9270,6 +9401,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
|
|
return SetCGInfo(new SparcV9TargetCodeGenInfo(Types));
|
|
return SetCGInfo(new SparcV9TargetCodeGenInfo(Types));
|
|
case llvm::Triple::xcore:
|
|
case llvm::Triple::xcore:
|
|
return SetCGInfo(new XCoreTargetCodeGenInfo(Types));
|
|
return SetCGInfo(new XCoreTargetCodeGenInfo(Types));
|
|
|
|
+ case llvm::Triple::arc:
|
|
|
|
+ return SetCGInfo(new ARCTargetCodeGenInfo(Types));
|
|
case llvm::Triple::spir:
|
|
case llvm::Triple::spir:
|
|
case llvm::Triple::spir64:
|
|
case llvm::Triple::spir64:
|
|
return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
|
|
return SetCGInfo(new SPIRTargetCodeGenInfo(Types));
|