blob: c5943d6034037b1d733e3b7de80fea225cced755 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
zonr6315f762010-10-05 15:35:14 +080017#include "slang_rs_export_func.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Zonr Chang0da0a7d2010-10-05 21:26:37 +080019#include "llvm/DerivedTypes.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070020#include "llvm/Target/TargetData.h"
Shih-wei Liao0a3f20e2010-08-10 13:09:49 -070021
Zonr Chang0da0a7d2010-10-05 21:26:37 +080022#include "clang/AST/ASTContext.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070023#include "clang/AST/Decl.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070024
zonr6315f762010-10-05 15:35:14 +080025#include "slang_rs_context.h"
zonr6315f762010-10-05 15:35:14 +080026
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070027using namespace slang;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070028
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070029RSExportFunc *RSExportFunc::Create(RSContext *Context,
30 const clang::FunctionDecl *FD) {
31 llvm::StringRef Name = FD->getName();
32 RSExportFunc *F;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070033
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070034 assert(!Name.empty() && "Function must have a name");
Shih-wei Liao462aefd2010-06-04 15:32:04 -070035
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070036 F = new RSExportFunc(Context, Name);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070037
Zonr Chang0da0a7d2010-10-05 21:26:37 +080038 // Initialize mParamPacketType
39 if (FD->getNumParams() <= 0) {
40 F->mParamPacketType = NULL;
41 } else {
Stephen Hines9e5b5032010-11-03 13:19:14 -070042 clang::ASTContext &Ctx = Context->getASTContext();
Shih-wei Liao462aefd2010-06-04 15:32:04 -070043
Zonr Chang0da0a7d2010-10-05 21:26:37 +080044 std::string Id(DUMMY_RS_TYPE_NAME_PREFIX"helper_func_param:");
45 Id.append(F->getName()).append(DUMMY_RS_TYPE_NAME_POSTFIX);
Shih-wei Liao462aefd2010-06-04 15:32:04 -070046
Zonr Chang0da0a7d2010-10-05 21:26:37 +080047 clang::RecordDecl *RD =
Stephen Hines9e5b5032010-11-03 13:19:14 -070048 clang::RecordDecl::Create(Ctx, clang::TTK_Struct,
49 Ctx.getTranslationUnitDecl(),
Zonr Chang0da0a7d2010-10-05 21:26:37 +080050 clang::SourceLocation(),
Stephen Hines9e5b5032010-11-03 13:19:14 -070051 &Ctx.Idents.get(Id));
Shih-wei Liao462aefd2010-06-04 15:32:04 -070052
Zonr Chang0da0a7d2010-10-05 21:26:37 +080053 for (unsigned i = 0; i < FD->getNumParams(); i++) {
54 const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
55 llvm::StringRef ParamName = PVD->getName();
56
57 if (PVD->hasDefaultArg())
58 fprintf(stderr, "Note: parameter '%s' in function '%s' has default "
59 "value which is not supported\n",
60 ParamName.str().c_str(),
61 F->getName().c_str());
62
63 clang::FieldDecl *FD =
Stephen Hines9e5b5032010-11-03 13:19:14 -070064 clang::FieldDecl::Create(Ctx,
Zonr Chang0da0a7d2010-10-05 21:26:37 +080065 RD,
66 clang::SourceLocation(),
67 PVD->getIdentifier(),
68 PVD->getOriginalType(),
69 NULL,
70 /* BitWidth = */NULL,
71 /* Mutable = */false);
72 RD->addDecl(FD);
73 }
74
75 RD->completeDefinition();
76
Stephen Hines9e5b5032010-11-03 13:19:14 -070077 clang::QualType T = Ctx.getTagDeclType(RD);
Zonr Chang0da0a7d2010-10-05 21:26:37 +080078 assert(!T.isNull());
79
80 RSExportType *ET =
81 RSExportType::Create(Context, T.getTypePtr());
82
83 if (ET == NULL) {
84 fprintf(stderr, "Failed to export the function %s. There's at least one "
85 "parameter whose type is not supported by the "
86 "reflection", F->getName().c_str());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070087 delete F;
88 return NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070089 }
Zonr Chang0da0a7d2010-10-05 21:26:37 +080090
91 assert((ET->getClass() == RSExportType::ExportClassRecord) &&
92 "Parameter packet must be a record");
93
94 F->mParamPacketType = static_cast<RSExportRecordType *>(ET);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070095 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070096
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070097 return F;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070098}
99
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800100bool
101RSExportFunc::checkParameterPacketType(const llvm::StructType *ParamTy) const {
102 if (ParamTy == NULL)
103 return !hasParam();
104 else if (!hasParam())
105 return false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700106
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800107 assert(mParamPacketType != NULL);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700108
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800109 const RSExportRecordType *ERT = mParamPacketType;
110 // must have same number of elements
111 if (ERT->getFields().size() != ParamTy->getNumElements())
112 return false;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700113
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800114 const llvm::StructLayout *ParamTySL =
Zonr Chang641558f2010-10-12 21:07:06 +0800115 getRSContext()->getTargetData()->getStructLayout(ParamTy);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700116
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800117 unsigned Index = 0;
118 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
119 FE = ERT->fields_end(); FI != FE; FI++, Index++) {
120 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700121
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800122 const llvm::Type *T1 = F->getType()->getLLVMType();
123 const llvm::Type *T2 = ParamTy->getTypeAtIndex(Index);
124
125 // Fast check
126 if (T1 == T2)
127 continue;
128
129 // Check offset
130 size_t T1Offset = F->getOffsetInParent();
131 size_t T2Offset = ParamTySL->getElementOffset(Index);
132
133 if (T1Offset != T2Offset)
134 return false;
135
136 // Check size
137 size_t T1Size = RSExportType::GetTypeAllocSize(F->getType());
Zonr Chang641558f2010-10-12 21:07:06 +0800138 size_t T2Size = getRSContext()->getTargetData()->getTypeAllocSize(T2);
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800139
140 if (T1Size != T2Size)
141 return false;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700142 }
143
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800144 return true;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700145}