Cleanup,
Const,
Constructor,
- DLLExport,
- DLLImport,
Deprecated,
Destructor,
FastCall,
Visibility,
WarnUnusedResult,
Weak,
- WeakImport
+ WeakImport,
+
+ FIRST_TARGET_ATTRIBUTE,
+ DLLExport,
+ DLLImport,
+ MSP430Interrupt
};
private:
static bool classof(const VisibilityAttr *A) { return true; }
};
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
DEF_SIMPLE_ATTR(CDecl);
DEF_SIMPLE_ATTR(Hiding);
DEF_SIMPLE_ATTR(Override);
+// Target-specific attributes
+DEF_SIMPLE_ATTR(DLLImport);
+DEF_SIMPLE_ATTR(DLLExport);
+
+class MSP430InterruptAttr : public Attr {
+ unsigned Number;
+
+public:
+ MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {}
+
+ unsigned getNumber() const { return Number; }
+
+ virtual Attr *clone(ASTContext &C) const {
+ return ::new (C) MSP430InterruptAttr(Number);
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; }
+ static bool classof(const MSP430InterruptAttr *A) { return true; }
+};
+
#undef DEF_SIMPLE_ATTR
} // end namespace clang
#include "CGCall.h"
#include "CGObjCRuntime.h"
#include "Mangle.h"
+#include "TargetInfo.h"
#include "clang/CodeGen/CodeGenOptions.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
Diagnostic &diags)
: BlockModule(C, M, TD, Types, *this), Context(C),
Features(C.getLangOptions()), CodeGenOpts(CGO), TheModule(M),
- TheTargetData(TD), Diags(diags), Types(C, M, TD), MangleCtx(C),
- VtableInfo(*this), Runtime(0),
+ TheTargetData(TD), TheTargetCodeGenInfo(0), Diags(diags),
+ Types(C, M, TD, getTargetCodeGenInfo().getABIInfo()),
+ MangleCtx(C), VtableInfo(*this), Runtime(0),
MemCpyFn(0), MemMoveFn(0), MemSetFn(0), CFConstantStringClassRef(0),
VMContext(M.getContext()) {
if (const SectionAttr *SA = D->getAttr<SectionAttr>())
GV->setSection(SA->getName());
+
+ getTargetCodeGenInfo().SetTargetAttributes(D, GV, *this);
}
void CodeGenModule::SetInternalFunctionAttributes(const Decl *D,
}
namespace clang {
+ class TargetCodeGenInfo;
class ASTContext;
class FunctionDecl;
class IdentifierInfo;
const CodeGenOptions &CodeGenOpts;
llvm::Module &TheModule;
const llvm::TargetData &TheTargetData;
+ mutable const TargetCodeGenInfo *TheTargetCodeGenInfo;
Diagnostic &Diags;
CodeGenTypes Types;
MangleContext MangleCtx;
Diagnostic &getDiags() const { return Diags; }
const llvm::TargetData &getTargetData() const { return TheTargetData; }
llvm::LLVMContext &getLLVMContext() { return VMContext; }
+ const TargetCodeGenInfo &getTargetCodeGenInfo() const;
/// getDeclVisibilityMode - Compute the visibility of the decl \arg D.
LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const;
using namespace CodeGen;
CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M,
- const llvm::TargetData &TD)
+ const llvm::TargetData &TD, const ABIInfo &Info)
: Context(Ctx), Target(Ctx.Target), TheModule(M), TheTargetData(TD),
- TheABIInfo(0) {
+ TheABIInfo(Info) {
}
CodeGenTypes::~CodeGenTypes() {
while (I != E)
delete &*I++;
}
- delete TheABIInfo;
}
/// ConvertType - Convert the specified type to its LLVM form.
const TargetInfo &Target;
llvm::Module& TheModule;
const llvm::TargetData& TheTargetData;
- mutable const ABIInfo* TheABIInfo;
+ const ABIInfo& TheABIInfo;
llvm::SmallVector<std::pair<QualType,
llvm::OpaqueType *>, 8> PointersToResolve;
/// interface to convert type T into a llvm::Type.
const llvm::Type *ConvertNewType(QualType T);
public:
- CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD);
+ CodeGenTypes(ASTContext &Ctx, llvm::Module &M, const llvm::TargetData &TD,
+ const ABIInfo &Info);
~CodeGenTypes();
const llvm::TargetData &getTargetData() const { return TheTargetData; }
const TargetInfo &getTarget() const { return Target; }
ASTContext &getContext() const { return Context; }
- const ABIInfo &getABIInfo() const;
+ const ABIInfo &getABIInfo() const { return TheABIInfo; }
llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); }
/// ConvertType - Convert type T into a llvm::Type.
-//===---- TargetABIInfo.cpp - Encapsulate target ABI details ----*- C++ -*-===//
+//===---- TargetInfo.cpp - Encapsulate target details -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
+#include "TargetInfo.h"
#include "ABIInfo.h"
#include "CodeGenFunction.h"
#include "clang/AST/RecordLayout.h"
#include "llvm/Type.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
OS << ")\n";
}
+TargetCodeGenInfo::~TargetCodeGenInfo() { delete Info; }
+
static bool isEmptyRecord(ASTContext &Context, QualType T, bool AllowArrays);
/// isEmptyField - Return true iff a the field is "empty", that is it
CodeGenFunction &CGF) const;
};
+class DefaultTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ DefaultTargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+};
+
+llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
+ CodeGenFunction &CGF) const {
+ return 0;
+}
+
+ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
+ ASTContext &Context,
+ llvm::LLVMContext &VMContext) const {
+ if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
+ return ABIArgInfo::getIndirect(0);
+ } else {
+ return (Ty->isPromotableIntegerType() ?
+ ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
+ }
+}
+
/// X86_32ABIInfo - The X86-32 ABI information.
class X86_32ABIInfo : public ABIInfo {
ASTContext &Context;
: ABIInfo(), Context(Context), IsDarwinVectorABI(d),
IsSmallStructInRegABI(p) {}
};
-}
+class X86_32TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ X86_32TargetCodeGenInfo(ASTContext &Context, bool d, bool p)
+ :TargetCodeGenInfo(new X86_32ABIInfo(Context, d, p)) {};
+};
+
+}
/// shouldReturnTypeInRegister - Determine if the given type should be
/// passed in a register (for the Darwin ABI).
virtual llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
CodeGenFunction &CGF) const;
};
+
+class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ X86_64TargetCodeGenInfo():TargetCodeGenInfo(new X86_64ABIInfo()) {};
+};
+
}
X86_64ABIInfo::Class X86_64ABIInfo::merge(Class Accum,
CodeGenFunction &CGF) const;
};
+class PIC16TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ PIC16TargetCodeGenInfo():TargetCodeGenInfo(new PIC16ABIInfo()) {};
+};
+
}
ABIArgInfo PIC16ABIInfo::classifyReturnType(QualType RetTy,
CodeGenFunction &CGF) const;
};
+class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ ARMTargetCodeGenInfo(ARMABIInfo::ABIKind K)
+ :TargetCodeGenInfo(new ARMABIInfo(K)) {};
+};
+
}
void ARMABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context,
CodeGenFunction &CGF) const;
};
+class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ SystemZTargetCodeGenInfo():TargetCodeGenInfo(new SystemZABIInfo()) {};
+};
+
}
bool SystemZABIInfo::isPromotableIntegerType(QualType Ty) const {
}
}
-ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context,
- llvm::LLVMContext &VMContext) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- return ABIArgInfo::getIndirect(0);
- } else {
- return (Ty->isPromotableIntegerType() ?
- ABIArgInfo::getExtend() : ABIArgInfo::getDirect());
- }
+// MSP430 ABI Implementation
+
+namespace {
+
+class MSP430TargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+ MSP430TargetCodeGenInfo():TargetCodeGenInfo(new DefaultABIInfo()) {};
+ void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const;
+};
+
}
-llvm::Value *DefaultABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty,
- CodeGenFunction &CGF) const {
- return 0;
+void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
+ llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (const MSP430InterruptAttr *attr = FD->getAttr<MSP430InterruptAttr>()) {
+ // Handle 'interrupt' attribute:
+ llvm::Function *F = cast<llvm::Function>(GV);
+
+ // Step 1: Set ISR calling convention.
+ F->setCallingConv(llvm::CallingConv::MSP430_INTR);
+
+ // Step 2: Add attributes goodness.
+ F->addFnAttr(llvm::Attribute::NoInline);
+
+ // Step 3: Emit ISR vector alias.
+ unsigned Num = attr->getNumber() + 0xffe0;
+ new llvm::GlobalAlias(GV->getType(), llvm::Function::ExternalLinkage,
+ "vector_" +
+ llvm::LowercaseString(llvm::utohexstr(Num)),
+ GV, &M.getModule());
+ }
+ }
}
-const ABIInfo &CodeGenTypes::getABIInfo() const {
- if (TheABIInfo)
- return *TheABIInfo;
+const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() const {
+ if (TheTargetCodeGenInfo)
+ return *TheTargetCodeGenInfo;
- // For now we just cache the ABIInfo in CodeGenTypes and don't free it.
+ // For now we just cache the TargetCodeGenInfo in CodeGenModule and don't
+ // free it.
const llvm::Triple &Triple(getContext().Target.getTriple());
switch (Triple.getArch()) {
default:
- return *(TheABIInfo = new DefaultABIInfo);
+ return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo);
case llvm::Triple::arm:
case llvm::Triple::thumb:
// FIXME: We want to know the float calling convention as well.
if (strcmp(getContext().Target.getABI(), "apcs-gnu") == 0)
- return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::APCS));
+ return *(TheTargetCodeGenInfo =
+ new ARMTargetCodeGenInfo(ARMABIInfo::APCS));
- return *(TheABIInfo = new ARMABIInfo(ARMABIInfo::AAPCS));
+ return *(TheTargetCodeGenInfo =
+ new ARMTargetCodeGenInfo(ARMABIInfo::AAPCS));
case llvm::Triple::pic16:
- return *(TheABIInfo = new PIC16ABIInfo());
+ return *(TheTargetCodeGenInfo = new PIC16TargetCodeGenInfo());
case llvm::Triple::systemz:
- return *(TheABIInfo = new SystemZABIInfo());
+ return *(TheTargetCodeGenInfo = new SystemZTargetCodeGenInfo());
+
+ case llvm::Triple::msp430:
+ return *(TheTargetCodeGenInfo = new MSP430TargetCodeGenInfo());
case llvm::Triple::x86:
switch (Triple.getOS()) {
case llvm::Triple::Darwin:
- return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Context, true, true));
case llvm::Triple::Cygwin:
case llvm::Triple::MinGW32:
case llvm::Triple::MinGW64:
case llvm::Triple::DragonFly:
case llvm::Triple::FreeBSD:
case llvm::Triple::OpenBSD:
- return *(TheABIInfo = new X86_32ABIInfo(Context, false, true));
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Context, false, true));
default:
- return *(TheABIInfo = new X86_32ABIInfo(Context, false, false));
+ return *(TheTargetCodeGenInfo =
+ new X86_32TargetCodeGenInfo(Context, false, false));
}
case llvm::Triple::x86_64:
- return *(TheABIInfo = new X86_64ABIInfo());
+ return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo());
}
}
--- /dev/null
+//===---- TargetInfo.h - Encapsulate target details -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes wrap the information about a call or function
+// definition used to handle ABI compliancy.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_TARGETINFO_H
+#define CLANG_CODEGEN_TARGETINFO_H
+
+namespace llvm {
+ class GlobalValue;
+}
+
+namespace clang {
+ class ABIInfo;
+ class Decl;
+
+ namespace CodeGen {
+ class CodeGenModule;
+ }
+
+ /// TargetCodeGenInfo - This class organizes various target-specific
+ /// codegeneration issues, like target-specific attributes, builtins and so
+ /// on.
+ class TargetCodeGenInfo {
+ ABIInfo *Info;
+ public:
+ // WARNING: Acquires the ownership of ABIInfo.
+ TargetCodeGenInfo(ABIInfo *info = 0):Info(info) { };
+ virtual ~TargetCodeGenInfo();
+
+ /// getABIInfo() - Returns ABI info helper for the target.
+ const ABIInfo& getABIInfo() const { return *Info; }
+
+ /// SetTargetAttributes - Provides a convenient hook to handle extra
+ /// target-specific attributes for the given global.
+ virtual void SetTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const { };
+ };
+}
+
+#endif // CLANG_CODEGEN_TARGETINFO_H
bool IsInherited = Record[Idx++];
switch (Kind) {
+ default:
+ assert(0 && "Unknown attribute!");
+ break;
STRING_ATTR(Alias);
UNSIGNED_ATTR(Aligned);
SIMPLE_ATTR(AlwaysInline);
void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
RecordData Record;
for (; Attr; Attr = Attr->getNext()) {
- Record.push_back(Attr->getKind()); // FIXME: stable encoding
+ Record.push_back(Attr->getKind()); // FIXME: stable encoding, target attrs
Record.push_back(Attr->isInherited());
switch (Attr->getKind()) {
+ default:
+ assert(0 && "Does not support PCH writing for this attribute yet!");
+ break;
case Attr::Alias:
AddString(cast<AliasAttr>(Attr)->getAliasee(), Record);
break;
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "TargetAttributesSema.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/APFloat.h"
#include "clang/AST/ASTConsumer.h"
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
bool CompleteTranslationUnit,
CodeCompleteConsumer *CodeCompleter)
- : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
+ : TheTargetAttributesSema(0),
+ LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
CurBlock(0), PackContext(0), ParsingDeclDepth(0),
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
}
+Sema::~Sema() {
+ if (PackContext) FreePackedContext();
+ delete TheTargetAttributesSema;
+}
+
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
class InitializationKind;
class InitializationSequence;
class VisibleDeclConsumer;
+ class TargetAttributesSema;
/// BlockSemaInfo - When a block is being parsed, this contains information
/// about the block. It is pointed to from Sema::CurBlock.
class Sema : public Action {
Sema(const Sema&); // DO NOT IMPLEMENT
void operator=(const Sema&); // DO NOT IMPLEMENT
+ mutable const TargetAttributesSema* TheTargetAttributesSema;
public:
const LangOptions &LangOpts;
Preprocessor &PP;
Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
bool CompleteTranslationUnit = true,
CodeCompleteConsumer *CompletionConsumer = 0);
- ~Sema() {
- if (PackContext) FreePackedContext();
- }
+ ~Sema();
const LangOptions &getLangOptions() const { return LangOpts; }
Diagnostic &getDiagnostics() const { return Diags; }
SourceManager &getSourceManager() const { return SourceMgr; }
+ const TargetAttributesSema &getTargetAttributesSema() const;
/// \brief Helper class that creates diagnostics with optional
/// template instantiation stacks.
//===----------------------------------------------------------------------===//
#include "Sema.h"
+#include "TargetAttributesSema.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
// Just ignore
break;
default:
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
+ // Ask target about the attribute.
+ const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
+ if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
break;
}
}
--- /dev/null
+//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains semantic analysis implementation for target-specific
+// attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Sema.h"
+#include "TargetAttributesSema.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang;
+
+TargetAttributesSema::~TargetAttributesSema() {}
+bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ return false;
+}
+
+static void HandleMSP430InterruptAttr(Decl *d,
+ const AttributeList &Attr, Sema &S) {
+ // Check the attribute arguments.
+ if (Attr.getNumArgs() != 1) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ // FIXME: Check for decl - it should be void ()(void).
+
+ Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
+ llvm::APSInt NumParams(32);
+ if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "interrupt" << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ unsigned Num = NumParams.getLimitedValue(255);
+ if ((Num & 1) || Num > 30) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
+ << "interrupt" << (int)NumParams.getSExtValue()
+ << NumParamsExpr->getSourceRange();
+ return;
+ }
+
+ d->addAttr(::new (S.Context) MSP430InterruptAttr(Num));
+ d->addAttr(::new (S.Context) UsedAttr());
+ }
+
+namespace {
+ class MSP430AttributesSema : public TargetAttributesSema {
+ public:
+ MSP430AttributesSema() { }
+ bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const {
+ if (Attr.getName()->getName() == "interrupt") {
+ HandleMSP430InterruptAttr(D, Attr, S);
+ return true;
+ }
+ return false;
+ }
+ };
+}
+
+const TargetAttributesSema &Sema::getTargetAttributesSema() const {
+ if (TheTargetAttributesSema)
+ return *TheTargetAttributesSema;
+
+ const llvm::Triple &Triple(Context.Target.getTriple());
+ switch (Triple.getArch()) {
+ default:
+ return *(TheTargetAttributesSema = new TargetAttributesSema);
+
+ case llvm::Triple::msp430:
+ return *(TheTargetAttributesSema = new MSP430AttributesSema);
+ }
+}
+
--- /dev/null
+//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_SEMA_TARGETSEMA_H
+#define CLANG_SEMA_TARGETSEMA_H
+
+namespace clang {
+ class Scope;
+ class Decl;
+ class Attr;
+ class Sema;
+
+ class TargetAttributesSema {
+ public:
+ virtual ~TargetAttributesSema();
+ virtual bool ProcessDeclAttribute(Scope *scope, Decl *D,
+ const AttributeList &Attr, Sema &S) const;
+ };
+}
+
+#endif