blob: 3088d3fbbdb765367aab7c6e7a096b8ff754008a [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
Stephen Hinesfcda2352010-10-19 16:49:32 -070019#include <stack>
zonr6315f762010-10-05 15:35:14 +080020#include <vector>
21#include <string>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070022
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070023#include "llvm/Metadata.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024#include "llvm/Constant.h"
25#include "llvm/Constants.h"
26#include "llvm/Module.h"
27#include "llvm/Function.h"
28#include "llvm/DerivedTypes.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070029
zonr6315f762010-10-05 15:35:14 +080030#include "llvm/Support/IRBuilder.h"
31
32#include "llvm/ADT/Twine.h"
33#include "llvm/ADT/StringExtras.h"
34
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070035#include "clang/AST/DeclGroup.h"
Stephen Hinesfcda2352010-10-19 16:49:32 -070036#include "clang/AST/Expr.h"
37#include "clang/AST/OperationKinds.h"
38#include "clang/AST/Stmt.h"
39#include "clang/AST/StmtVisitor.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040
Zonr Chang592a9542010-10-07 20:03:58 +080041#include "slang_rs.h"
zonr6315f762010-10-05 15:35:14 +080042#include "slang_rs_context.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080043#include "slang_rs_metadata.h"
zonr6315f762010-10-05 15:35:14 +080044#include "slang_rs_export_var.h"
45#include "slang_rs_export_func.h"
46#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070047
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070048using namespace slang;
49
50RSBackend::RSBackend(RSContext *Context,
51 clang::Diagnostic &Diags,
52 const clang::CodeGenOptions &CodeGenOpts,
53 const clang::TargetOptions &TargetOpts,
54 const PragmaList &Pragmas,
55 llvm::raw_ostream *OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080056 Slang::OutputType OT,
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070057 clang::SourceManager &SourceMgr,
zonr6315f762010-10-05 15:35:14 +080058 bool AllowRSPrefix)
59 : Backend(Diags,
60 CodeGenOpts,
61 TargetOpts,
62 Pragmas,
63 OS,
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080064 OT),
zonr6315f762010-10-05 15:35:14 +080065 mContext(Context),
Zonr Chang3a9ca1f2010-10-06 17:52:56 +080066 mSourceMgr(SourceMgr),
67 mAllowRSPrefix(AllowRSPrefix),
zonr6315f762010-10-05 15:35:14 +080068 mExportVarMetadata(NULL),
69 mExportFuncMetadata(NULL),
70 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070071 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070072}
73
Stephen Hinesfcda2352010-10-19 16:49:32 -070074///////////////////////////////////////////////////////////////////////////////
Shih-wei Liao462aefd2010-06-04 15:32:04 -070075
Stephen Hinesfcda2352010-10-19 16:49:32 -070076namespace {
77
78 class RSObjectRefCounting : public clang::StmtVisitor<RSObjectRefCounting> {
79 private:
80 class Scope {
81 private:
82 clang::CompoundStmt *mCS; // Associated compound statement ({ ... })
83 std::list<clang::Decl*> mRSO; // Declared RS object in this scope
84
85 public:
86 Scope(clang::CompoundStmt *CS) : mCS(CS) {
87 return;
88 }
89
90 inline void addRSObject(clang::Decl* D) { mRSO.push_back(D); }
91 };
92 std::stack<Scope*> mScopeStack;
93
94 inline Scope *getCurrentScope() { return mScopeStack.top(); }
95
Zonr Changb1771ef2010-10-22 18:03:46 +080096 // Return false if the type of variable declared in VD is not an RS object
97 // type.
Stephen Hinesfcda2352010-10-19 16:49:32 -070098 static bool InitializeRSObject(clang::VarDecl *VD);
Zonr Changb1771ef2010-10-22 18:03:46 +080099 // Return an zero-initializer expr of the type DT. This processes both
100 // RS matrix type and RS object type.
101 static clang::Expr *CreateZeroInitializerForRSSpecificType(
Stephen Hinesfcda2352010-10-19 16:49:32 -0700102 RSExportPrimitiveType::DataType DT,
103 clang::ASTContext &C,
104 const clang::SourceLocation &Loc);
105
106 public:
107 void VisitChildren(clang::Stmt *S) {
108 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
109 I != E;
110 I++)
111 if (clang::Stmt *Child = *I)
112 Visit(Child);
113 }
114 void VisitStmt(clang::Stmt *S) { VisitChildren(S); }
115
116 void VisitDeclStmt(clang::DeclStmt *DS);
117 void VisitCompoundStmt(clang::CompoundStmt *CS);
118 void VisitBinAssign(clang::BinaryOperator *AS);
119
120 // We believe that RS objects never are involved in CompoundAssignOperator.
121 // I.e., rs_allocation foo; foo += bar;
122 };
123}
124
125bool RSObjectRefCounting::InitializeRSObject(clang::VarDecl *VD) {
126 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
127 RSExportPrimitiveType::DataType DT =
Zonr Changb1771ef2010-10-22 18:03:46 +0800128 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hinesfcda2352010-10-19 16:49:32 -0700129
130 if (DT == RSExportPrimitiveType::DataTypeUnknown)
131 return false;
132
133 if (VD->hasInit()) {
134 // TODO: Update the reference count of RS object in initializer.
135 // This can potentially be done as part of the assignment pass.
136 } else {
137 clang::Expr *ZeroInitializer =
Zonr Changb1771ef2010-10-22 18:03:46 +0800138 CreateZeroInitializerForRSSpecificType(DT,
139 VD->getASTContext(),
140 VD->getLocation());
Stephen Hinesfcda2352010-10-19 16:49:32 -0700141
142 if (ZeroInitializer) {
143 ZeroInitializer->setType(T->getCanonicalTypeInternal());
144 VD->setInit(ZeroInitializer);
145 }
146 }
147
Zonr Changb1771ef2010-10-22 18:03:46 +0800148 return RSExportPrimitiveType::IsRSObjectType(DT);
Stephen Hinesfcda2352010-10-19 16:49:32 -0700149}
150
Zonr Changb1771ef2010-10-22 18:03:46 +0800151clang::Expr *RSObjectRefCounting::CreateZeroInitializerForRSSpecificType(
Stephen Hinesfcda2352010-10-19 16:49:32 -0700152 RSExportPrimitiveType::DataType DT,
153 clang::ASTContext &C,
154 const clang::SourceLocation &Loc) {
155 clang::Expr *Res = NULL;
156 switch (DT) {
157 case RSExportPrimitiveType::DataTypeRSElement:
158 case RSExportPrimitiveType::DataTypeRSType:
159 case RSExportPrimitiveType::DataTypeRSAllocation:
160 case RSExportPrimitiveType::DataTypeRSSampler:
161 case RSExportPrimitiveType::DataTypeRSScript:
162 case RSExportPrimitiveType::DataTypeRSMesh:
163 case RSExportPrimitiveType::DataTypeRSProgramFragment:
164 case RSExportPrimitiveType::DataTypeRSProgramVertex:
165 case RSExportPrimitiveType::DataTypeRSProgramRaster:
166 case RSExportPrimitiveType::DataTypeRSProgramStore:
167 case RSExportPrimitiveType::DataTypeRSFont: {
168 // (ImplicitCastExpr 'nullptr_t'
169 // (IntegerLiteral 0)))
170 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
171 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
172 clang::Expr *CastToNull =
173 clang::ImplicitCastExpr::Create(C,
174 C.NullPtrTy,
175 clang::CK_IntegralToPointer,
176 Int0,
177 NULL,
178 clang::VK_RValue);
179
180 Res = new (C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
181 break;
182 }
183 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
184 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
185 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
186 // RS matrix is not completely an RS object. They hold data by themselves.
187 // (InitListExpr rs_matrix2x2
188 // (InitListExpr float[4]
189 // (FloatingLiteral 0)
190 // (FloatingLiteral 0)
191 // (FloatingLiteral 0)
192 // (FloatingLiteral 0)))
193 clang::QualType FloatTy = C.FloatTy;
194 // Constructor sets value to 0.0f by default
195 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
196 clang::FloatingLiteral *Float0Val =
197 clang::FloatingLiteral::Create(C,
198 Val,
199 /* isExact = */true,
200 FloatTy,
201 Loc);
202
Zonr Chang0307eaa2010-10-22 02:29:53 +0800203 unsigned N = 0;
Stephen Hinesfcda2352010-10-19 16:49:32 -0700204 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
205 N = 2;
206 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
207 N = 3;
208 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
209 N = 4;
210
211 // Directly allocate 16 elements instead of dynamically allocate N*N
212 clang::Expr *InitVals[16];
213 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
214 InitVals[i] = Float0Val;
215 clang::Expr *InitExpr =
216 new (C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
217 InitExpr->setType(C.getConstantArrayType(FloatTy,
218 llvm::APInt(32, 4),
219 clang::ArrayType::Normal,
220 /* EltTypeQuals = */0));
221
222 Res = new (C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
223 break;
224 }
225 case RSExportPrimitiveType::DataTypeUnknown:
226 case RSExportPrimitiveType::DataTypeFloat16:
227 case RSExportPrimitiveType::DataTypeFloat32:
228 case RSExportPrimitiveType::DataTypeFloat64:
229 case RSExportPrimitiveType::DataTypeSigned8:
230 case RSExportPrimitiveType::DataTypeSigned16:
231 case RSExportPrimitiveType::DataTypeSigned32:
232 case RSExportPrimitiveType::DataTypeSigned64:
233 case RSExportPrimitiveType::DataTypeUnsigned8:
234 case RSExportPrimitiveType::DataTypeUnsigned16:
235 case RSExportPrimitiveType::DataTypeUnsigned32:
236 case RSExportPrimitiveType::DataTypeUnsigned64:
237 case RSExportPrimitiveType::DataTypeBoolean:
238 case RSExportPrimitiveType::DataTypeUnsigned565:
239 case RSExportPrimitiveType::DataTypeUnsigned5551:
240 case RSExportPrimitiveType::DataTypeUnsigned4444:
241 case RSExportPrimitiveType::DataTypeMax: {
242 assert(false && "Not RS object type!");
243 }
244 // No default case will enable compiler detecting the missing cases
245 }
246
247 return Res;
248}
249
250void RSObjectRefCounting::VisitDeclStmt(clang::DeclStmt *DS) {
251 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
252 I != E;
253 I++) {
254 clang::Decl *D = *I;
255 if (D->getKind() == clang::Decl::Var) {
256 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
257 if (InitializeRSObject(VD))
258 getCurrentScope()->addRSObject(VD);
259 }
260 }
261 return;
262}
263
264void RSObjectRefCounting::VisitCompoundStmt(clang::CompoundStmt *CS) {
265 if (!CS->body_empty()) {
266 // Push a new scope
267 Scope *S = new Scope(CS);
268 mScopeStack.push(S);
269
270 VisitChildren(CS);
271
272 // Destroy the scope
273 // TODO: Update reference count of the RS object refenced by the
274 // getCurrentScope().
275 assert((getCurrentScope() == S) && "Corrupted scope stack!");
276 mScopeStack.pop();
277 delete S;
278 }
279 return;
280}
281
282void RSObjectRefCounting::VisitBinAssign(clang::BinaryOperator *AS) {
283 // TODO: Update reference count
284 return;
285}
286
Stephen Hinescfae0f32010-11-01 18:57:31 -0700287// 1) Add zero initialization of local RS object types
288void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
289 if (FD &&
290 FD->hasBody() &&
291 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
292 RSObjectRefCounting RSObjectRefCounter;
293 RSObjectRefCounter.Visit(FD->getBody());
294 }
295 return;
296}
297
298void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
299 // Disallow user-defined functions with prefix "rs"
300 if (!mAllowRSPrefix) {
301 // Iterate all function declarations in the program.
302 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
303 I != E; I++) {
304 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
305 if (FD == NULL)
306 continue;
307 if (!FD->getName().startswith("rs")) // Check prefix
308 continue;
309 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
310 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
311 mDiags.getCustomDiagID(clang::Diagnostic::Error,
312 "invalid function name prefix, "
313 "\"rs\" is reserved: '%0'"))
314 << FD->getName();
315 }
316 }
317
318 // Process any non-static function declarations
319 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
320 AnnotateFunction(dyn_cast<clang::FunctionDecl>(*I));
321 }
322
323 Backend::HandleTopLevelDecl(D);
324 return;
325}
326
Stephen Hinesfcda2352010-10-19 16:49:32 -0700327void RSBackend::HandleTranslationUnitPre(clang::ASTContext& C) {
Stephen Hinesfcda2352010-10-19 16:49:32 -0700328 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
329
Stephen Hinescfae0f32010-11-01 18:57:31 -0700330 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700331 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
332 E = TUDecl->decls_end(); I != E; I++) {
333 if ((I->getKind() >= clang::Decl::firstFunction) &&
334 (I->getKind() <= clang::Decl::lastFunction)) {
Stephen Hinescfae0f32010-11-01 18:57:31 -0700335 AnnotateFunction(static_cast<clang::FunctionDecl*>(*I));
Stephen Hinesfcda2352010-10-19 16:49:32 -0700336 }
337 }
338
339 return;
340}
341
342///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800343void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700344 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700345
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 // Dump export variable info
347 if (mContext->hasExportVar()) {
348 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800349 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700352
zonr6315f762010-10-05 15:35:14 +0800353 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
354 E = mContext->export_vars_end();
355 I != E;
356 I++) {
357 const RSExportVar *EV = *I;
358 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700359
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700360 // Variable name
361 ExportVarInfo.push_back(
362 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700363
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700364 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800365 switch (ET->getClass()) {
366 case RSExportType::ExportClassPrimitive: {
367 ExportVarInfo.push_back(
368 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700369 mLLVMContext, llvm::utostr_32(
Zonr Changa65ec162010-10-17 01:53:05 +0800370 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
371 break;
372 }
373 case RSExportType::ExportClassPointer: {
374 ExportVarInfo.push_back(
375 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700376 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800377 ->getPointeeType()->getName()).c_str()));
378 break;
379 }
380 case RSExportType::ExportClassMatrix: {
381 ExportVarInfo.push_back(
382 llvm::MDString::get(
383 mLLVMContext, llvm::utostr_32(
384 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
385 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
386 break;
387 }
388 case RSExportType::ExportClassVector:
389 case RSExportType::ExportClassConstantArray:
390 case RSExportType::ExportClassRecord: {
391 ExportVarInfo.push_back(
392 llvm::MDString::get(mLLVMContext,
393 EV->getType()->getName().c_str()));
394 break;
395 }
396 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700397
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700398 mExportVarMetadata->addOperand(
399 llvm::MDNode::get(mLLVMContext,
400 ExportVarInfo.data(),
401 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700402
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700403 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700404 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700405 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700406
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700407 // Dump export function info
408 if (mContext->hasExportFunc()) {
409 if (mExportFuncMetadata == NULL)
410 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800411 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700412
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700413 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700414
zonr6315f762010-10-05 15:35:14 +0800415 for (RSContext::const_export_func_iterator
416 I = mContext->export_funcs_begin(),
417 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700418 I != E;
419 I++) {
zonr6315f762010-10-05 15:35:14 +0800420 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700421
422 // Function name
zonr6315f762010-10-05 15:35:14 +0800423 if (!EF->hasParam()) {
424 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
425 EF->getName().c_str()));
426 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800427 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700428 llvm::Function *HelperFunction;
429 const std::string HelperFunctionName(".helper_" + EF->getName());
430
431 assert(F && "Function marked as exported disappeared in Bitcode");
432
433 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700434 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800435 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700436
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800437 if (!F->getArgumentList().empty()) {
438 std::vector<const llvm::Type*> HelperFunctionParameterTys;
439 for (llvm::Function::arg_iterator AI = F->arg_begin(),
440 AE = F->arg_end(); AI != AE; AI++)
441 HelperFunctionParameterTys.push_back(AI->getType());
442
443 HelperFunctionParameterTy =
444 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
445 }
446
447 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
448 fprintf(stderr, "Failed to export function %s: parameter type "
449 "mismatch during creation of helper function.\n",
450 EF->getName().c_str());
451
452 const RSExportRecordType *Expected = EF->getParamPacketType();
453 if (Expected) {
454 fprintf(stderr, "Expected:\n");
455 Expected->getLLVMType()->dump();
456 }
457 if (HelperFunctionParameterTy) {
458 fprintf(stderr, "Got:\n");
459 HelperFunctionParameterTy->dump();
460 }
461 }
462
463 std::vector<const llvm::Type*> Params;
464 if (HelperFunctionParameterTy) {
465 llvm::PointerType *HelperFunctionParameterTyP =
466 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
467 Params.push_back(HelperFunctionParameterTyP);
468 }
469
470 llvm::FunctionType * HelperFunctionType =
471 llvm::FunctionType::get(F->getReturnType(),
472 Params,
473 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700474
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700475 HelperFunction =
476 llvm::Function::Create(HelperFunctionType,
477 llvm::GlobalValue::ExternalLinkage,
478 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800479 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700480
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700481 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
482 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700483
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700484 // Create helper function body
485 {
486 llvm::Argument *HelperFunctionParameter =
487 &(*HelperFunction->arg_begin());
488 llvm::BasicBlock *BB =
489 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
490 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
491 llvm::SmallVector<llvm::Value*, 6> Params;
492 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700493
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700494 Idx[0] =
495 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700496
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700497 // getelementptr and load instruction for all elements in
498 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800499 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700500 // getelementptr
501 Idx[1] =
502 llvm::ConstantInt::get(
503 llvm::Type::getInt32Ty(mLLVMContext), i);
504 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
505 Idx,
506 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700507
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700508 // load
509 llvm::Value *V = IB->CreateLoad(Ptr);
510 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700511 }
512
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700513 // Call and pass the all elements as paramter to F
514 llvm::CallInst *CI = IB->CreateCall(F,
515 Params.data(),
516 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700517
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700518 CI->setCallingConv(F->getCallingConv());
519
520 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
521 IB->CreateRetVoid();
522 else
523 IB->CreateRet(CI);
524
525 delete IB;
526 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700527 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700528
529 ExportFuncInfo.push_back(
530 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
531 }
532
533 mExportFuncMetadata->addOperand(
534 llvm::MDNode::get(mLLVMContext,
535 ExportFuncInfo.data(),
536 ExportFuncInfo.size()));
537
538 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700539 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700540 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700541
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700542 // Dump export type info
543 if (mContext->hasExportType()) {
544 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700545
zonr6315f762010-10-05 15:35:14 +0800546 for (RSContext::const_export_type_iterator
547 I = mContext->export_types_begin(),
548 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700549 I != E;
550 I++) {
551 // First, dump type name list to export
552 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700553
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700554 ExportTypeInfo.clear();
555 // Type name
556 ExportTypeInfo.push_back(
557 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700558
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700559 if (ET->getClass() == RSExportType::ExportClassRecord) {
560 const RSExportRecordType *ERT =
561 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700562
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700563 if (mExportTypeMetadata == NULL)
564 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800565 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700566
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700567 mExportTypeMetadata->addOperand(
568 llvm::MDNode::get(mLLVMContext,
569 ExportTypeInfo.data(),
570 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700571
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700572 // Now, export struct field information to %[struct name]
573 std::string StructInfoMetadataName("%");
574 StructInfoMetadataName.append(ET->getName());
575 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800576 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700577 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700578
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700579 assert(StructInfoMetadata->getNumOperands() == 0 &&
580 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800581 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
582 FE = ERT->fields_end();
583 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700584 FI++) {
585 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700586
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700587 // 1. field name
588 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
589 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700590
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700591 // 2. field type name
592 FieldInfo.push_back(
593 llvm::MDString::get(mLLVMContext,
594 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700595
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700596 // 3. field kind
597 switch (F->getType()->getClass()) {
598 case RSExportType::ExportClassPrimitive:
599 case RSExportType::ExportClassVector: {
600 const RSExportPrimitiveType *EPT =
601 static_cast<const RSExportPrimitiveType*>(F->getType());
602 FieldInfo.push_back(
603 llvm::MDString::get(mLLVMContext,
604 llvm::itostr(EPT->getKind())));
605 break;
606 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700607
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700608 default: {
609 FieldInfo.push_back(
610 llvm::MDString::get(mLLVMContext,
611 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800612 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700613 break;
614 }
615 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700616
zonr6315f762010-10-05 15:35:14 +0800617 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
618 FieldInfo.data(),
619 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700620
621 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700622 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700623 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700624 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700625 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700626
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700627 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700628}
629
630RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700631 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700632}