blob: 9fa4d98aba9c116662e88907426fb36e39cbd5b3 [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,
47 const PragmaList &Pragmas,
48 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),
63 mExportTypeMetadata(NULL) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070064 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -070065}
66
Stephen Hinescfae0f32010-11-01 18:57:31 -070067// 1) Add zero initialization of local RS object types
68void RSBackend::AnnotateFunction(clang::FunctionDecl *FD) {
69 if (FD &&
70 FD->hasBody() &&
71 !SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr)) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080072 mRefCount.Init(mContext->getASTContext());
Stephen Hines4b32ffd2010-11-05 18:47:11 -070073 mRefCount.Visit(FD->getBody());
Stephen Hinescfae0f32010-11-01 18:57:31 -070074 }
75 return;
76}
77
78void RSBackend::HandleTopLevelDecl(clang::DeclGroupRef D) {
79 // Disallow user-defined functions with prefix "rs"
80 if (!mAllowRSPrefix) {
81 // Iterate all function declarations in the program.
82 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end();
83 I != E; I++) {
84 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
85 if (FD == NULL)
86 continue;
87 if (!FD->getName().startswith("rs")) // Check prefix
88 continue;
89 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
90 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
91 mDiags.getCustomDiagID(clang::Diagnostic::Error,
92 "invalid function name prefix, "
93 "\"rs\" is reserved: '%0'"))
94 << FD->getName();
95 }
96 }
97
98 // Process any non-static function declarations
99 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
100 AnnotateFunction(dyn_cast<clang::FunctionDecl>(*I));
101 }
102
103 Backend::HandleTopLevelDecl(D);
104 return;
105}
106
Stephen Hinesfcda2352010-10-19 16:49:32 -0700107void RSBackend::HandleTranslationUnitPre(clang::ASTContext& C) {
Stephen Hinesfcda2352010-10-19 16:49:32 -0700108 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
109
Stephen Hinescfae0f32010-11-01 18:57:31 -0700110 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700111 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
112 E = TUDecl->decls_end(); I != E; I++) {
113 if ((I->getKind() >= clang::Decl::firstFunction) &&
114 (I->getKind() <= clang::Decl::lastFunction)) {
Stephen Hinescfae0f32010-11-01 18:57:31 -0700115 AnnotateFunction(static_cast<clang::FunctionDecl*>(*I));
Stephen Hinesfcda2352010-10-19 16:49:32 -0700116 }
117 }
118
119 return;
120}
121
122///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800123void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700124 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700125
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700126 // Dump export variable info
127 if (mContext->hasExportVar()) {
128 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800129 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700130
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700132
zonr6315f762010-10-05 15:35:14 +0800133 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
134 E = mContext->export_vars_end();
135 I != E;
136 I++) {
137 const RSExportVar *EV = *I;
138 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700139
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700140 // Variable name
141 ExportVarInfo.push_back(
142 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700143
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700144 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800145 switch (ET->getClass()) {
146 case RSExportType::ExportClassPrimitive: {
147 ExportVarInfo.push_back(
148 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700149 mLLVMContext, llvm::utostr_32(
Zonr Changa65ec162010-10-17 01:53:05 +0800150 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
151 break;
152 }
153 case RSExportType::ExportClassPointer: {
154 ExportVarInfo.push_back(
155 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700156 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800157 ->getPointeeType()->getName()).c_str()));
158 break;
159 }
160 case RSExportType::ExportClassMatrix: {
161 ExportVarInfo.push_back(
162 llvm::MDString::get(
163 mLLVMContext, llvm::utostr_32(
164 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
165 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
166 break;
167 }
168 case RSExportType::ExportClassVector:
169 case RSExportType::ExportClassConstantArray:
170 case RSExportType::ExportClassRecord: {
171 ExportVarInfo.push_back(
172 llvm::MDString::get(mLLVMContext,
173 EV->getType()->getName().c_str()));
174 break;
175 }
176 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700177
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700178 mExportVarMetadata->addOperand(
179 llvm::MDNode::get(mLLVMContext,
180 ExportVarInfo.data(),
181 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700182
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700183 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700184 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700185 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700186
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 // Dump export function info
188 if (mContext->hasExportFunc()) {
189 if (mExportFuncMetadata == NULL)
190 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800191 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700192
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700193 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700194
zonr6315f762010-10-05 15:35:14 +0800195 for (RSContext::const_export_func_iterator
196 I = mContext->export_funcs_begin(),
197 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700198 I != E;
199 I++) {
zonr6315f762010-10-05 15:35:14 +0800200 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700201
202 // Function name
zonr6315f762010-10-05 15:35:14 +0800203 if (!EF->hasParam()) {
204 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
205 EF->getName().c_str()));
206 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800207 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700208 llvm::Function *HelperFunction;
209 const std::string HelperFunctionName(".helper_" + EF->getName());
210
211 assert(F && "Function marked as exported disappeared in Bitcode");
212
213 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700214 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800215 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700216
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800217 if (!F->getArgumentList().empty()) {
218 std::vector<const llvm::Type*> HelperFunctionParameterTys;
219 for (llvm::Function::arg_iterator AI = F->arg_begin(),
220 AE = F->arg_end(); AI != AE; AI++)
221 HelperFunctionParameterTys.push_back(AI->getType());
222
223 HelperFunctionParameterTy =
224 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
225 }
226
227 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
228 fprintf(stderr, "Failed to export function %s: parameter type "
229 "mismatch during creation of helper function.\n",
230 EF->getName().c_str());
231
232 const RSExportRecordType *Expected = EF->getParamPacketType();
233 if (Expected) {
234 fprintf(stderr, "Expected:\n");
235 Expected->getLLVMType()->dump();
236 }
237 if (HelperFunctionParameterTy) {
238 fprintf(stderr, "Got:\n");
239 HelperFunctionParameterTy->dump();
240 }
241 }
242
243 std::vector<const llvm::Type*> Params;
244 if (HelperFunctionParameterTy) {
245 llvm::PointerType *HelperFunctionParameterTyP =
246 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
247 Params.push_back(HelperFunctionParameterTyP);
248 }
249
250 llvm::FunctionType * HelperFunctionType =
251 llvm::FunctionType::get(F->getReturnType(),
252 Params,
253 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700254
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700255 HelperFunction =
256 llvm::Function::Create(HelperFunctionType,
257 llvm::GlobalValue::ExternalLinkage,
258 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800259 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700260
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700261 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
262 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700263
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700264 // Create helper function body
265 {
266 llvm::Argument *HelperFunctionParameter =
267 &(*HelperFunction->arg_begin());
268 llvm::BasicBlock *BB =
269 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
270 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
271 llvm::SmallVector<llvm::Value*, 6> Params;
272 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700273
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700274 Idx[0] =
275 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700276
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700277 // getelementptr and load instruction for all elements in
278 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800279 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700280 // getelementptr
281 Idx[1] =
282 llvm::ConstantInt::get(
283 llvm::Type::getInt32Ty(mLLVMContext), i);
284 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
285 Idx,
286 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700287
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700288 // load
289 llvm::Value *V = IB->CreateLoad(Ptr);
290 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700291 }
292
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700293 // Call and pass the all elements as paramter to F
294 llvm::CallInst *CI = IB->CreateCall(F,
295 Params.data(),
296 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700297
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700298 CI->setCallingConv(F->getCallingConv());
299
300 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
301 IB->CreateRetVoid();
302 else
303 IB->CreateRet(CI);
304
305 delete IB;
306 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700307 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700308
309 ExportFuncInfo.push_back(
310 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
311 }
312
313 mExportFuncMetadata->addOperand(
314 llvm::MDNode::get(mLLVMContext,
315 ExportFuncInfo.data(),
316 ExportFuncInfo.size()));
317
318 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700319 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700320 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700321
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700322 // Dump export type info
323 if (mContext->hasExportType()) {
324 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700325
zonr6315f762010-10-05 15:35:14 +0800326 for (RSContext::const_export_type_iterator
327 I = mContext->export_types_begin(),
328 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700329 I != E;
330 I++) {
331 // First, dump type name list to export
332 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700333
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700334 ExportTypeInfo.clear();
335 // Type name
336 ExportTypeInfo.push_back(
337 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700338
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700339 if (ET->getClass() == RSExportType::ExportClassRecord) {
340 const RSExportRecordType *ERT =
341 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700342
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700343 if (mExportTypeMetadata == NULL)
344 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800345 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700346
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700347 mExportTypeMetadata->addOperand(
348 llvm::MDNode::get(mLLVMContext,
349 ExportTypeInfo.data(),
350 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700351
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700352 // Now, export struct field information to %[struct name]
353 std::string StructInfoMetadataName("%");
354 StructInfoMetadataName.append(ET->getName());
355 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800356 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700357 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700358
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700359 assert(StructInfoMetadata->getNumOperands() == 0 &&
360 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800361 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
362 FE = ERT->fields_end();
363 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700364 FI++) {
365 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700366
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700367 // 1. field name
368 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
369 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700370
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700371 // 2. field type name
372 FieldInfo.push_back(
373 llvm::MDString::get(mLLVMContext,
374 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700375
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700376 // 3. field kind
377 switch (F->getType()->getClass()) {
378 case RSExportType::ExportClassPrimitive:
379 case RSExportType::ExportClassVector: {
380 const RSExportPrimitiveType *EPT =
381 static_cast<const RSExportPrimitiveType*>(F->getType());
382 FieldInfo.push_back(
383 llvm::MDString::get(mLLVMContext,
384 llvm::itostr(EPT->getKind())));
385 break;
386 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700387
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700388 default: {
389 FieldInfo.push_back(
390 llvm::MDString::get(mLLVMContext,
391 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800392 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700393 break;
394 }
395 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700396
zonr6315f762010-10-05 15:35:14 +0800397 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
398 FieldInfo.data(),
399 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700400
401 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700402 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700403 } // ET->getClass() == RSExportType::ExportClassRecord
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 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700408}
409
410RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700411 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700412}
Stephen Hinese639eb52010-11-08 19:27:20 -0800413
414} // namespace slang