blob: a1efad11156ed91574ed433510e8291a96c6fe16 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
Stephen Hines7b51b552012-02-16 00:12:38 -08002 * Copyright 2010-2012, The Android Open Source Project
Zonr Changc383a502010-10-12 01:52:08 +08003 *
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_backend.h"
18
zonr6315f762010-10-05 15:35:14 +080019#include <string>
Stephen Hinese639eb52010-11-08 19:27:20 -080020#include <vector>
zonr6315f762010-10-05 15:35:14 +080021
Shih-wei Liao43730fe2012-08-02 23:06:18 -070022#include "clang/AST/ASTContext.h"
mkopec1c460b372012-01-09 11:21:50 -050023#include "clang/Frontend/CodeGenOptions.h"
24
zonr6315f762010-10-05 15:35:14 +080025#include "llvm/ADT/Twine.h"
26#include "llvm/ADT/StringExtras.h"
27
Stephen Hinese639eb52010-11-08 19:27:20 -080028#include "llvm/Constant.h"
29#include "llvm/Constants.h"
30#include "llvm/DerivedTypes.h"
31#include "llvm/Function.h"
Shih-wei Liao43730fe2012-08-02 23:06:18 -070032#include "llvm/IRBuilder.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080033#include "llvm/Metadata.h"
34#include "llvm/Module.h"
35
mkopec1c460b372012-01-09 11:21:50 -050036#include "llvm/Support/DebugLoc.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080037
Stephen Hines6e6578a2011-02-07 18:05:48 -080038#include "slang_assert.h"
Zonr Chang592a9542010-10-07 20:03:58 +080039#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080040#include "slang_rs_context.h"
Stephen Hines4ccf75e2011-08-16 18:21:01 -070041#include "slang_rs_export_foreach.h"
zonr6315f762010-10-05 15:35:14 +080042#include "slang_rs_export_func.h"
43#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080044#include "slang_rs_export_var.h"
45#include "slang_rs_metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070046
Stephen Hinese639eb52010-11-08 19:27:20 -080047namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070048
49RSBackend::RSBackend(RSContext *Context,
Logan Chien9207a2e2011-10-21 15:39:28 +080050 clang::DiagnosticsEngine *DiagEngine,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051 const clang::CodeGenOptions &CodeGenOpts,
52 const clang::TargetOptions &TargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -080053 PragmaList *Pragmas,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070054 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080055 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070056 clang::SourceManager &SourceMgr,
Stephen Hines4a4bf922011-08-18 17:20:33 -070057 bool AllowRSPrefix)
Logan Chien9207a2e2011-10-21 15:39:28 +080058 : Backend(DiagEngine, CodeGenOpts, TargetOpts, Pragmas, OS, OT),
59 mContext(Context),
60 mSourceMgr(SourceMgr),
61 mAllowRSPrefix(AllowRSPrefix),
62 mExportVarMetadata(NULL),
63 mExportFuncMetadata(NULL),
Stephen Hines7b51b552012-02-16 00:12:38 -080064 mExportForEachNameMetadata(NULL),
65 mExportForEachSignatureMetadata(NULL),
Logan Chien9207a2e2011-10-21 15:39:28 +080066 mExportTypeMetadata(NULL),
67 mRSObjectSlotsMetadata(NULL),
68 mRefCount(mContext->getASTContext()) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070069}
70
Stephen Hinescfae0f32010-11-01 18:57:31 -070071// 1) Add zero initialization of local RS object types
72void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
73 if (FD &&
74 FD->hasBody() &&
75 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070076 mRefCount.Init();
Stephen Hines4b32ffd2010-11-05 18:47:11 -070077 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070078 }
79 return;
80}
81
Logan Chienfa6ef562011-11-25 13:50:02 +080082bool RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
Stephen Hinescfae0f32010-11-01 18:57:31 -070083 // Disallow user-defined functions with prefix "rs"
84 if (!mAllowRSPrefix) {
85 // Iterate all function declarations in the program.
86 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
87 I != E; I++) {
Logan Chienab992e52011-07-20 22:06:52 +080088 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hinescfae0f32010-11-01 18:57:31 -070089 if (FD == NULL)
90 continue;
91 if (!FD->getName().startswith("rs")) // Check prefix
92 continue;
93 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
Logan Chien9207a2e2011-10-21 15:39:28 +080094 mDiagEngine.Report(
95 clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
96 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
97 "invalid function name prefix, "
98 "\"rs\" is reserved: '%0'"))
99 << FD->getName();
Stephen Hinescfae0f32010-11-01 18:57:31 -0700100 }
101 }
102
103 // Process any non-static function declarations
104 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
Logan Chienab992e52011-07-20 22:06:52 +0800105 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hineseb2eec92011-01-09 19:13:09 -0800106 if (FD && FD->isGlobal()) {
Stephen Hinesab5a5352012-08-04 15:13:40 -0700107 // Check that we don't have any array parameters being misintrepeted as
108 // kernel pointers due to the C type system's array to pointer decay.
109 size_t numParams = FD->getNumParams();
110 for (size_t i = 0; i < numParams; i++) {
111 const clang::ParmVarDecl *PVD = FD->getParamDecl(i);
112 clang::QualType QT = PVD->getOriginalType();
113 if (QT->isArrayType()) {
114 mDiagEngine.Report(
115 clang::FullSourceLoc(PVD->getTypeSpecStartLoc(), mSourceMgr),
116 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
117 "exported function parameters may "
118 "not have array type: %0")) << QT;
119 }
120 }
Stephen Hineseb2eec92011-01-09 19:13:09 -0800121 AnnotateFunction(FD);
122 }
Stephen Hinescfae0f32010-11-01 18:57:31 -0700123 }
124
Logan Chienfa6ef562011-11-25 13:50:02 +0800125 return Backend::HandleTopLevelDecl(D);
Stephen Hinescfae0f32010-11-01 18:57:31 -0700126}
127
Stephen Hinesc97a3332010-11-30 15:31:08 -0800128namespace {
129
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700130static bool ValidateVarDecl(clang::VarDecl *VD, unsigned int TargetAPI) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700131 if (!VD) {
132 return true;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800133 }
Stephen Hines78e69cb2011-04-22 15:03:19 -0700134
135 clang::ASTContext &C = VD->getASTContext();
136 const clang::Type *T = VD->getType().getTypePtr();
137 bool valid = true;
138
139 if (VD->getLinkage() == clang::ExternalLinkage) {
140 llvm::StringRef TypeName;
Stephen Hines5bfec8d2012-04-04 08:18:57 -0700141 if (!RSExportType::NormalizeType(T, TypeName, &C.getDiagnostics(), VD)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700142 valid = false;
143 }
144 }
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700145 valid &= RSExportType::ValidateVarDecl(VD, TargetAPI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700146
147 return valid;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800148}
149
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700150static bool ValidateASTContext(clang::ASTContext &C, unsigned int TargetAPI) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800151 bool valid = true;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700152 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800153 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
154 DE = TUDecl->decls_end();
155 DI != DE;
156 DI++) {
Logan Chienab992e52011-07-20 22:06:52 +0800157 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI);
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700158 if (VD && !ValidateVarDecl(VD, TargetAPI)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700159 valid = false;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800160 }
161 }
162
163 return valid;
164}
165
Stephen Hinese5e64432010-12-02 18:48:20 -0800166} // namespace
Stephen Hinesc97a3332010-11-30 15:31:08 -0800167
168void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
169 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
170
Stephen Hinesd5a84f62012-04-04 17:44:38 -0700171 if (!ValidateASTContext(C, getTargetAPI())) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800172 return;
173 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700174
Stephen Hines96ab06c2011-01-05 15:29:26 -0800175 int version = mContext->getVersion();
176 if (version == 0) {
177 // Not setting a version is an error
Stephen Hines7aff4a02011-12-08 18:34:27 -0800178 mDiagEngine.Report(
179 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
180 mDiagEngine.getCustomDiagID(
181 clang::DiagnosticsEngine::Error,
182 "missing pragma for version in source file"));
183 } else {
184 slangAssert(version == 1);
Stephen Hines96ab06c2011-01-05 15:29:26 -0800185 }
186
Stephen Hinescf9a73a2012-09-20 10:38:02 -0700187 if (mContext->getReflectJavaPackageName().empty()) {
188 mDiagEngine.Report(
189 mSourceMgr.getLocForEndOfFile(mSourceMgr.getMainFileID()),
190 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
191 "missing \"#pragma rs "
192 "java_package_name(com.foo.bar)\" "
193 "in source file"));
194 return;
195 }
196
Stephen Hines688e64b2011-08-23 16:01:25 -0700197 // Create a static global destructor if necessary (to handle RS object
198 // runtime cleanup).
199 clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
200 if (FD) {
201 HandleTopLevelDecl(clang::DeclGroupRef(FD));
202 }
203
Stephen Hinescfae0f32010-11-01 18:57:31 -0700204 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700205 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
206 E = TUDecl->decls_end(); I != E; I++) {
207 if ((I->getKind() >= clang::Decl::firstFunction) &&
208 (I->getKind() <= clang::Decl::lastFunction)) {
Logan Chienab992e52011-07-20 22:06:52 +0800209 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hineseb2eec92011-01-09 19:13:09 -0800210 if (FD && !FD->isGlobal()) {
211 AnnotateFunction(FD);
212 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700213 }
214 }
215
216 return;
217}
218
219///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800220void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Stephen Hinesc808a992010-11-29 17:20:42 -0800221 if (!mContext->processExport()) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800222 return;
Stephen Hinesc808a992010-11-29 17:20:42 -0800223 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700224
mkopec1c460b372012-01-09 11:21:50 -0500225 // Write optimization level
226 llvm::SmallVector<llvm::Value*, 1> OptimizationOption;
227 OptimizationOption.push_back(llvm::ConstantInt::get(
228 mLLVMContext, llvm::APInt(32, mCodeGenOpts.OptimizationLevel)));
229
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700230 // Dump export variable info
231 if (mContext->hasExportVar()) {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800232 int slotCount = 0;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700233 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800234 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700235
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700236 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800237
238 // We emit slot information (#rs_object_slots) for any reference counted
239 // RS type or pointer (which can also be bound).
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700240
zonr6315f762010-10-05 15:35:14 +0800241 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
242 E = mContext->export_vars_end();
243 I != E;
244 I++) {
245 const RSExportVar *EV = *I;
246 const RSExportType *ET = EV->getType();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800247 bool countsAsRSObject = false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700248
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700249 // Variable name
250 ExportVarInfo.push_back(
251 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700252
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700253 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800254 switch (ET->getClass()) {
255 case RSExportType::ExportClassPrimitive: {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800256 const RSExportPrimitiveType *PT =
257 static_cast<const RSExportPrimitiveType*>(ET);
Zonr Changa65ec162010-10-17 01:53:05 +0800258 ExportVarInfo.push_back(
259 llvm::MDString::get(
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800260 mLLVMContext, llvm::utostr_32(PT->getType())));
261 if (PT->isRSObjectType()) {
262 countsAsRSObject = true;
263 }
Zonr Changa65ec162010-10-17 01:53:05 +0800264 break;
265 }
266 case RSExportType::ExportClassPointer: {
267 ExportVarInfo.push_back(
268 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700269 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800270 ->getPointeeType()->getName()).c_str()));
271 break;
272 }
273 case RSExportType::ExportClassMatrix: {
274 ExportVarInfo.push_back(
275 llvm::MDString::get(
276 mLLVMContext, llvm::utostr_32(
277 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
278 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
279 break;
280 }
281 case RSExportType::ExportClassVector:
282 case RSExportType::ExportClassConstantArray:
283 case RSExportType::ExportClassRecord: {
284 ExportVarInfo.push_back(
285 llvm::MDString::get(mLLVMContext,
286 EV->getType()->getName().c_str()));
287 break;
288 }
289 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700291 mExportVarMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700292 llvm::MDNode::get(mLLVMContext, ExportVarInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 ExportVarInfo.clear();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800294
295 if (mRSObjectSlotsMetadata == NULL) {
296 mRSObjectSlotsMetadata =
297 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
298 }
299
300 if (countsAsRSObject) {
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700301 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
302 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800303 }
304
305 slotCount++;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700306 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700308
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700309 // Dump export function info
310 if (mContext->hasExportFunc()) {
311 if (mExportFuncMetadata == NULL)
312 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800313 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700314
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700315 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700316
zonr6315f762010-10-05 15:35:14 +0800317 for (RSContext::const_export_func_iterator
318 I = mContext->export_funcs_begin(),
319 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 I != E;
321 I++) {
zonr6315f762010-10-05 15:35:14 +0800322 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700323
324 // Function name
zonr6315f762010-10-05 15:35:14 +0800325 if (!EF->hasParam()) {
326 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
327 EF->getName().c_str()));
328 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800329 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700330 llvm::Function *HelperFunction;
331 const std::string HelperFunctionName(".helper_" + EF->getName());
332
Stephen Hines6e6578a2011-02-07 18:05:48 -0800333 slangAssert(F && "Function marked as exported disappeared in Bitcode");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700334
335 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700336 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800337 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700338
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800339 if (!F->getArgumentList().empty()) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700340 std::vector<llvm::Type*> HelperFunctionParameterTys;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800341 for (llvm::Function::arg_iterator AI = F->arg_begin(),
342 AE = F->arg_end(); AI != AE; AI++)
343 HelperFunctionParameterTys.push_back(AI->getType());
344
345 HelperFunctionParameterTy =
Stephen Hinesa67e4452011-07-19 15:39:26 -0700346 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800347 }
348
349 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
350 fprintf(stderr, "Failed to export function %s: parameter type "
351 "mismatch during creation of helper function.\n",
352 EF->getName().c_str());
353
354 const RSExportRecordType *Expected = EF->getParamPacketType();
355 if (Expected) {
356 fprintf(stderr, "Expected:\n");
357 Expected->getLLVMType()->dump();
358 }
359 if (HelperFunctionParameterTy) {
360 fprintf(stderr, "Got:\n");
361 HelperFunctionParameterTy->dump();
362 }
363 }
364
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700365 std::vector<llvm::Type*> Params;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800366 if (HelperFunctionParameterTy) {
367 llvm::PointerType *HelperFunctionParameterTyP =
368 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
369 Params.push_back(HelperFunctionParameterTyP);
370 }
371
372 llvm::FunctionType * HelperFunctionType =
373 llvm::FunctionType::get(F->getReturnType(),
Stephen Hinesa67e4452011-07-19 15:39:26 -0700374 Params,
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800375 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700376
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700377 HelperFunction =
378 llvm::Function::Create(HelperFunctionType,
379 llvm::GlobalValue::ExternalLinkage,
380 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800381 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700382
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700383 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
384 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700385
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700386 // Create helper function body
387 {
388 llvm::Argument *HelperFunctionParameter =
389 &(*HelperFunction->arg_begin());
390 llvm::BasicBlock *BB =
391 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
392 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
393 llvm::SmallVector<llvm::Value*, 6> Params;
394 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700395
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700396 Idx[0] =
397 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700398
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700399 // getelementptr and load instruction for all elements in
400 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800401 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700402 // getelementptr
Logan Chien9207a2e2011-10-21 15:39:28 +0800403 Idx[1] = llvm::ConstantInt::get(
404 llvm::Type::getInt32Ty(mLLVMContext), i);
405
406 llvm::Value *Ptr =
407 IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700408
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700409 // load
410 llvm::Value *V = IB->CreateLoad(Ptr);
411 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700412 }
413
Stephen Hinesa67e4452011-07-19 15:39:26 -0700414 // Call and pass the all elements as parameter to F
415 llvm::CallInst *CI = IB->CreateCall(F, Params);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700416
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700417 CI->setCallingConv(F->getCallingConv());
418
419 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
420 IB->CreateRetVoid();
421 else
422 IB->CreateRet(CI);
423
424 delete IB;
425 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700426 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700427
428 ExportFuncInfo.push_back(
429 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
430 }
431
432 mExportFuncMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700433 llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700434 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700435 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700436 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700437
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700438 // Dump export function info
439 if (mContext->hasExportForEach()) {
Stephen Hines7b51b552012-02-16 00:12:38 -0800440 if (mExportForEachNameMetadata == NULL) {
441 mExportForEachNameMetadata =
442 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_NAME_MN);
443 }
444 if (mExportForEachSignatureMetadata == NULL) {
445 mExportForEachSignatureMetadata =
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700446 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
Stephen Hines7b51b552012-02-16 00:12:38 -0800447 }
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700448
Stephen Hines7b51b552012-02-16 00:12:38 -0800449 llvm::SmallVector<llvm::Value*, 1> ExportForEachName;
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700450 llvm::SmallVector<llvm::Value*, 1> ExportForEachInfo;
451
452 for (RSContext::const_export_foreach_iterator
453 I = mContext->export_foreach_begin(),
454 E = mContext->export_foreach_end();
455 I != E;
456 I++) {
457 const RSExportForEach *EFE = *I;
458
Stephen Hines7b51b552012-02-16 00:12:38 -0800459 ExportForEachName.push_back(
460 llvm::MDString::get(mLLVMContext, EFE->getName().c_str()));
461
462 mExportForEachNameMetadata->addOperand(
463 llvm::MDNode::get(mLLVMContext, ExportForEachName));
464 ExportForEachName.clear();
465
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700466 ExportForEachInfo.push_back(
467 llvm::MDString::get(mLLVMContext,
Stephen Hines7b51b552012-02-16 00:12:38 -0800468 llvm::utostr_32(EFE->getSignatureMetadata())));
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700469
Stephen Hines7b51b552012-02-16 00:12:38 -0800470 mExportForEachSignatureMetadata->addOperand(
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700471 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
472 ExportForEachInfo.clear();
473 }
474 }
475
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700476 // Dump export type info
477 if (mContext->hasExportType()) {
478 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700479
zonr6315f762010-10-05 15:35:14 +0800480 for (RSContext::const_export_type_iterator
481 I = mContext->export_types_begin(),
482 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700483 I != E;
484 I++) {
485 // First, dump type name list to export
486 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700487
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700488 ExportTypeInfo.clear();
489 // Type name
490 ExportTypeInfo.push_back(
491 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700492
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700493 if (ET->getClass() == RSExportType::ExportClassRecord) {
494 const RSExportRecordType *ERT =
495 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700496
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700497 if (mExportTypeMetadata == NULL)
498 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800499 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700500
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700501 mExportTypeMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700502 llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700503
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700504 // Now, export struct field information to %[struct name]
505 std::string StructInfoMetadataName("%");
506 StructInfoMetadataName.append(ET->getName());
507 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800508 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700510
Stephen Hines6e6578a2011-02-07 18:05:48 -0800511 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
512 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800513 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
514 FE = ERT->fields_end();
515 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700516 FI++) {
517 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700518
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700519 // 1. field name
520 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
521 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700522
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700523 // 2. field type name
524 FieldInfo.push_back(
525 llvm::MDString::get(mLLVMContext,
526 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700527
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700528 StructInfoMetadata->addOperand(
529 llvm::MDNode::get(mLLVMContext, FieldInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700530 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700531 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700532 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700533 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700534 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700535
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700536 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700537}
538
539RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700540 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700541}
Stephen Hinese639eb52010-11-08 19:27:20 -0800542
543} // namespace slang