blob: 6ae73fca8b8fc25af12b9a07d038882ea7ae1cd0 [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_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
22#include "llvm/ADT/Twine.h"
23#include "llvm/ADT/StringExtras.h"
24
Stephen Hinese639eb52010-11-08 19:27:20 -080025#include "llvm/Constant.h"
26#include "llvm/Constants.h"
27#include "llvm/DerivedTypes.h"
28#include "llvm/Function.h"
29#include "llvm/Metadata.h"
30#include "llvm/Module.h"
31
32#include "llvm/Support/IRBuilder.h"
33
Stephen Hines6e6578a2011-02-07 18:05:48 -080034#include "slang_assert.h"
Zonr Chang592a9542010-10-07 20:03:58 +080035#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080036#include "slang_rs_context.h"
Stephen Hines4ccf75e2011-08-16 18:21:01 -070037#include "slang_rs_export_foreach.h"
zonr6315f762010-10-05 15:35:14 +080038#include "slang_rs_export_func.h"
39#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080040#include "slang_rs_export_var.h"
41#include "slang_rs_metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070042
Stephen Hinese639eb52010-11-08 19:27:20 -080043namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070044
45RSBackend::RSBackend(RSContext *Context,
Stephen Hinese639eb52010-11-08 19:27:20 -080046 clang::Diagnostic *Diags,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070047 const clang::CodeGenOptions &CodeGenOpts,
48 const clang::TargetOptions &TargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -080049 PragmaList *Pragmas,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070050 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080051 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070052 clang::SourceManager &SourceMgr,
Stephen Hines4a4bf922011-08-18 17:20:33 -070053 bool AllowRSPrefix)
zonr6315f762010-10-05 15:35:14 +080054 : Backend(Diags,
55 CodeGenOpts,
56 TargetOpts,
57 Pragmas,
58 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080059 OT),
zonr6315f762010-10-05 15:35:14 +080060 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080061 mSourceMgr(SourceMgr),
62 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080063 mExportVarMetadata(NULL),
64 mExportFuncMetadata(NULL),
Stephen Hines4ccf75e2011-08-16 18:21:01 -070065 mExportForEachMetadata(NULL),
Stephen Hinesb3a12fe2011-01-26 20:16:38 -080066 mExportTypeMetadata(NULL),
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070067 mRSObjectSlotsMetadata(NULL),
68 mRefCount(mContext->getASTContext()) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070069 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070070}
71
Stephen Hinescfae0f32010-11-01 18:57:31 -070072// 1) Add zero initialization of local RS object types
73void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
74 if (FD &&
75 FD->hasBody() &&
76 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070077 mRefCount.Init();
Stephen Hines4b32ffd2010-11-05 18:47:11 -070078 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070079 }
80 return;
81}
82
83void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
84 // Disallow user-defined functions with prefix "rs"
85 if (!mAllowRSPrefix) {
86 // Iterate all function declarations in the program.
87 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
88 I != E; I++) {
Logan Chienab992e52011-07-20 22:06:52 +080089 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hinescfae0f32010-11-01 18:57:31 -070090 if (FD == NULL)
91 continue;
92 if (!FD->getName().startswith("rs")) // Check prefix
93 continue;
94 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
95 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
96 mDiags.getCustomDiagID(clang::Diagnostic::Error,
97 "invalid function name prefix, "
98 "\"rs\" is reserved: '%0'"))
99 << FD->getName();
100 }
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()) {
107 AnnotateFunction(FD);
108 }
Stephen Hinescfae0f32010-11-01 18:57:31 -0700109 }
110
111 Backend::HandleTopLevelDecl(D);
112 return;
113}
114
Stephen Hinesc97a3332010-11-30 15:31:08 -0800115namespace {
116
Stephen Hines78e69cb2011-04-22 15:03:19 -0700117static bool ValidateVarDecl(clang::VarDecl *VD) {
118 if (!VD) {
119 return true;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800120 }
Stephen Hines78e69cb2011-04-22 15:03:19 -0700121
122 clang::ASTContext &C = VD->getASTContext();
123 const clang::Type *T = VD->getType().getTypePtr();
124 bool valid = true;
125
126 if (VD->getLinkage() == clang::ExternalLinkage) {
127 llvm::StringRef TypeName;
128 if (!RSExportType::NormalizeType(T, TypeName, &C.getDiagnostics(), VD)) {
129 valid = false;
130 }
131 }
132 valid &= RSExportType::ValidateVarDecl(VD);
133
134 return valid;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800135}
136
Stephen Hines78e69cb2011-04-22 15:03:19 -0700137static bool ValidateASTContext(clang::ASTContext &C) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800138 bool valid = true;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700139 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800140 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
141 DE = TUDecl->decls_end();
142 DI != DE;
143 DI++) {
Logan Chienab992e52011-07-20 22:06:52 +0800144 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700145 if (VD && !ValidateVarDecl(VD)) {
146 valid = false;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800147 }
148 }
149
150 return valid;
151}
152
Stephen Hinese5e64432010-12-02 18:48:20 -0800153} // namespace
Stephen Hinesc97a3332010-11-30 15:31:08 -0800154
155void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
156 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
157
Stephen Hines78e69cb2011-04-22 15:03:19 -0700158 if (!ValidateASTContext(C)) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800159 return;
160 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700161
Stephen Hines96ab06c2011-01-05 15:29:26 -0800162 int version = mContext->getVersion();
163 if (version == 0) {
164 // Not setting a version is an error
165 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
166 "Missing pragma for version in source file"));
167 } else if (version > 1) {
168 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
169 "Pragma for version in source file must be set to 1"));
170 }
171
Stephen Hinescfae0f32010-11-01 18:57:31 -0700172 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700173 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
174 E = TUDecl->decls_end(); I != E; I++) {
175 if ((I->getKind() >= clang::Decl::firstFunction) &&
176 (I->getKind() <= clang::Decl::lastFunction)) {
Logan Chienab992e52011-07-20 22:06:52 +0800177 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hineseb2eec92011-01-09 19:13:09 -0800178 if (FD && !FD->isGlobal()) {
179 AnnotateFunction(FD);
180 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700181 }
182 }
183
184 return;
185}
186
187///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800188void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Stephen Hinesc808a992010-11-29 17:20:42 -0800189 if (!mContext->processExport()) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800190 return;
Stephen Hinesc808a992010-11-29 17:20:42 -0800191 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700192
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700193 // Dump export variable info
194 if (mContext->hasExportVar()) {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800195 int slotCount = 0;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700196 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800197 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700198
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700199 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800200
201 // We emit slot information (#rs_object_slots) for any reference counted
202 // RS type or pointer (which can also be bound).
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700203
zonr6315f762010-10-05 15:35:14 +0800204 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
205 E = mContext->export_vars_end();
206 I != E;
207 I++) {
208 const RSExportVar *EV = *I;
209 const RSExportType *ET = EV->getType();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800210 bool countsAsRSObject = false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700211
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700212 // Variable name
213 ExportVarInfo.push_back(
214 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700215
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700216 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800217 switch (ET->getClass()) {
218 case RSExportType::ExportClassPrimitive: {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800219 const RSExportPrimitiveType *PT =
220 static_cast<const RSExportPrimitiveType*>(ET);
Zonr Changa65ec162010-10-17 01:53:05 +0800221 ExportVarInfo.push_back(
222 llvm::MDString::get(
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800223 mLLVMContext, llvm::utostr_32(PT->getType())));
224 if (PT->isRSObjectType()) {
225 countsAsRSObject = true;
226 }
Zonr Changa65ec162010-10-17 01:53:05 +0800227 break;
228 }
229 case RSExportType::ExportClassPointer: {
230 ExportVarInfo.push_back(
231 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700232 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800233 ->getPointeeType()->getName()).c_str()));
234 break;
235 }
236 case RSExportType::ExportClassMatrix: {
237 ExportVarInfo.push_back(
238 llvm::MDString::get(
239 mLLVMContext, llvm::utostr_32(
240 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
241 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
242 break;
243 }
244 case RSExportType::ExportClassVector:
245 case RSExportType::ExportClassConstantArray:
246 case RSExportType::ExportClassRecord: {
247 ExportVarInfo.push_back(
248 llvm::MDString::get(mLLVMContext,
249 EV->getType()->getName().c_str()));
250 break;
251 }
252 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700253
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700254 mExportVarMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700255 llvm::MDNode::get(mLLVMContext, ExportVarInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 ExportVarInfo.clear();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800257
258 if (mRSObjectSlotsMetadata == NULL) {
259 mRSObjectSlotsMetadata =
260 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
261 }
262
263 if (countsAsRSObject) {
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700264 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
265 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800266 }
267
268 slotCount++;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700269 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700270 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700271
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272 // Dump export function info
273 if (mContext->hasExportFunc()) {
274 if (mExportFuncMetadata == NULL)
275 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800276 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700277
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700278 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700279
zonr6315f762010-10-05 15:35:14 +0800280 for (RSContext::const_export_func_iterator
281 I = mContext->export_funcs_begin(),
282 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700283 I != E;
284 I++) {
zonr6315f762010-10-05 15:35:14 +0800285 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700286
287 // Function name
zonr6315f762010-10-05 15:35:14 +0800288 if (!EF->hasParam()) {
289 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
290 EF->getName().c_str()));
291 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800292 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 llvm::Function *HelperFunction;
294 const std::string HelperFunctionName(".helper_" + EF->getName());
295
Stephen Hines6e6578a2011-02-07 18:05:48 -0800296 slangAssert(F && "Function marked as exported disappeared in Bitcode");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297
298 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700299 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800300 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700301
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800302 if (!F->getArgumentList().empty()) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700303 std::vector<llvm::Type*> HelperFunctionParameterTys;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800304 for (llvm::Function::arg_iterator AI = F->arg_begin(),
305 AE = F->arg_end(); AI != AE; AI++)
306 HelperFunctionParameterTys.push_back(AI->getType());
307
308 HelperFunctionParameterTy =
Stephen Hinesa67e4452011-07-19 15:39:26 -0700309 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800310 }
311
312 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
313 fprintf(stderr, "Failed to export function %s: parameter type "
314 "mismatch during creation of helper function.\n",
315 EF->getName().c_str());
316
317 const RSExportRecordType *Expected = EF->getParamPacketType();
318 if (Expected) {
319 fprintf(stderr, "Expected:\n");
320 Expected->getLLVMType()->dump();
321 }
322 if (HelperFunctionParameterTy) {
323 fprintf(stderr, "Got:\n");
324 HelperFunctionParameterTy->dump();
325 }
326 }
327
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700328 std::vector<llvm::Type*> Params;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800329 if (HelperFunctionParameterTy) {
330 llvm::PointerType *HelperFunctionParameterTyP =
331 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
332 Params.push_back(HelperFunctionParameterTyP);
333 }
334
335 llvm::FunctionType * HelperFunctionType =
336 llvm::FunctionType::get(F->getReturnType(),
Stephen Hinesa67e4452011-07-19 15:39:26 -0700337 Params,
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800338 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700339
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700340 HelperFunction =
341 llvm::Function::Create(HelperFunctionType,
342 llvm::GlobalValue::ExternalLinkage,
343 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800344 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700345
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
347 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700348
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 // Create helper function body
350 {
351 llvm::Argument *HelperFunctionParameter =
352 &(*HelperFunction->arg_begin());
353 llvm::BasicBlock *BB =
354 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
355 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
356 llvm::SmallVector<llvm::Value*, 6> Params;
357 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700358
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700359 Idx[0] =
360 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700361
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700362 // getelementptr and load instruction for all elements in
363 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800364 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700365 // getelementptr
366 Idx[1] =
367 llvm::ConstantInt::get(
368 llvm::Type::getInt32Ty(mLLVMContext), i);
369 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
370 Idx,
371 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700372
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700373 // load
374 llvm::Value *V = IB->CreateLoad(Ptr);
375 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700376 }
377
Stephen Hinesa67e4452011-07-19 15:39:26 -0700378 // Call and pass the all elements as parameter to F
379 llvm::CallInst *CI = IB->CreateCall(F, Params);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700380
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700381 CI->setCallingConv(F->getCallingConv());
382
383 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
384 IB->CreateRetVoid();
385 else
386 IB->CreateRet(CI);
387
388 delete IB;
389 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700390 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700391
392 ExportFuncInfo.push_back(
393 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
394 }
395
396 mExportFuncMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700397 llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700398 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700399 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700400 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700401
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700402 // Dump export function info
403 if (mContext->hasExportForEach()) {
404 if (mExportForEachMetadata == NULL)
405 mExportForEachMetadata =
406 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
407
408 llvm::SmallVector<llvm::Value*, 1> ExportForEachInfo;
409
410 for (RSContext::const_export_foreach_iterator
411 I = mContext->export_foreach_begin(),
412 E = mContext->export_foreach_end();
413 I != E;
414 I++) {
415 const RSExportForEach *EFE = *I;
416
417 ExportForEachInfo.push_back(
418 llvm::MDString::get(mLLVMContext,
419 llvm::utostr_32(EFE->getMetadataEncoding())));
420
421 mExportForEachMetadata->addOperand(
422 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
423 ExportForEachInfo.clear();
424 }
425 }
426
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700427 // Dump export type info
428 if (mContext->hasExportType()) {
429 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700430
zonr6315f762010-10-05 15:35:14 +0800431 for (RSContext::const_export_type_iterator
432 I = mContext->export_types_begin(),
433 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700434 I != E;
435 I++) {
436 // First, dump type name list to export
437 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700438
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700439 ExportTypeInfo.clear();
440 // Type name
441 ExportTypeInfo.push_back(
442 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700443
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700444 if (ET->getClass() == RSExportType::ExportClassRecord) {
445 const RSExportRecordType *ERT =
446 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700447
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700448 if (mExportTypeMetadata == NULL)
449 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800450 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700451
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700452 mExportTypeMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700453 llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700454
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700455 // Now, export struct field information to %[struct name]
456 std::string StructInfoMetadataName("%");
457 StructInfoMetadataName.append(ET->getName());
458 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800459 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700460 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700461
Stephen Hines6e6578a2011-02-07 18:05:48 -0800462 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
463 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800464 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
465 FE = ERT->fields_end();
466 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700467 FI++) {
468 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700469
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700470 // 1. field name
471 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
472 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700473
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700474 // 2. field type name
475 FieldInfo.push_back(
476 llvm::MDString::get(mLLVMContext,
477 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700478
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700479 // 3. field kind
480 switch (F->getType()->getClass()) {
481 case RSExportType::ExportClassPrimitive:
482 case RSExportType::ExportClassVector: {
483 const RSExportPrimitiveType *EPT =
484 static_cast<const RSExportPrimitiveType*>(F->getType());
485 FieldInfo.push_back(
486 llvm::MDString::get(mLLVMContext,
487 llvm::itostr(EPT->getKind())));
488 break;
489 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700490
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700491 default: {
492 FieldInfo.push_back(
493 llvm::MDString::get(mLLVMContext,
494 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800495 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700496 break;
497 }
498 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700499
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700500 StructInfoMetadata->addOperand(
501 llvm::MDNode::get(mLLVMContext, FieldInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700502 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700503 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700504 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700505 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700506 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700507
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700508 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700509}
510
511RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700512 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700513}
Stephen Hinese639eb52010-11-08 19:27:20 -0800514
515} // namespace slang