blob: db2595dcfd8cc63b18ff50c101ea831ec588ae1f [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"
zonr6315f762010-10-05 15:35:14 +080037#include "slang_rs_export_func.h"
38#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080039#include "slang_rs_export_var.h"
40#include "slang_rs_metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070041
Stephen Hinese639eb52010-11-08 19:27:20 -080042namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070043
44RSBackend::RSBackend(RSContext *Context,
Stephen Hinese639eb52010-11-08 19:27:20 -080045 clang::Diagnostic *Diags,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070046 const clang::CodeGenOptions &CodeGenOpts,
47 const clang::TargetOptions &TargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -080048 PragmaList *Pragmas,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070049 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080050 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080052 bool AllowRSPrefix)
53 : Backend(Diags,
54 CodeGenOpts,
55 TargetOpts,
56 Pragmas,
57 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080058 OT),
zonr6315f762010-10-05 15:35:14 +080059 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080060 mSourceMgr(SourceMgr),
61 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080062 mExportVarMetadata(NULL),
63 mExportFuncMetadata(NULL),
Stephen Hinesb3a12fe2011-01-26 20:16:38 -080064 mExportTypeMetadata(NULL),
65 mRSObjectSlotsMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070066 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070067}
68
Stephen Hinescfae0f32010-11-01 18:57:31 -070069// 1) Add zero initialization of local RS object types
70void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
71 if (FD &&
72 FD->hasBody() &&
73 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -080074 mRefCount.Init(mContext->getASTContext(), &mDiags);
Stephen Hines4b32ffd2010-11-05 18:47:11 -070075 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070076 }
77 return;
78}
79
80void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
81 // Disallow user-defined functions with prefix "rs"
82 if (!mAllowRSPrefix) {
83 // Iterate all function declarations in the program.
84 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
85 I != E; I++) {
86 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
87 if (FD == NULL)
88 continue;
89 if (!FD->getName().startswith("rs")) // Check prefix
90 continue;
91 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
92 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
93 mDiags.getCustomDiagID(clang::Diagnostic::Error,
94 "invalid function name prefix, "
95 "\"rs\" is reserved: '%0'"))
96 << FD->getName();
97 }
98 }
99
100 // Process any non-static function declarations
101 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
Stephen Hineseb2eec92011-01-09 19:13:09 -0800102 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
103 if (FD && FD->isGlobal()) {
104 AnnotateFunction(FD);
105 }
Stephen Hinescfae0f32010-11-01 18:57:31 -0700106 }
107
108 Backend::HandleTopLevelDecl(D);
109 return;
110}
111
Stephen Hinesc97a3332010-11-30 15:31:08 -0800112namespace {
113
Stephen Hinese5e64432010-12-02 18:48:20 -0800114bool ValidateVar(clang::VarDecl *VD, clang::Diagnostic *Diags,
115 clang::SourceManager *SM) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800116 llvm::StringRef TypeName;
117 const clang::Type *T = VD->getType().getTypePtr();
Stephen Hinesdd6206b2010-12-09 19:39:22 -0800118 if (!RSExportType::NormalizeType(T, TypeName, Diags, SM, VD)) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800119 return false;
120 }
121 return true;
122}
123
124bool ValidateASTContext(clang::ASTContext &C, clang::Diagnostic &Diags) {
125 bool valid = true;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700126 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800127 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
128 DE = TUDecl->decls_end();
129 DI != DE;
130 DI++) {
131 if (DI->getKind() == clang::Decl::Var) {
132 clang::VarDecl *VD = (clang::VarDecl*) (*DI);
133 if (VD->getLinkage() == clang::ExternalLinkage) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800134 if (!ValidateVar(VD, &Diags, &C.getSourceManager())) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800135 valid = false;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800136 }
137 }
138 }
139 }
140
141 return valid;
142}
143
Stephen Hinese5e64432010-12-02 18:48:20 -0800144} // namespace
Stephen Hinesc97a3332010-11-30 15:31:08 -0800145
146void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
147 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
148
149 if (!ValidateASTContext(C, mDiags)) {
150 return;
151 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700152
Stephen Hines96ab06c2011-01-05 15:29:26 -0800153 int version = mContext->getVersion();
154 if (version == 0) {
155 // Not setting a version is an error
156 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
157 "Missing pragma for version in source file"));
158 } else if (version > 1) {
159 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
160 "Pragma for version in source file must be set to 1"));
161 }
162
Stephen Hinescfae0f32010-11-01 18:57:31 -0700163 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700164 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
165 E = TUDecl->decls_end(); I != E; I++) {
166 if ((I->getKind() >= clang::Decl::firstFunction) &&
167 (I->getKind() <= clang::Decl::lastFunction)) {
Stephen Hineseb2eec92011-01-09 19:13:09 -0800168 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
169 if (FD && !FD->isGlobal()) {
170 AnnotateFunction(FD);
171 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700172 }
173 }
174
175 return;
176}
177
178///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800179void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Stephen Hinesc808a992010-11-29 17:20:42 -0800180 if (!mContext->processExport()) {
181 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
182 "elements cannot be exported"));
Stephen Hinesc97a3332010-11-30 15:31:08 -0800183 return;
Stephen Hinesc808a992010-11-29 17:20:42 -0800184 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700185
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700186 // Dump export variable info
187 if (mContext->hasExportVar()) {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800188 int slotCount = 0;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700189 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800190 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700191
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800193 llvm::SmallVector<llvm::Value*, 1> SlotVarInfo;
194
195 // We emit slot information (#rs_object_slots) for any reference counted
196 // RS type or pointer (which can also be bound).
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700197
zonr6315f762010-10-05 15:35:14 +0800198 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
199 E = mContext->export_vars_end();
200 I != E;
201 I++) {
202 const RSExportVar *EV = *I;
203 const RSExportType *ET = EV->getType();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800204 bool countsAsRSObject = false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700205
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700206 // Variable name
207 ExportVarInfo.push_back(
208 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700209
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700210 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800211 switch (ET->getClass()) {
212 case RSExportType::ExportClassPrimitive: {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800213 const RSExportPrimitiveType *PT =
214 static_cast<const RSExportPrimitiveType*>(ET);
Zonr Changa65ec162010-10-17 01:53:05 +0800215 ExportVarInfo.push_back(
216 llvm::MDString::get(
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800217 mLLVMContext, llvm::utostr_32(PT->getType())));
218 if (PT->isRSObjectType()) {
219 countsAsRSObject = true;
220 }
Zonr Changa65ec162010-10-17 01:53:05 +0800221 break;
222 }
223 case RSExportType::ExportClassPointer: {
224 ExportVarInfo.push_back(
225 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700226 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800227 ->getPointeeType()->getName()).c_str()));
228 break;
229 }
230 case RSExportType::ExportClassMatrix: {
231 ExportVarInfo.push_back(
232 llvm::MDString::get(
233 mLLVMContext, llvm::utostr_32(
234 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
235 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
236 break;
237 }
238 case RSExportType::ExportClassVector:
239 case RSExportType::ExportClassConstantArray:
240 case RSExportType::ExportClassRecord: {
241 ExportVarInfo.push_back(
242 llvm::MDString::get(mLLVMContext,
243 EV->getType()->getName().c_str()));
244 break;
245 }
246 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700247
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700248 mExportVarMetadata->addOperand(
249 llvm::MDNode::get(mLLVMContext,
250 ExportVarInfo.data(),
251 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700252
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700253 ExportVarInfo.clear();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800254
255 if (mRSObjectSlotsMetadata == NULL) {
256 mRSObjectSlotsMetadata =
257 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
258 }
259
260 if (countsAsRSObject) {
261 SlotVarInfo.push_back(
262 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount)));
263
264 mRSObjectSlotsMetadata->addOperand(
265 llvm::MDNode::get(mLLVMContext,
266 SlotVarInfo.data(),
267 SlotVarInfo.size()));
268 }
269
270 slotCount++;
271 SlotVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700272 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700273 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700274
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700275 // Dump export function info
276 if (mContext->hasExportFunc()) {
277 if (mExportFuncMetadata == NULL)
278 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800279 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700280
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700281 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700282
zonr6315f762010-10-05 15:35:14 +0800283 for (RSContext::const_export_func_iterator
284 I = mContext->export_funcs_begin(),
285 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700286 I != E;
287 I++) {
zonr6315f762010-10-05 15:35:14 +0800288 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700289
290 // Function name
zonr6315f762010-10-05 15:35:14 +0800291 if (!EF->hasParam()) {
292 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
293 EF->getName().c_str()));
294 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800295 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700296 llvm::Function *HelperFunction;
297 const std::string HelperFunctionName(".helper_" + EF->getName());
298
Stephen Hines6e6578a2011-02-07 18:05:48 -0800299 slangAssert(F && "Function marked as exported disappeared in Bitcode");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700300
301 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700302 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800303 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700304
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800305 if (!F->getArgumentList().empty()) {
306 std::vector<const llvm::Type*> HelperFunctionParameterTys;
307 for (llvm::Function::arg_iterator AI = F->arg_begin(),
308 AE = F->arg_end(); AI != AE; AI++)
309 HelperFunctionParameterTys.push_back(AI->getType());
310
311 HelperFunctionParameterTy =
312 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
313 }
314
315 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
316 fprintf(stderr, "Failed to export function %s: parameter type "
317 "mismatch during creation of helper function.\n",
318 EF->getName().c_str());
319
320 const RSExportRecordType *Expected = EF->getParamPacketType();
321 if (Expected) {
322 fprintf(stderr, "Expected:\n");
323 Expected->getLLVMType()->dump();
324 }
325 if (HelperFunctionParameterTy) {
326 fprintf(stderr, "Got:\n");
327 HelperFunctionParameterTy->dump();
328 }
329 }
330
331 std::vector<const llvm::Type*> Params;
332 if (HelperFunctionParameterTy) {
333 llvm::PointerType *HelperFunctionParameterTyP =
334 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
335 Params.push_back(HelperFunctionParameterTyP);
336 }
337
338 llvm::FunctionType * HelperFunctionType =
339 llvm::FunctionType::get(F->getReturnType(),
340 Params,
341 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700342
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700343 HelperFunction =
344 llvm::Function::Create(HelperFunctionType,
345 llvm::GlobalValue::ExternalLinkage,
346 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800347 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700348
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700349 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
350 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700351
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700352 // Create helper function body
353 {
354 llvm::Argument *HelperFunctionParameter =
355 &(*HelperFunction->arg_begin());
356 llvm::BasicBlock *BB =
357 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
358 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
359 llvm::SmallVector<llvm::Value*, 6> Params;
360 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700361
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700362 Idx[0] =
363 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700364
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700365 // getelementptr and load instruction for all elements in
366 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800367 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700368 // getelementptr
369 Idx[1] =
370 llvm::ConstantInt::get(
371 llvm::Type::getInt32Ty(mLLVMContext), i);
372 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
373 Idx,
374 Idx + 2);
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
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700381 // Call and pass the all elements as paramter to F
382 llvm::CallInst *CI = IB->CreateCall(F,
383 Params.data(),
384 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700385
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700386 CI->setCallingConv(F->getCallingConv());
387
388 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
389 IB->CreateRetVoid();
390 else
391 IB->CreateRet(CI);
392
393 delete IB;
394 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700395 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700396
397 ExportFuncInfo.push_back(
398 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
399 }
400
401 mExportFuncMetadata->addOperand(
402 llvm::MDNode::get(mLLVMContext,
403 ExportFuncInfo.data(),
404 ExportFuncInfo.size()));
405
406 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700407 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700408 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700409
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700410 // Dump export type info
411 if (mContext->hasExportType()) {
412 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700413
zonr6315f762010-10-05 15:35:14 +0800414 for (RSContext::const_export_type_iterator
415 I = mContext->export_types_begin(),
416 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700417 I != E;
418 I++) {
419 // First, dump type name list to export
420 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700421
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700422 ExportTypeInfo.clear();
423 // Type name
424 ExportTypeInfo.push_back(
425 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700426
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700427 if (ET->getClass() == RSExportType::ExportClassRecord) {
428 const RSExportRecordType *ERT =
429 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700430
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700431 if (mExportTypeMetadata == NULL)
432 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800433 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700434
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700435 mExportTypeMetadata->addOperand(
436 llvm::MDNode::get(mLLVMContext,
437 ExportTypeInfo.data(),
438 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700439
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700440 // Now, export struct field information to %[struct name]
441 std::string StructInfoMetadataName("%");
442 StructInfoMetadataName.append(ET->getName());
443 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800444 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700445 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700446
Stephen Hines6e6578a2011-02-07 18:05:48 -0800447 slangAssert(StructInfoMetadata->getNumOperands() == 0 &&
448 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800449 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
450 FE = ERT->fields_end();
451 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700452 FI++) {
453 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700454
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700455 // 1. field name
456 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
457 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700458
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700459 // 2. field type name
460 FieldInfo.push_back(
461 llvm::MDString::get(mLLVMContext,
462 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700463
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700464 // 3. field kind
465 switch (F->getType()->getClass()) {
466 case RSExportType::ExportClassPrimitive:
467 case RSExportType::ExportClassVector: {
468 const RSExportPrimitiveType *EPT =
469 static_cast<const RSExportPrimitiveType*>(F->getType());
470 FieldInfo.push_back(
471 llvm::MDString::get(mLLVMContext,
472 llvm::itostr(EPT->getKind())));
473 break;
474 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700475
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700476 default: {
477 FieldInfo.push_back(
478 llvm::MDString::get(mLLVMContext,
479 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800480 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700481 break;
482 }
483 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700484
zonr6315f762010-10-05 15:35:14 +0800485 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
486 FieldInfo.data(),
487 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700488
489 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700490 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700491 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700492 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700493 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700494
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700495 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700496}
497
498RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700499 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700500}
Stephen Hinese639eb52010-11-08 19:27:20 -0800501
502} // namespace slang