blob: 1e15c0d0a13d6f97f3db67d6d841023ee375f043 [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
Zonr Chang592a9542010-10-07 20:03:58 +080034#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080035#include "slang_rs_context.h"
zonr6315f762010-10-05 15:35:14 +080036#include "slang_rs_export_func.h"
37#include "slang_rs_export_type.h"
Stephen Hinese639eb52010-11-08 19:27:20 -080038#include "slang_rs_export_var.h"
39#include "slang_rs_metadata.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040
Stephen Hinese639eb52010-11-08 19:27:20 -080041namespace slang {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070042
43RSBackend::RSBackend(RSContext *Context,
Stephen Hinese639eb52010-11-08 19:27:20 -080044 clang::Diagnostic *Diags,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070045 const clang::CodeGenOptions &CodeGenOpts,
46 const clang::TargetOptions &TargetOpts,
Stephen Hines3fd0a942011-01-18 12:27:39 -080047 PragmaList *Pragmas,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070048 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080049 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070050 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080051 bool AllowRSPrefix)
52 : Backend(Diags,
53 CodeGenOpts,
54 TargetOpts,
55 Pragmas,
56 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080057 OT),
zonr6315f762010-10-05 15:35:14 +080058 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080059 mSourceMgr(SourceMgr),
60 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080061 mExportVarMetadata(NULL),
62 mExportFuncMetadata(NULL),
Stephen Hinesb3a12fe2011-01-26 20:16:38 -080063 mExportTypeMetadata(NULL),
64 mRSObjectSlotsMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070065 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070066}
67
Stephen Hinescfae0f32010-11-01 18:57:31 -070068// 1) Add zero initialization of local RS object types
69void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
70 if (FD &&
71 FD->hasBody() &&
72 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080073 mRefCount.Init(mContext->getASTContext());
Stephen Hines4b32ffd2010-11-05 18:47:11 -070074 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070075 }
76 return;
77}
78
79void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
80 // Disallow user-defined functions with prefix "rs"
81 if (!mAllowRSPrefix) {
82 // Iterate all function declarations in the program.
83 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
84 I != E; I++) {
85 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
86 if (FD == NULL)
87 continue;
88 if (!FD->getName().startswith("rs")) // Check prefix
89 continue;
90 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
91 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
92 mDiags.getCustomDiagID(clang::Diagnostic::Error,
93 "invalid function name prefix, "
94 "\"rs\" is reserved: '%0'"))
95 << FD->getName();
96 }
97 }
98
99 // Process any non-static function declarations
100 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
Stephen Hineseb2eec92011-01-09 19:13:09 -0800101 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
102 if (FD && FD->isGlobal()) {
103 AnnotateFunction(FD);
104 }
Stephen Hinescfae0f32010-11-01 18:57:31 -0700105 }
106
107 Backend::HandleTopLevelDecl(D);
108 return;
109}
110
Stephen Hinesc97a3332010-11-30 15:31:08 -0800111namespace {
112
Stephen Hinese5e64432010-12-02 18:48:20 -0800113bool ValidateVar(clang::VarDecl *VD, clang::Diagnostic *Diags,
114 clang::SourceManager *SM) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800115 llvm::StringRef TypeName;
116 const clang::Type *T = VD->getType().getTypePtr();
Stephen Hinesdd6206b2010-12-09 19:39:22 -0800117 if (!RSExportType::NormalizeType(T, TypeName, Diags, SM, VD)) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800118 return false;
119 }
120 return true;
121}
122
123bool ValidateASTContext(clang::ASTContext &C, clang::Diagnostic &Diags) {
124 bool valid = true;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700125 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
Stephen Hinesc97a3332010-11-30 15:31:08 -0800126 for (clang::DeclContext::decl_iterator DI = TUDecl->decls_begin(),
127 DE = TUDecl->decls_end();
128 DI != DE;
129 DI++) {
130 if (DI->getKind() == clang::Decl::Var) {
131 clang::VarDecl *VD = (clang::VarDecl*) (*DI);
132 if (VD->getLinkage() == clang::ExternalLinkage) {
Stephen Hinese5e64432010-12-02 18:48:20 -0800133 if (!ValidateVar(VD, &Diags, &C.getSourceManager())) {
Stephen Hinesc97a3332010-11-30 15:31:08 -0800134 valid = false;
Stephen Hinesc97a3332010-11-30 15:31:08 -0800135 }
136 }
137 }
138 }
139
140 return valid;
141}
142
Stephen Hinese5e64432010-12-02 18:48:20 -0800143} // namespace
Stephen Hinesc97a3332010-11-30 15:31:08 -0800144
145void RSBackend::HandleTranslationUnitPre(clang::ASTContext &C) {
146 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
147
148 if (!ValidateASTContext(C, mDiags)) {
149 return;
150 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700151
Stephen Hines96ab06c2011-01-05 15:29:26 -0800152 int version = mContext->getVersion();
153 if (version == 0) {
154 // Not setting a version is an error
155 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
156 "Missing pragma for version in source file"));
157 } else if (version > 1) {
158 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
159 "Pragma for version in source file must be set to 1"));
160 }
161
Stephen Hinescfae0f32010-11-01 18:57:31 -0700162 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700163 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
164 E = TUDecl->decls_end(); I != E; I++) {
165 if ((I->getKind() >= clang::Decl::firstFunction) &&
166 (I->getKind() <= clang::Decl::lastFunction)) {
Stephen Hineseb2eec92011-01-09 19:13:09 -0800167 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
168 if (FD && !FD->isGlobal()) {
169 AnnotateFunction(FD);
170 }
Stephen Hinesfcda2352010-10-19 16:49:32 -0700171 }
172 }
173
174 return;
175}
176
177///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800178void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Stephen Hinesc808a992010-11-29 17:20:42 -0800179 if (!mContext->processExport()) {
180 mDiags.Report(mDiags.getCustomDiagID(clang::Diagnostic::Error,
181 "elements cannot be exported"));
Stephen Hinesc97a3332010-11-30 15:31:08 -0800182 return;
Stephen Hinesc808a992010-11-29 17:20:42 -0800183 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700184
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700185 // Dump export variable info
186 if (mContext->hasExportVar()) {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800187 int slotCount = 0;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700188 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800189 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700190
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700191 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800192 llvm::SmallVector<llvm::Value*, 1> SlotVarInfo;
193
194 // We emit slot information (#rs_object_slots) for any reference counted
195 // RS type or pointer (which can also be bound).
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700196
zonr6315f762010-10-05 15:35:14 +0800197 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
198 E = mContext->export_vars_end();
199 I != E;
200 I++) {
201 const RSExportVar *EV = *I;
202 const RSExportType *ET = EV->getType();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800203 bool countsAsRSObject = false;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700204
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700205 // Variable name
206 ExportVarInfo.push_back(
207 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700208
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700209 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800210 switch (ET->getClass()) {
211 case RSExportType::ExportClassPrimitive: {
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800212 const RSExportPrimitiveType *PT =
213 static_cast<const RSExportPrimitiveType*>(ET);
Zonr Changa65ec162010-10-17 01:53:05 +0800214 ExportVarInfo.push_back(
215 llvm::MDString::get(
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800216 mLLVMContext, llvm::utostr_32(PT->getType())));
217 if (PT->isRSObjectType()) {
218 countsAsRSObject = true;
219 }
Zonr Changa65ec162010-10-17 01:53:05 +0800220 break;
221 }
222 case RSExportType::ExportClassPointer: {
223 ExportVarInfo.push_back(
224 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700225 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800226 ->getPointeeType()->getName()).c_str()));
227 break;
228 }
229 case RSExportType::ExportClassMatrix: {
230 ExportVarInfo.push_back(
231 llvm::MDString::get(
232 mLLVMContext, llvm::utostr_32(
233 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
234 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
235 break;
236 }
237 case RSExportType::ExportClassVector:
238 case RSExportType::ExportClassConstantArray:
239 case RSExportType::ExportClassRecord: {
240 ExportVarInfo.push_back(
241 llvm::MDString::get(mLLVMContext,
242 EV->getType()->getName().c_str()));
243 break;
244 }
245 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700246
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700247 mExportVarMetadata->addOperand(
248 llvm::MDNode::get(mLLVMContext,
249 ExportVarInfo.data(),
250 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700251
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252 ExportVarInfo.clear();
Stephen Hinesb3a12fe2011-01-26 20:16:38 -0800253
254 if (mRSObjectSlotsMetadata == NULL) {
255 mRSObjectSlotsMetadata =
256 M->getOrInsertNamedMetadata(RS_OBJECT_SLOTS_MN);
257 }
258
259 if (countsAsRSObject) {
260 SlotVarInfo.push_back(
261 llvm::MDString::get(mLLVMContext, llvm::utostr_32(slotCount)));
262
263 mRSObjectSlotsMetadata->addOperand(
264 llvm::MDNode::get(mLLVMContext,
265 SlotVarInfo.data(),
266 SlotVarInfo.size()));
267 }
268
269 slotCount++;
270 SlotVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700271 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700272 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 // Dump export function info
275 if (mContext->hasExportFunc()) {
276 if (mExportFuncMetadata == NULL)
277 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800278 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700279
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700280 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700281
zonr6315f762010-10-05 15:35:14 +0800282 for (RSContext::const_export_func_iterator
283 I = mContext->export_funcs_begin(),
284 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700285 I != E;
286 I++) {
zonr6315f762010-10-05 15:35:14 +0800287 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288
289 // Function name
zonr6315f762010-10-05 15:35:14 +0800290 if (!EF->hasParam()) {
291 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
292 EF->getName().c_str()));
293 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800294 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700295 llvm::Function *HelperFunction;
296 const std::string HelperFunctionName(".helper_" + EF->getName());
297
298 assert(F && "Function marked as exported disappeared in Bitcode");
299
300 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700301 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800302 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700303
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800304 if (!F->getArgumentList().empty()) {
305 std::vector<const llvm::Type*> HelperFunctionParameterTys;
306 for (llvm::Function::arg_iterator AI = F->arg_begin(),
307 AE = F->arg_end(); AI != AE; AI++)
308 HelperFunctionParameterTys.push_back(AI->getType());
309
310 HelperFunctionParameterTy =
311 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
312 }
313
314 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
315 fprintf(stderr, "Failed to export function %s: parameter type "
316 "mismatch during creation of helper function.\n",
317 EF->getName().c_str());
318
319 const RSExportRecordType *Expected = EF->getParamPacketType();
320 if (Expected) {
321 fprintf(stderr, "Expected:\n");
322 Expected->getLLVMType()->dump();
323 }
324 if (HelperFunctionParameterTy) {
325 fprintf(stderr, "Got:\n");
326 HelperFunctionParameterTy->dump();
327 }
328 }
329
330 std::vector<const llvm::Type*> Params;
331 if (HelperFunctionParameterTy) {
332 llvm::PointerType *HelperFunctionParameterTyP =
333 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
334 Params.push_back(HelperFunctionParameterTyP);
335 }
336
337 llvm::FunctionType * HelperFunctionType =
338 llvm::FunctionType::get(F->getReturnType(),
339 Params,
340 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700341
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700342 HelperFunction =
343 llvm::Function::Create(HelperFunctionType,
344 llvm::GlobalValue::ExternalLinkage,
345 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800346 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700347
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700348 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
349 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 // Create helper function body
352 {
353 llvm::Argument *HelperFunctionParameter =
354 &(*HelperFunction->arg_begin());
355 llvm::BasicBlock *BB =
356 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
357 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
358 llvm::SmallVector<llvm::Value*, 6> Params;
359 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700360
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700361 Idx[0] =
362 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700363
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700364 // getelementptr and load instruction for all elements in
365 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800366 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700367 // getelementptr
368 Idx[1] =
369 llvm::ConstantInt::get(
370 llvm::Type::getInt32Ty(mLLVMContext), i);
371 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
372 Idx,
373 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700374
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700375 // load
376 llvm::Value *V = IB->CreateLoad(Ptr);
377 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700378 }
379
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700380 // Call and pass the all elements as paramter to F
381 llvm::CallInst *CI = IB->CreateCall(F,
382 Params.data(),
383 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700384
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700385 CI->setCallingConv(F->getCallingConv());
386
387 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
388 IB->CreateRetVoid();
389 else
390 IB->CreateRet(CI);
391
392 delete IB;
393 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700394 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700395
396 ExportFuncInfo.push_back(
397 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
398 }
399
400 mExportFuncMetadata->addOperand(
401 llvm::MDNode::get(mLLVMContext,
402 ExportFuncInfo.data(),
403 ExportFuncInfo.size()));
404
405 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700406 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700407 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700408
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700409 // Dump export type info
410 if (mContext->hasExportType()) {
411 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700412
zonr6315f762010-10-05 15:35:14 +0800413 for (RSContext::const_export_type_iterator
414 I = mContext->export_types_begin(),
415 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700416 I != E;
417 I++) {
418 // First, dump type name list to export
419 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700420
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700421 ExportTypeInfo.clear();
422 // Type name
423 ExportTypeInfo.push_back(
424 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700425
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700426 if (ET->getClass() == RSExportType::ExportClassRecord) {
427 const RSExportRecordType *ERT =
428 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700429
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700430 if (mExportTypeMetadata == NULL)
431 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800432 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700433
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700434 mExportTypeMetadata->addOperand(
435 llvm::MDNode::get(mLLVMContext,
436 ExportTypeInfo.data(),
437 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700438
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700439 // Now, export struct field information to %[struct name]
440 std::string StructInfoMetadataName("%");
441 StructInfoMetadataName.append(ET->getName());
442 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800443 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700444 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700445
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700446 assert(StructInfoMetadata->getNumOperands() == 0 &&
447 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800448 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
449 FE = ERT->fields_end();
450 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700451 FI++) {
452 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700453
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700454 // 1. field name
455 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
456 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700457
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700458 // 2. field type name
459 FieldInfo.push_back(
460 llvm::MDString::get(mLLVMContext,
461 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700462
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700463 // 3. field kind
464 switch (F->getType()->getClass()) {
465 case RSExportType::ExportClassPrimitive:
466 case RSExportType::ExportClassVector: {
467 const RSExportPrimitiveType *EPT =
468 static_cast<const RSExportPrimitiveType*>(F->getType());
469 FieldInfo.push_back(
470 llvm::MDString::get(mLLVMContext,
471 llvm::itostr(EPT->getKind())));
472 break;
473 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700474
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700475 default: {
476 FieldInfo.push_back(
477 llvm::MDString::get(mLLVMContext,
478 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800479 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700480 break;
481 }
482 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700483
zonr6315f762010-10-05 15:35:14 +0800484 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
485 FieldInfo.data(),
486 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700487
488 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700489 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700490 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700491 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700492 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700493
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700494 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700495}
496
497RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700498 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700499}
Stephen Hinese639eb52010-11-08 19:27:20 -0800500
501} // namespace slang