blob: d4a081bbaf4f6c14255d1ecc17930f6b1df0711b [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,
Logan Chien9207a2e2011-10-21 15:39:28 +080046 clang::DiagnosticsEngine *DiagEngine,
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)
Logan Chien9207a2e2011-10-21 15:39:28 +080054 : Backend(DiagEngine, CodeGenOpts, TargetOpts, Pragmas, OS, OT),
55 mContext(Context),
56 mSourceMgr(SourceMgr),
57 mAllowRSPrefix(AllowRSPrefix),
58 mExportVarMetadata(NULL),
59 mExportFuncMetadata(NULL),
60 mExportForEachMetadata(NULL),
61 mExportTypeMetadata(NULL),
62 mRSObjectSlotsMetadata(NULL),
63 mRefCount(mContext->getASTContext()) {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070064}
65
Stephen Hinescfae0f32010-11-01 18:57:31 -070066// 1) Add zero initialization of local RS object types
67void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
68 if (FD &&
69 FD->hasBody() &&
70 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -070071 mRefCount.Init();
Stephen Hines4b32ffd2010-11-05 18:47:11 -070072 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070073 }
74 return;
75}
76
77void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
78 // Disallow user-defined functions with prefix "rs"
79 if (!mAllowRSPrefix) {
80 // Iterate all function declarations in the program.
81 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
82 I != E; I++) {
Logan Chienab992e52011-07-20 22:06:52 +080083 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hinescfae0f32010-11-01 18:57:31 -070084 if (FD == NULL)
85 continue;
86 if (!FD->getName().startswith("rs")) // Check prefix
87 continue;
88 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
Logan Chien9207a2e2011-10-21 15:39:28 +080089 mDiagEngine.Report(
90 clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
91 mDiagEngine.getCustomDiagID(clang::DiagnosticsEngine::Error,
92 "invalid function name prefix, "
93 "\"rs\" is reserved: '%0'"))
94 << FD->getName();
Stephen Hinescfae0f32010-11-01 18:57:31 -070095 }
96 }
97
98 // Process any non-static function declarations
99 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
Logan Chienab992e52011-07-20 22:06:52 +0800100 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hineseb2eec92011-01-09 19:13:09 -0800101 if (FD && FD->isGlobal()) {
102 AnnotateFunction(FD);
103 }
Stephen Hinescfae0f32010-11-01 18:57:31 -0700104 }
105
106 Backend::HandleTopLevelDecl(D);
107 return;
108}
109
Stephen Hinesc97a3332010-11-30 15:31:08 -0800110namespace {
111
Stephen Hines78e69cb2011-04-22 15:03:19 -0700112static bool ValidateVarDecl(clang::VarDecl *VD) {
113 if (!VD) {
114 return true;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800115 }
Stephen Hines78e69cb2011-04-22 15:03:19 -0700116
117 clang::ASTContext &C = VD->getASTContext();
118 const clang::Type *T = VD->getType().getTypePtr();
119 bool valid = true;
120
121 if (VD->getLinkage() == clang::ExternalLinkage) {
122 llvm::StringRef TypeName;
123 if (!RSExportType::NormalizeType(T, TypeName, &C.getDiagnostics(), VD)) {
124 valid = false;
125 }
126 }
127 valid &= RSExportType::ValidateVarDecl(VD);
128
129 return valid;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800130}
131
Stephen Hines78e69cb2011-04-22 15:03:19 -0700132static bool ValidateASTContext(clang::ASTContext &C) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800133 bool valid = true;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700134 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800135 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
136 DE = TUDecl->decls_end();
137 DI != DE;
138 DI++) {
Logan Chienab992e52011-07-20 22:06:52 +0800139 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*DI);
Stephen Hines78e69cb2011-04-22 15:03:19 -0700140 if (VD && !ValidateVarDecl(VD)) {
141 valid = false;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800142 }
143 }
144
145 return valid;
146}
147
Stephen Hinese5e64432010-12-02 18:48:20 -0800148} // namespace
Stephen Hinesc97a3332010-11-30 15:31:08 -0800149
150void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
151 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
152
Stephen Hines78e69cb2011-04-22 15:03:19 -0700153 if (!ValidateASTContext(C)) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800154 return;
155 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700156
Stephen Hines96ab06c2011-01-05 15:29:26 -0800157 int version = mContext->getVersion();
158 if (version == 0) {
159 // Not setting a version is an error
Logan Chien9207a2e2011-10-21 15:39:28 +0800160 mDiagEngine.Report(mDiagEngine.getCustomDiagID(
161 clang::DiagnosticsEngine::Error,
162 "Missing pragma for version in source file"));
Stephen Hines96ab06c2011-01-05 15:29:26 -0800163 } else if (version > 1) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800164 mDiagEngine.Report(mDiagEngine.getCustomDiagID(
165 clang::DiagnosticsEngine::Error,
166 "Pragma for version in source file must be set to 1"));
Stephen Hines96ab06c2011-01-05 15:29:26 -0800167 }
168
Stephen Hines688e64b2011-08-23 16:01:25 -0700169 // Create a static global destructor if necessary (to handle RS object
170 // runtime cleanup).
171 clang::FunctionDecl *FD = mRefCount.CreateStaticGlobalDtor();
172 if (FD) {
173 HandleTopLevelDecl(clang::DeclGroupRef(FD));
174 }
175
Stephen Hinescfae0f32010-11-01 18:57:31 -0700176 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700177 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
178 E = TUDecl->decls_end(); I != E; I++) {
179 if ((I->getKind() >= clang::Decl::firstFunction) &&
180 (I->getKind() <= clang::Decl::lastFunction)) {
Logan Chienab992e52011-07-20 22:06:52 +0800181 clang::FunctionDecl *FD = llvm::dyn_cast<clang::FunctionDecl>(*I);
Stephen Hineseb2eec92011-01-09 19:13:09 -0800182 if (FD && !FD->isGlobal()) {
183 AnnotateFunction(FD);
184 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700185 }
186 }
187
188 return;
189}
190
191///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800192void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Stephen Hinesc808a992010-11-29 17:20:42 -0800193 if (!mContext->processExport()) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800194 return;
Stephen Hinesc808a992010-11-29 17:20:42 -0800195 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700196
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197 // Dump export variable info
198 if (mContext->hasExportVar()) {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800199 int slotCount = 0;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700200 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800201 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700202
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700203 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800204
205 // We emit slot information (#rs_object_slots) for any reference counted
206 // RS type or pointer (which can also be bound).
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700207
zonr6315f762010-10-05 15:35:14 +0800208 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
209 E = mContext->export_vars_end();
210 I != E;
211 I++) {
212 const RSExportVar *EV = *I;
213 const RSExportType *ET = EV->getType();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800214 bool countsAsRSObject = false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700215
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700216 // Variable name
217 ExportVarInfo.push_back(
218 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700219
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700220 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800221 switch (ET->getClass()) {
222 case RSExportType::ExportClassPrimitive: {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800223 const RSExportPrimitiveType *PT =
224 static_cast<const RSExportPrimitiveType*>(ET);
Zonr Changa65ec162010-10-17 01:53:05 +0800225 ExportVarInfo.push_back(
226 llvm::MDString::get(
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800227 mLLVMContext, llvm::utostr_32(PT->getType())));
228 if (PT->isRSObjectType()) {
229 countsAsRSObject = true;
230 }
Zonr Changa65ec162010-10-17 01:53:05 +0800231 break;
232 }
233 case RSExportType::ExportClassPointer: {
234 ExportVarInfo.push_back(
235 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700236 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800237 ->getPointeeType()->getName()).c_str()));
238 break;
239 }
240 case RSExportType::ExportClassMatrix: {
241 ExportVarInfo.push_back(
242 llvm::MDString::get(
243 mLLVMContext, llvm::utostr_32(
244 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
245 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
246 break;
247 }
248 case RSExportType::ExportClassVector:
249 case RSExportType::ExportClassConstantArray:
250 case RSExportType::ExportClassRecord: {
251 ExportVarInfo.push_back(
252 llvm::MDString::get(mLLVMContext,
253 EV->getType()->getName().c_str()));
254 break;
255 }
256 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700257
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700258 mExportVarMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700259 llvm::MDNode::get(mLLVMContext, ExportVarInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700260 ExportVarInfo.clear();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800261
262 if (mRSObjectSlotsMetadata == NULL) {
263 mRSObjectSlotsMetadata =
264 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
265 }
266
267 if (countsAsRSObject) {
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700268 mRSObjectSlotsMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
269 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount))));
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800270 }
271
272 slotCount++;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 // Dump export function info
277 if (mContext->hasExportFunc()) {
278 if (mExportFuncMetadata == NULL)
279 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800280 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700281
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700282 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700283
zonr6315f762010-10-05 15:35:14 +0800284 for (RSContext::const_export_func_iterator
285 I = mContext->export_funcs_begin(),
286 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 I != E;
288 I++) {
zonr6315f762010-10-05 15:35:14 +0800289 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700290
291 // Function name
zonr6315f762010-10-05 15:35:14 +0800292 if (!EF->hasParam()) {
293 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
294 EF->getName().c_str()));
295 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800296 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297 llvm::Function *HelperFunction;
298 const std::string HelperFunctionName(".helper_" + EF->getName());
299
Stephen Hines6e6578a2011-02-07 18:05:48 -0800300 slangAssert(F && "Function marked as exported disappeared in Bitcode");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700301
302 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700303 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800304 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700305
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800306 if (!F->getArgumentList().empty()) {
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700307 std::vector<llvm::Type*> HelperFunctionParameterTys;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800308 for (llvm::Function::arg_iterator AI = F->arg_begin(),
309 AE = F->arg_end(); AI != AE; AI++)
310 HelperFunctionParameterTys.push_back(AI->getType());
311
312 HelperFunctionParameterTy =
Stephen Hinesa67e4452011-07-19 15:39:26 -0700313 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800314 }
315
316 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
317 fprintf(stderr, "Failed to export function %s: parameter type "
318 "mismatch during creation of helper function.\n",
319 EF->getName().c_str());
320
321 const RSExportRecordType *Expected = EF->getParamPacketType();
322 if (Expected) {
323 fprintf(stderr, "Expected:\n");
324 Expected->getLLVMType()->dump();
325 }
326 if (HelperFunctionParameterTy) {
327 fprintf(stderr, "Got:\n");
328 HelperFunctionParameterTy->dump();
329 }
330 }
331
Shih-wei Liao7c67e572011-07-19 05:54:53 -0700332 std::vector<llvm::Type*> Params;
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800333 if (HelperFunctionParameterTy) {
334 llvm::PointerType *HelperFunctionParameterTyP =
335 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
336 Params.push_back(HelperFunctionParameterTyP);
337 }
338
339 llvm::FunctionType * HelperFunctionType =
340 llvm::FunctionType::get(F->getReturnType(),
Stephen Hinesa67e4452011-07-19 15:39:26 -0700341 Params,
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800342 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700343
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700344 HelperFunction =
345 llvm::Function::Create(HelperFunctionType,
346 llvm::GlobalValue::ExternalLinkage,
347 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800348 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700349
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700350 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
351 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700352
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700353 // Create helper function body
354 {
355 llvm::Argument *HelperFunctionParameter =
356 &(*HelperFunction->arg_begin());
357 llvm::BasicBlock *BB =
358 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
359 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
360 llvm::SmallVector<llvm::Value*, 6> Params;
361 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700362
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700363 Idx[0] =
364 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700365
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700366 // getelementptr and load instruction for all elements in
367 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800368 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700369 // getelementptr
Logan Chien9207a2e2011-10-21 15:39:28 +0800370 Idx[1] = llvm::ConstantInt::get(
371 llvm::Type::getInt32Ty(mLLVMContext), i);
372
373 llvm::Value *Ptr =
374 IB->CreateInBoundsGEP(HelperFunctionParameter, Idx);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700375
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700376 // load
377 llvm::Value *V = IB->CreateLoad(Ptr);
378 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700379 }
380
Stephen Hinesa67e4452011-07-19 15:39:26 -0700381 // Call and pass the all elements as parameter to F
382 llvm::CallInst *CI = IB->CreateCall(F, Params);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700383
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700384 CI->setCallingConv(F->getCallingConv());
385
386 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
387 IB->CreateRetVoid();
388 else
389 IB->CreateRet(CI);
390
391 delete IB;
392 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700393 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700394
395 ExportFuncInfo.push_back(
396 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
397 }
398
399 mExportFuncMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700400 llvm::MDNode::get(mLLVMContext, ExportFuncInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700401 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700402 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700403 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700404
Stephen Hines4ccf75e2011-08-16 18:21:01 -0700405 // Dump export function info
406 if (mContext->hasExportForEach()) {
407 if (mExportForEachMetadata == NULL)
408 mExportForEachMetadata =
409 M->getOrInsertNamedMetadata(RS_EXPORT_FOREACH_MN);
410
411 llvm::SmallVector<llvm::Value*, 1> ExportForEachInfo;
412
413 for (RSContext::const_export_foreach_iterator
414 I = mContext->export_foreach_begin(),
415 E = mContext->export_foreach_end();
416 I != E;
417 I++) {
418 const RSExportForEach *EFE = *I;
419
420 ExportForEachInfo.push_back(
421 llvm::MDString::get(mLLVMContext,
422 llvm::utostr_32(EFE->getMetadataEncoding())));
423
424 mExportForEachMetadata->addOperand(
425 llvm::MDNode::get(mLLVMContext, ExportForEachInfo));
426 ExportForEachInfo.clear();
427 }
428 }
429
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700430 // Dump export type info
431 if (mContext->hasExportType()) {
432 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700433
zonr6315f762010-10-05 15:35:14 +0800434 for (RSContext::const_export_type_iterator
435 I = mContext->export_types_begin(),
436 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700437 I != E;
438 I++) {
439 // First, dump type name list to export
440 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700441
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700442 ExportTypeInfo.clear();
443 // Type name
444 ExportTypeInfo.push_back(
445 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700446
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700447 if (ET->getClass() == RSExportType::ExportClassRecord) {
448 const RSExportRecordType *ERT =
449 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700450
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700451 if (mExportTypeMetadata == NULL)
452 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800453 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700454
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700455 mExportTypeMetadata->addOperand(
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700456 llvm::MDNode::get(mLLVMContext, ExportTypeInfo));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700457
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700458 // Now, export struct field information to %[struct name]
459 std::string StructInfoMetadataName("%");
460 StructInfoMetadataName.append(ET->getName());
461 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800462 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700463 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700464
Stephen Hines6e6578a2011-02-07 18:05:48 -0800465 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
466 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800467 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
468 FE = ERT->fields_end();
469 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700470 FI++) {
471 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700472
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700473 // 1. field name
474 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
475 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700476
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700477 // 2. field type name
478 FieldInfo.push_back(
479 llvm::MDString::get(mLLVMContext,
480 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700481
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700482 // 3. field kind
483 switch (F->getType()->getClass()) {
484 case RSExportType::ExportClassPrimitive:
485 case RSExportType::ExportClassVector: {
486 const RSExportPrimitiveType *EPT =
487 static_cast<const RSExportPrimitiveType*>(F->getType());
488 FieldInfo.push_back(
489 llvm::MDString::get(mLLVMContext,
490 llvm::itostr(EPT->getKind())));
491 break;
492 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700493
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700494 default: {
495 FieldInfo.push_back(
496 llvm::MDString::get(mLLVMContext,
497 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800498 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700499 break;
500 }
501 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700502
Stephen Hinesd27a74e2011-07-13 20:59:46 -0700503 StructInfoMetadata->addOperand(
504 llvm::MDNode::get(mLLVMContext, FieldInfo));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700505 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700506 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700507 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700508 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700509 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700510
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700511 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700512}
513
514RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700515 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700516}
Stephen Hinese639eb52010-11-08 19:27:20 -0800517
518} // namespace slang