blob: 8e0d160f6e20a5f5c420980b3f9f0c51f25f568c [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include "slang_rs_export_func.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -07002
Zonr Chang0da0a7d2010-10-05 21:26:37 +08003#include "llvm/DerivedTypes.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07004#include "llvm/Target/TargetData.h"
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -07005
Zonr Chang0da0a7d2010-10-05 21:26:37 +08006#include "clang/AST/ASTContext.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -07007#include "clang/AST/Decl.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -07008
zonr6315f762010-10-05 15:35:14 +08009#include "slang_rs_context.h"
zonr6315f762010-10-05 15:35:14 +080010
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070011using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070012
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070013RSExportFunc *RSExportFunc::Create(RSContext *Context,
14 const clang::FunctionDecl *FD) {
15 llvm::StringRef Name = FD->getName();
16 RSExportFunc *F;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070017
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070018 assert(!Name.empty() && "Function must have a name");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070019
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070020 F = new RSExportFunc(Context, Name);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070021
Zonr Chang0da0a7d2010-10-05 21:26:37 +080022 // Initialize mParamPacketType
23 if (FD->getNumParams() <= 0) {
24 F->mParamPacketType = NULL;
25 } else {
26 clang::ASTContext *Ctx = Context->getASTContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070027
Zonr Chang0da0a7d2010-10-05 21:26:37 +080028 std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_func_param:");
29 Id.append(F->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070030
Zonr Chang0da0a7d2010-10-05 21:26:37 +080031 clang::RecordDecl *RD =
32 clang::RecordDecl::Create(*Ctx, clang::TTK_Struct,
33 Ctx->getTranslationUnitDecl(),
34 clang::SourceLocation(),
35 &Ctx->Idents.get(Id));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070036
Zonr Chang0da0a7d2010-10-05 21:26:37 +080037 for (unsigned i = 0; i < FD->getNumParams(); i++) {
38 const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
39 llvm::StringRef ParamName = PVD->getName();
40
41 if (PVD->hasDefaultArg())
42 fprintf(stderr, "Note: parameter '%s' in function '%s' has default "
43 "value which is not supported\n",
44 ParamName.str().c_str(),
45 F->getName().c_str());
46
47 clang::FieldDecl *FD =
48 clang::FieldDecl::Create(*Ctx,
49 RD,
50 clang::SourceLocation(),
51 PVD->getIdentifier(),
52 PVD->getOriginalType(),
53 NULL,
54 /* BitWidth = */NULL,
55 /* Mutable = */false);
56 RD->addDecl(FD);
57 }
58
59 RD->completeDefinition();
60
61 clang::QualType T = Ctx->getTagDeclType(RD);
62 assert(!T.isNull());
63
64 RSExportType *ET =
65 RSExportType::Create(Context, T.getTypePtr());
66
67 if (ET == NULL) {
68 fprintf(stderr, "Failed to export the function %s. There's at least one "
69 "parameter whose type is not supported by the "
70 "reflection", F->getName().c_str());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070071 delete F;
72 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070073 }
Zonr Chang0da0a7d2010-10-05 21:26:37 +080074
75 assert((ET->getClass() == RSExportType::ExportClassRecord) &&
76 "Parameter packet must be a record");
77
78 F->mParamPacketType = static_cast<RSExportRecordType *>(ET);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070079 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070080
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070081 return F;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070082}
83
Zonr Chang0da0a7d2010-10-05 21:26:37 +080084bool
85RSExportFunc::checkParameterPacketType(const llvm::StructType *ParamTy) const {
86 if (ParamTy == NULL)
87 return !hasParam();
88 else if (!hasParam())
89 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070090
Zonr Chang0da0a7d2010-10-05 21:26:37 +080091 assert(mParamPacketType != NULL);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070092
Zonr Chang0da0a7d2010-10-05 21:26:37 +080093 const RSExportRecordType *ERT = mParamPacketType;
94 // must have same number of elements
95 if (ERT->getFields().size() != ParamTy->getNumElements())
96 return false;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097
Zonr Chang0da0a7d2010-10-05 21:26:37 +080098 const llvm::StructLayout *ParamTySL =
99 mContext->getTargetData()->getStructLayout(ParamTy);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700100
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800101 unsigned Index = 0;
102 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
103 FE = ERT->fields_end(); FI != FE; FI++, Index++) {
104 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700105
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800106 const llvm::Type *T1 = F->getType()->getLLVMType();
107 const llvm::Type *T2 = ParamTy->getTypeAtIndex(Index);
108
109 // Fast check
110 if (T1 == T2)
111 continue;
112
113 // Check offset
114 size_t T1Offset = F->getOffsetInParent();
115 size_t T2Offset = ParamTySL->getElementOffset(Index);
116
117 if (T1Offset != T2Offset)
118 return false;
119
120 // Check size
121 size_t T1Size = RSExportType::GetTypeAllocSize(F->getType());
122 size_t T2Size = mContext->getTargetData()->getTypeAllocSize(T2);
123
124 if (T1Size != T2Size)
125 return false;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700126 }
127
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800128 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700129}