diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index cd5dc214096e8ccf2eab7d47886a34ac6dcc2018..9e5dd79f13bd884840e6393d60c80cd51e78e8f5 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -279,6 +279,14 @@ def MSP430Interrupt : Attr { let Args = [UnsignedArgument<"Number">]; } +def MBlazeInterruptHandler : Attr { + let Spellings = []; +} + +def MBlazeSaveVolatiles : Attr { + let Spellings = []; +} + def Naked : Attr { let Spellings = ["naked"]; } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 4234c6f3378c45ccd6a396bc13d0d1714bb3d079..5f7cf84386551d790ef46dc07e60123f8c3b7133 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -2529,6 +2529,116 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); } +//===----------------------------------------------------------------------===// +// MBlaze ABI Implementation +//===----------------------------------------------------------------------===// + +namespace { + +class MBlazeABIInfo : public ABIInfo { +public: + MBlazeABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {} + + bool isPromotableIntegerType(QualType Ty) const; + + ABIArgInfo classifyReturnType(QualType RetTy) const; + ABIArgInfo classifyArgumentType(QualType RetTy) const; + + virtual void computeInfo(CGFunctionInfo &FI) const { + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end(); + it != ie; ++it) + it->info = classifyArgumentType(it->type); + } + + virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CGF) const; +}; + +class MBlazeTargetCodeGenInfo : public TargetCodeGenInfo { +public: + MBlazeTargetCodeGenInfo(CodeGenTypes &CGT) + : TargetCodeGenInfo(new MBlazeABIInfo(CGT)) {} + void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) const; +}; + +} + +bool MBlazeABIInfo::isPromotableIntegerType(QualType Ty) const { + // MBlaze ABI requires all 8 and 16 bit quantities to be extended. + if (const BuiltinType *BT = Ty->getAs<BuiltinType>()) + switch (BT->getKind()) { + case BuiltinType::Bool: + case BuiltinType::Char_S: + case BuiltinType::Char_U: + case BuiltinType::SChar: + case BuiltinType::UChar: + case BuiltinType::Short: + case BuiltinType::UShort: + return true; + default: + return false; + } + return false; +} + +llvm::Value *MBlazeABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, + CodeGenFunction &CGF) const { + // FIXME: Implement + return 0; +} + + +ABIArgInfo MBlazeABIInfo::classifyReturnType(QualType RetTy) const { + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + if (isAggregateTypeForABI(RetTy)) + return ABIArgInfo::getIndirect(0); + + return (isPromotableIntegerType(RetTy) ? + ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); +} + +ABIArgInfo MBlazeABIInfo::classifyArgumentType(QualType Ty) const { + if (isAggregateTypeForABI(Ty)) + return ABIArgInfo::getIndirect(0); + + return (isPromotableIntegerType(Ty) ? + ABIArgInfo::getExtend() : ABIArgInfo::getDirect()); +} + +void MBlazeTargetCodeGenInfo::SetTargetAttributes(const Decl *D, + llvm::GlobalValue *GV, + CodeGen::CodeGenModule &M) + const { + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) return; + + llvm::CallingConv::ID CC = llvm::CallingConv::C; + if (FD->hasAttr<MBlazeInterruptHandlerAttr>()) + CC = llvm::CallingConv::MBLAZE_INTR; + else if (FD->hasAttr<MBlazeSaveVolatilesAttr>()) + CC = llvm::CallingConv::MBLAZE_SVOL; + + if (CC != llvm::CallingConv::C) { + // Handle 'interrupt_handler' attribute: + llvm::Function *F = cast<llvm::Function>(GV); + + // Step 1: Set ISR calling convention. + F->setCallingConv(CC); + + // Step 2: Add attributes goodness. + F->addFnAttr(llvm::Attribute::NoInline); + } + + // Step 3: Emit _interrupt_handler alias. + if (CC == llvm::CallingConv::MBLAZE_INTR) + new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage, + "_interrupt_handler", GV, &M.getModule()); +} + + //===----------------------------------------------------------------------===// // MSP430 ABI Implementation //===----------------------------------------------------------------------===// @@ -2654,6 +2764,9 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::systemz: return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo(Types)); + case llvm::Triple::mblaze: + return *(TheTargetCodeGenInfo = new MBlazeTargetCodeGenInfo(Types)); + case llvm::Triple::msp430: return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo(Types)); diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index 1854e7430853fc19d98cdf012fb08b4d91113117..bb618027dd13392d37b8efba56599852bc5faa38 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -71,6 +71,55 @@ namespace { }; } +static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(), + S.Context)); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + +static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(), + S.Context)); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + + +namespace { + class MBlazeAttributesSema : public TargetAttributesSema { + public: + MBlazeAttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, + Sema &S) const { + if (Attr.getName()->getName() == "interrupt_handler") { + HandleMBlazeInterruptHandlerAttr(D, Attr, S); + return true; + } else if (Attr.getName()->getName() == "save_volatiles") { + HandleMBlazeSaveVolatilesAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + static void HandleX86ForceAlignArgPointerAttr(Decl *D, const AttributeList& Attr, Sema &S) { @@ -220,6 +269,8 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const { case llvm::Triple::msp430: return *(TheTargetAttributesSema = new MSP430AttributesSema); + case llvm::Triple::mblaze: + return *(TheTargetAttributesSema = new MBlazeAttributesSema); case llvm::Triple::x86: return *(TheTargetAttributesSema = new X86AttributesSema); }