blob: f59804c42de5e45668c30696b7057464d2fc6bef [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
19#include <vector>
20#include <string>
Shih-wei Liao462aefd2010-06-04 15:32:04 -070021
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070022#include "llvm/Metadata.h"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070023#include "llvm/Constant.h"
24#include "llvm/Constants.h"
25#include "llvm/Module.h"
26#include "llvm/Function.h"
27#include "llvm/DerivedTypes.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070028
zonr6315f762010-10-05 15:35:14 +080029#include "llvm/Support/IRBuilder.h"
30
31#include "llvm/ADT/Twine.h"
32#include "llvm/ADT/StringExtras.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"
Zonr Chang7f2f3852010-10-07 19:12:23 +080036#include "slang_rs_metadata.h"
zonr6315f762010-10-05 15:35:14 +080037#include "slang_rs_export_var.h"
38#include "slang_rs_export_func.h"
39#include "slang_rs_export_type.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070041using namespace slang;
42
43RSBackend::RSBackend(RSContext *Context,
44 clang::Diagnostic &Diags,
45 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 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++) {
83 clang::FunctionDecl *FD = dyn_cast<clang::FunctionDecl>(*I);
84 if (FD == NULL)
85 continue;
86 if (!FD->getName().startswith("rs")) // Check prefix
87 continue;
88 if (!SlangRS::IsFunctionInRSHeaderFile(FD, mSourceMgr))
89 mDiags.Report(clang::FullSourceLoc(FD->getLocation(), mSourceMgr),
90 mDiags.getCustomDiagID(clang::Diagnostic::Error,
91 "invalid function name prefix, "
92 "\"rs\" is reserved: '%0'"))
93 << FD->getName();
94 }
95 }
96
97 // Process any non-static function declarations
98 for (clang::DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; I++) {
99 AnnotateFunction(dyn_cast<clang::FunctionDecl>(*I));
100 }
101
102 Backend::HandleTopLevelDecl(D);
103 return;
104}
105
Stephen Hinesfcda2352010-10-19 16:49:32 -0700106void RSBackend::HandleTranslationUnitPre(clang::ASTContext& C) {
Stephen Hinesfcda2352010-10-19 16:49:32 -0700107 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
108
Stephen Hinescfae0f32010-11-01 18:57:31 -0700109 // Process any static function declarations
Stephen Hinesfcda2352010-10-19 16:49:32 -0700110 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
111 E = TUDecl->decls_end(); I != E; I++) {
112 if ((I->getKind() >= clang::Decl::firstFunction) &&
113 (I->getKind() <= clang::Decl::lastFunction)) {
Stephen Hinescfae0f32010-11-01 18:57:31 -0700114 AnnotateFunction(static_cast<clang::FunctionDecl*>(*I));
Stephen Hinesfcda2352010-10-19 16:49:32 -0700115 }
116 }
117
118 return;
119}
120
121///////////////////////////////////////////////////////////////////////////////
Zonr Chang68fc02c2010-10-13 19:09:19 +0800122void RSBackend::HandleTranslationUnitPost(llvm::Module *M) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700123 mContext->processExport();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700124
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700125 // Dump export variable info
126 if (mContext->hasExportVar()) {
127 if (mExportVarMetadata == NULL)
Zonr Chang68fc02c2010-10-13 19:09:19 +0800128 mExportVarMetadata = M->getOrInsertNamedMetadata(RS_EXPORT_VAR_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700129
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700130 llvm::SmallVector<llvm::Value*, 2> ExportVarInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700131
zonr6315f762010-10-05 15:35:14 +0800132 for (RSContext::const_export_var_iterator I = mContext->export_vars_begin(),
133 E = mContext->export_vars_end();
134 I != E;
135 I++) {
136 const RSExportVar *EV = *I;
137 const RSExportType *ET = EV->getType();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700138
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700139 // Variable name
140 ExportVarInfo.push_back(
141 llvm::MDString::get(mLLVMContext, EV->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700142
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700143 // Type name
Zonr Changa65ec162010-10-17 01:53:05 +0800144 switch (ET->getClass()) {
145 case RSExportType::ExportClassPrimitive: {
146 ExportVarInfo.push_back(
147 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700148 mLLVMContext, llvm::utostr_32(
Zonr Changa65ec162010-10-17 01:53:05 +0800149 static_cast<const RSExportPrimitiveType*>(ET)->getType())));
150 break;
151 }
152 case RSExportType::ExportClassPointer: {
153 ExportVarInfo.push_back(
154 llvm::MDString::get(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700155 mLLVMContext, ("*" + static_cast<const RSExportPointerType*>(ET)
Zonr Changa65ec162010-10-17 01:53:05 +0800156 ->getPointeeType()->getName()).c_str()));
157 break;
158 }
159 case RSExportType::ExportClassMatrix: {
160 ExportVarInfo.push_back(
161 llvm::MDString::get(
162 mLLVMContext, llvm::utostr_32(
163 RSExportPrimitiveType::DataTypeRSMatrix2x2 +
164 static_cast<const RSExportMatrixType*>(ET)->getDim() - 2)));
165 break;
166 }
167 case RSExportType::ExportClassVector:
168 case RSExportType::ExportClassConstantArray:
169 case RSExportType::ExportClassRecord: {
170 ExportVarInfo.push_back(
171 llvm::MDString::get(mLLVMContext,
172 EV->getType()->getName().c_str()));
173 break;
174 }
175 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700176
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700177 mExportVarMetadata->addOperand(
178 llvm::MDNode::get(mLLVMContext,
179 ExportVarInfo.data(),
180 ExportVarInfo.size()) );
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700181
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700182 ExportVarInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700183 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700184 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700185
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700186 // Dump export function info
187 if (mContext->hasExportFunc()) {
188 if (mExportFuncMetadata == NULL)
189 mExportFuncMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800190 M->getOrInsertNamedMetadata(RS_EXPORT_FUNC_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700191
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700192 llvm::SmallVector<llvm::Value*, 1> ExportFuncInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193
zonr6315f762010-10-05 15:35:14 +0800194 for (RSContext::const_export_func_iterator
195 I = mContext->export_funcs_begin(),
196 E = mContext->export_funcs_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197 I != E;
198 I++) {
zonr6315f762010-10-05 15:35:14 +0800199 const RSExportFunc *EF = *I;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700200
201 // Function name
zonr6315f762010-10-05 15:35:14 +0800202 if (!EF->hasParam()) {
203 ExportFuncInfo.push_back(llvm::MDString::get(mLLVMContext,
204 EF->getName().c_str()));
205 } else {
Zonr Chang68fc02c2010-10-13 19:09:19 +0800206 llvm::Function *F = M->getFunction(EF->getName());
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700207 llvm::Function *HelperFunction;
208 const std::string HelperFunctionName(".helper_" + EF->getName());
209
210 assert(F && "Function marked as exported disappeared in Bitcode");
211
212 // Create helper function
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700213 {
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800214 llvm::StructType *HelperFunctionParameterTy = NULL;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700215
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800216 if (!F->getArgumentList().empty()) {
217 std::vector<const llvm::Type*> HelperFunctionParameterTys;
218 for (llvm::Function::arg_iterator AI = F->arg_begin(),
219 AE = F->arg_end(); AI != AE; AI++)
220 HelperFunctionParameterTys.push_back(AI->getType());
221
222 HelperFunctionParameterTy =
223 llvm::StructType::get(mLLVMContext, HelperFunctionParameterTys);
224 }
225
226 if (!EF->checkParameterPacketType(HelperFunctionParameterTy)) {
227 fprintf(stderr, "Failed to export function %s: parameter type "
228 "mismatch during creation of helper function.\n",
229 EF->getName().c_str());
230
231 const RSExportRecordType *Expected = EF->getParamPacketType();
232 if (Expected) {
233 fprintf(stderr, "Expected:\n");
234 Expected->getLLVMType()->dump();
235 }
236 if (HelperFunctionParameterTy) {
237 fprintf(stderr, "Got:\n");
238 HelperFunctionParameterTy->dump();
239 }
240 }
241
242 std::vector<const llvm::Type*> Params;
243 if (HelperFunctionParameterTy) {
244 llvm::PointerType *HelperFunctionParameterTyP =
245 llvm::PointerType::getUnqual(HelperFunctionParameterTy);
246 Params.push_back(HelperFunctionParameterTyP);
247 }
248
249 llvm::FunctionType * HelperFunctionType =
250 llvm::FunctionType::get(F->getReturnType(),
251 Params,
252 /* IsVarArgs = */false);
Shih-wei Liaocecd11d2010-09-21 08:07:58 -0700253
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700254 HelperFunction =
255 llvm::Function::Create(HelperFunctionType,
256 llvm::GlobalValue::ExternalLinkage,
257 HelperFunctionName,
Zonr Chang68fc02c2010-10-13 19:09:19 +0800258 M);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700259
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700260 HelperFunction->addFnAttr(llvm::Attribute::NoInline);
261 HelperFunction->setCallingConv(F->getCallingConv());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700262
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700263 // Create helper function body
264 {
265 llvm::Argument *HelperFunctionParameter =
266 &(*HelperFunction->arg_begin());
267 llvm::BasicBlock *BB =
268 llvm::BasicBlock::Create(mLLVMContext, "entry", HelperFunction);
269 llvm::IRBuilder<> *IB = new llvm::IRBuilder<>(BB);
270 llvm::SmallVector<llvm::Value*, 6> Params;
271 llvm::Value *Idx[2];
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700272
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700273 Idx[0] =
274 llvm::ConstantInt::get(llvm::Type::getInt32Ty(mLLVMContext), 0);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700275
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700276 // getelementptr and load instruction for all elements in
277 // parameter .p
Zonr Chang0da0a7d2010-10-05 21:26:37 +0800278 for (size_t i = 0; i < EF->getNumParameters(); i++) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700279 // getelementptr
280 Idx[1] =
281 llvm::ConstantInt::get(
282 llvm::Type::getInt32Ty(mLLVMContext), i);
283 llvm::Value *Ptr = IB->CreateInBoundsGEP(HelperFunctionParameter,
284 Idx,
285 Idx + 2);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700286
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700287 // load
288 llvm::Value *V = IB->CreateLoad(Ptr);
289 Params.push_back(V);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700290 }
291
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700292 // Call and pass the all elements as paramter to F
293 llvm::CallInst *CI = IB->CreateCall(F,
294 Params.data(),
295 Params.data() + Params.size());
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700296
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700297 CI->setCallingConv(F->getCallingConv());
298
299 if (F->getReturnType() == llvm::Type::getVoidTy(mLLVMContext))
300 IB->CreateRetVoid();
301 else
302 IB->CreateRet(CI);
303
304 delete IB;
305 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700306 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700307
308 ExportFuncInfo.push_back(
309 llvm::MDString::get(mLLVMContext, HelperFunctionName.c_str()));
310 }
311
312 mExportFuncMetadata->addOperand(
313 llvm::MDNode::get(mLLVMContext,
314 ExportFuncInfo.data(),
315 ExportFuncInfo.size()));
316
317 ExportFuncInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700318 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700319 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700320
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700321 // Dump export type info
322 if (mContext->hasExportType()) {
323 llvm::SmallVector<llvm::Value*, 1> ExportTypeInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700324
zonr6315f762010-10-05 15:35:14 +0800325 for (RSContext::const_export_type_iterator
326 I = mContext->export_types_begin(),
327 E = mContext->export_types_end();
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700328 I != E;
329 I++) {
330 // First, dump type name list to export
331 const RSExportType *ET = I->getValue();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700332
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700333 ExportTypeInfo.clear();
334 // Type name
335 ExportTypeInfo.push_back(
336 llvm::MDString::get(mLLVMContext, ET->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700337
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700338 if (ET->getClass() == RSExportType::ExportClassRecord) {
339 const RSExportRecordType *ERT =
340 static_cast<const RSExportRecordType*>(ET);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700341
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700342 if (mExportTypeMetadata == NULL)
343 mExportTypeMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800344 M->getOrInsertNamedMetadata(RS_EXPORT_TYPE_MN);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700345
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700346 mExportTypeMetadata->addOperand(
347 llvm::MDNode::get(mLLVMContext,
348 ExportTypeInfo.data(),
349 ExportTypeInfo.size()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700350
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700351 // Now, export struct field information to %[struct name]
352 std::string StructInfoMetadataName("%");
353 StructInfoMetadataName.append(ET->getName());
354 llvm::NamedMDNode *StructInfoMetadata =
Zonr Chang68fc02c2010-10-13 19:09:19 +0800355 M->getOrInsertNamedMetadata(StructInfoMetadataName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700356 llvm::SmallVector<llvm::Value*, 3> FieldInfo;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700357
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700358 assert(StructInfoMetadata->getNumOperands() == 0 &&
359 "Metadata with same name was created before");
zonr6315f762010-10-05 15:35:14 +0800360 for (RSExportRecordType::const_field_iterator FI = ERT->fields_begin(),
361 FE = ERT->fields_end();
362 FI != FE;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700363 FI++) {
364 const RSExportRecordType::Field *F = *FI;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700365
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700366 // 1. field name
367 FieldInfo.push_back(llvm::MDString::get(mLLVMContext,
368 F->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700369
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700370 // 2. field type name
371 FieldInfo.push_back(
372 llvm::MDString::get(mLLVMContext,
373 F->getType()->getName().c_str()));
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700374
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700375 // 3. field kind
376 switch (F->getType()->getClass()) {
377 case RSExportType::ExportClassPrimitive:
378 case RSExportType::ExportClassVector: {
379 const RSExportPrimitiveType *EPT =
380 static_cast<const RSExportPrimitiveType*>(F->getType());
381 FieldInfo.push_back(
382 llvm::MDString::get(mLLVMContext,
383 llvm::itostr(EPT->getKind())));
384 break;
385 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700386
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700387 default: {
388 FieldInfo.push_back(
389 llvm::MDString::get(mLLVMContext,
390 llvm::itostr(
zonr6315f762010-10-05 15:35:14 +0800391 RSExportPrimitiveType::DataKindUser)));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700392 break;
393 }
394 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700395
zonr6315f762010-10-05 15:35:14 +0800396 StructInfoMetadata->addOperand(llvm::MDNode::get(mLLVMContext,
397 FieldInfo.data(),
398 FieldInfo.size()));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700399
400 FieldInfo.clear();
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700401 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700402 } // ET->getClass() == RSExportType::ExportClassRecord
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700403 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700404 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700405
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700406 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700407}
408
409RSBackend::~RSBackend() {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700410 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700411}