1. Add some ABI information for the Microblaze.

2. Add attibutes "interrupt_handler" and "save_volatiles" for the Microblaze target.

llvm-svn: 122184
This commit is contained in:
Wesley Peck 2010-12-19 19:57:51 +00:00
parent 3e635d2e99
commit 36a1f68fec
3 changed files with 172 additions and 0 deletions

View File

@ -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"];
}

View File

@ -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));

View File

@ -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);
}